From c4c227d33ea6f4737bcdb65a4de2863e9407f63b Mon Sep 17 00:00:00 2001
From: SimonShiki <sinangentoo@gmail.com>
Date: Sun, 11 Aug 2024 09:35:53 +0800
Subject: [PATCH] :bug: fix: ncm signin issue

Signed-off-by: SimonShiki <sinangentoo@gmail.com>
---
 src/components/base/pagination.tsx | 10 +++----
 src/components/songlist-item.tsx   |  2 +-
 src/jotais/settings.ts             |  1 -
 src/pages/ncm.tsx                  | 46 ++++++++++++++++++++++--------
 src/storages/ncm.ts                |  9 ++++--
 5 files changed, 46 insertions(+), 22 deletions(-)

diff --git a/src/components/base/pagination.tsx b/src/components/base/pagination.tsx
index 2841d36..8a87295 100644
--- a/src/components/base/pagination.tsx
+++ b/src/components/base/pagination.tsx
@@ -56,7 +56,7 @@ export default function Pagination ({ currentPage, totalPages, onPageChange, siz
                     onPageChange(pageNumber);
                 }
             }}
-            className={size === 'md' ? 'px-4 h-10' : 'px-2 h-6'}
+            className={size === 'md' ? 'px-3 h-8' : 'px-2 h-6'}
             iconOnly
         >
             {pageNumber}
@@ -72,10 +72,10 @@ export default function Pagination ({ currentPage, totalPages, onPageChange, siz
             <Button
                 onClick={() => onPageChange(Math.max(1, currentPage - 1))}
                 disabled={currentPage === 1}
-                className={`${size === 'md' ? 'w-10 h-10' : 'w-6 h-6'} group flex justify-center items-center`}
+                className={`${size === 'md' ? 'w-8 h-8' : 'w-6 h-6'} group flex justify-center items-center`}
                 iconOnly
             >
-                <span className={`i-ph:caret-left-bold ${size === 'md' ? 'w-4 h-4' : 'w-3 h-3'} color-text-pri group-disabled:color-outline-sec dark:color-text-dark-pri dark:group-disabled:color-outline-dark-sec`} />
+                <span className={`i-fluent:chevron-left-16-regular ${size === 'md' ? 'w-4 h-4' : 'w-3 h-3'} color-text-pri group-disabled:color-outline-sec dark:color-text-dark-pri dark:group-disabled:color-outline-dark-sec`} />
             </Button>
 
             {renderPageNumbers()}
@@ -83,10 +83,10 @@ export default function Pagination ({ currentPage, totalPages, onPageChange, siz
             <Button
                 onClick={() => onPageChange(Math.min(totalPages, currentPage + 1))}
                 disabled={currentPage === totalPages}
-                className={`${size === 'md' ? 'w-10 h-10' : 'w-6 h-6'} group flex justify-center items-center`}
+                className={`${size === 'md' ? 'w-8 h-8' : 'w-6 h-6'} group flex justify-center items-center`}
                 iconOnly
             >
-                <span className={`i-ph:caret-right-bold ${size === 'md' ? 'w-4 h-4' : 'w-3 h-3'} color-text-pri group-disabled:color-outline-sec dark:color-text-dark-pri dark:group-disabled:color-outline-dark-sec`} />
+                <span className={`i-fluent:chevron-right-16-regular ${size === 'md' ? 'w-4 h-4' : 'w-3 h-3'} color-text-pri group-disabled:color-outline-sec dark:color-text-dark-pri dark:group-disabled:color-outline-dark-sec`} />
             </Button>
         </div>
     );
diff --git a/src/components/songlist-item.tsx b/src/components/songlist-item.tsx
index efce842..28c4fda 100644
--- a/src/components/songlist-item.tsx
+++ b/src/components/songlist-item.tsx
@@ -15,7 +15,7 @@ export default function SonglistItem (props: SonglistItemProps) {
     return (
         <Card onDoubleClick={() => {
             props.onClick?.(props.id, props.index);
-        }} className={`flex flex-row items-center py-2 gap-2 hover:!bg-black cursor-pointer hover:!bg-op-5 transition-colors ${props.hideBg ? '!border-none !bg-transparent' : ''}`}>
+        }} className={`flex flex-row items-center active:scale-99 py-2 gap-2 hover:!bg-black cursor-pointer hover:!bg-op-5 transition-all ${props.hideBg ? '!border-none !bg-transparent' : ''}`}>
             <img draggable={false} src={props.cover ?? defaultCover} alt={props.name} className='rounded-md w-10 h-10' />
             <span className='color-text-pri font-size-sm font-500'>{props.name}</span>
         </Card>
diff --git a/src/jotais/settings.ts b/src/jotais/settings.ts
index 668b881..66e6a29 100644
--- a/src/jotais/settings.ts
+++ b/src/jotais/settings.ts
@@ -1,6 +1,5 @@
 import { focusAtom } from 'jotai-optics';
 import { atomWithStorage } from 'jotai/utils';
-import sharedStore from './shared-store';
 
 export interface StorageConfig<Idenfiter extends string> {
     identifer: Idenfiter;
diff --git a/src/pages/ncm.tsx b/src/pages/ncm.tsx
index 1a10f42..fa1785f 100644
--- a/src/pages/ncm.tsx
+++ b/src/pages/ncm.tsx
@@ -13,6 +13,7 @@ import Spinner from '../components/base/spinner';
 import Button from '../components/base/button';
 import SonglistItem from '../components/songlist-item';
 import { FormattedMessage, useIntl } from 'react-intl';
+import Pagination from '../components/base/pagination';
 
 interface NCMProfile {
     nickname: string;
@@ -36,6 +37,9 @@ export default function NCM () {
     const [searchPage, setSearchPage] = useState(1);
     const [showSonglist, setShowSonglist] = useState<string | number | null>(null);
     const [songlistName, setSonglistName] = useState('');
+    const [songlistTotalPage, setSonglistTotalPage] = useState(0);
+    const [songlistPage, setSonglistPage] = useState(0);
+
     const [songlistDetail, setSonglistDetail] = useState<AbstractSong<'ncm'>[]>([]);
     const [isSearching, setIsSearching] = useState(false);
 
@@ -68,6 +72,18 @@ export default function NCM () {
         updateSearchResult();
     }, [isSearching, searchText, ncmInstance]);
 
+    useEffect(() => {
+        if (!showSonglist || !songlistPage) return;
+        ncmInstance.getRemoteSonglistDetail(showSonglist as number, 10, songlistPage).then((detail) => {
+            setSonglistDetail(detail);
+        });
+    }, [songlistPage]);
+
+    useEffect(() => {
+        if (showSonglist) return;
+        setSonglistPage(0);
+    }, [showSonglist]);
+
     const handleClickSong = useCallback((song: AbstractSong<'ncm'>, playlist: AbstractSong<'ncm'>[]) => {
         player.clearPlaylist();
         player.addToPlaylist(...playlist);
@@ -87,7 +103,9 @@ export default function NCM () {
     const handleClickRemoteSonglist = useCallback(async (id: string | number, index: number) => {
         setShowSonglist(id);
         setSonglistName(songlist[index].name);
-        setSonglistDetail(await ncmInstance.getRemoteSonglistDetail(id));
+        setSonglistDetail([]);
+        setSonglistPage(1);
+        setSonglistTotalPage(Math.ceil(songlist[index].trackCount / 10));
     }, [songlist, ncmInstance]);
 
     const intl = useIntl();
@@ -205,17 +223,21 @@ export default function NCM () {
                         </span>
                     </Button>
                 </div>
-                <Virtuoso
-                    className="flex-1"
-                    totalCount={barOpen ? songlistDetail.length + 1 : songlistDetail.length}
-                    itemContent={(index) => {
-                        if (index === songlistDetail.length) {
-                            return <div className="h-20" />;
-                        }
-                        const song = songlistDetail[index];
-                        return <SongItem song={song} onClick={() => handleClickSong(song, songlistDetail)} hideBg={!(index % 2)} />;
-                    }}
-                />
+                {songlistDetail.length > 0 ? (
+                    <Virtuoso
+                        className="flex-1"
+                        totalCount={songlistDetail.length}
+                        itemContent={(index) => {
+                            const song = songlistDetail[index];
+                            return <SongItem song={song} onClick={() => handleClickSong(song, songlistDetail)} hideBg={!(index % 2)} />;
+                        }}
+                    />
+                ) : (
+                    <div className='w-full h-full flex justify-center items-center'>
+                        <Spinner />
+                    </div>
+                )}
+                <Pagination totalPages={songlistTotalPage} className={`mx-auto ${barOpen ? 'mb-20' : ''}`} currentPage={songlistPage} onPageChange={setSonglistPage} />
             </div>
         );
     }
diff --git a/src/storages/ncm.ts b/src/storages/ncm.ts
index b200af6..d7dc90b 100644
--- a/src/storages/ncm.ts
+++ b/src/storages/ncm.ts
@@ -255,9 +255,9 @@ export class NCM implements AbstractStorage {
     }
 
     private initListener () {
-        const ncmConfig = sharedStore.get(this.ncmStorageConfigJotai) as NCMConfig;
         const loggedInJotai = focusAtom(this.ncmStorageConfigJotai, (optic) => optic.prop('loggedIn'));
         sharedStore.sub(loggedInJotai, async () => {
+            const ncmConfig = sharedStore.get(this.ncmStorageConfigJotai) as NCMConfig;
             const loggedIn = sharedStore.get(loggedInJotai);
             if (loggedIn) {
                 const { userId } = await this.getProfile();
@@ -390,8 +390,11 @@ export class NCM implements AbstractStorage {
     async getRemoteSonglistDetail (id: string | number, limit = 10, page = 1) {
         const offset = (page - 1) * limit;
         const res = await fetch(`${this.config.api}playlist/track/all?id=${id}&limit=${limit}&offset=${offset}${this.config.cookie ? `&cookie=${this.config.cookie}` : ''}`);
-        const { songs } = await res.json();
-        const mappedList: Song<'ncm'>[] = (songs as NCMSonglistTrack[]).map(song => ({
+        const data = await res.json();
+        if (!data.songs) {
+            console.error(data);
+        }
+        const mappedList: Song<'ncm'>[] = (data.songs as NCMSonglistTrack[]).map(song => ({
             id: song.id,
             name: song.name,
             cover: song.al.picUrl,