diff --git a/src/renderer/api/user.ts b/src/renderer/api/user.ts index 9187caa..3314d0c 100644 --- a/src/renderer/api/user.ts +++ b/src/renderer/api/user.ts @@ -4,6 +4,8 @@ export enum UserApiNames { FETCH_USER_ACCOUNT = 'fetchUserAccount', FETCH_USER_LIKED_TRACKS_IDS = 'fetchUserLikedTracksIDs', FETCH_USER_PLAYLISTS = 'fetchUserPlaylists', + FETCH_USER_ALBUMS = 'fetchUserAlbums', + FETCH_USER_ARTIST = 'fetchUserArtists', } /** @@ -99,7 +101,7 @@ export interface FetchUserPlaylistsParams { } export interface FetchUserPlaylistsResponse { code: number - more: false + more: boolean version: string playlist: Playlist[] } @@ -151,40 +153,44 @@ export function dailySignin(type = 0) { }) } -/** - * 获取收藏的专辑(需要登录) - * 说明 : 调用此接口可获取到用户收藏的专辑 - * - limit : 返回数量 , 默认为 25 - * - offset : 偏移数量,用于分页 , 如 :( 页数 -1)*25, 其中 25 为 limit 的值 , 默认为 0 - * @param {Object} params - * @param {number} params.limit - * @param {number=} params.offset - */ -// export function likedAlbums(params) { -// return request({ -// url: '/album/sublist', -// method: 'get', -// params: { -// limit: params.limit, -// timestamp: new Date().getTime(), -// }, -// }) -// } +export interface FetchUserAlbumsParams { + offset?: number // default 0 + limit?: number // default 25 +} +export interface FetchUserAlbumsResponse { + code: number + hasMore: boolean + paidCount: number + count: number + data: Album[] +} +export function fetchUserAlbums(params: FetchUserAlbumsParams) { + return request({ + url: '/album/sublist', + method: 'get', + params: { + ...params, + timestamp: new Date().getTime(), + }, + }) +} -/** - * 获取收藏的歌手(需要登录) - * 说明 : 调用此接口可获取到用户收藏的歌手 - */ -// export function likedArtists(params) { -// return request({ -// url: '/artist/sublist', -// method: 'get', -// params: { -// limit: params.limit, -// timestamp: new Date().getTime(), -// }, -// }) -// } +// 获取收藏的歌手 +export interface FetchUserArtistsResponse { + code: number + hasMore: boolean + count: number + data: Artist[] +} +export function fetchUserArtists(): Promise { + return request({ + url: '/artist/sublist', + method: 'get', + params: { + timestamp: new Date().getTime(), + }, + }) +} /** * 获取收藏的MV(需要登录) diff --git a/src/renderer/components/Cover.tsx b/src/renderer/components/Cover.tsx index 7b65396..dc92195 100644 --- a/src/renderer/components/Cover.tsx +++ b/src/renderer/components/Cover.tsx @@ -21,7 +21,7 @@ const Cover = ({ {showHover && (
{ const nickname = 'creator' in item ? item.creator.nickname : 'someone' - const artist = 'artist' in item ? item.artist.name : 'unknown' + const artist = + 'artist' in item + ? item.artist.name + : 'artists' in item + ? item.artists?.[0]?.name + : 'unknown' const copywriter = 'copywriter' in item ? item.copywriter : 'unknown' const releaseYear = ('publishTime' in item && @@ -125,10 +130,10 @@ const CoverRow = ({
{renderItems.map((item, index) => ( @@ -146,6 +151,7 @@ const CoverRow = ({ onClick={() => goTo(item.id)} imageUrl={getImageUrl(item)} showPlayButton={true} + roundedClass={artists ? 'rounded-full' : 'rounded-xl'} /> )} @@ -163,9 +169,14 @@ const CoverRow = ({
) : ( - + {/* Playlist private icon */} - {(item as Playlist).privacy && ( + {(item as Playlist).privacy === 10 && ( ) : ( -
- {getSubtitleText(item, subtitle)} -
+ !artists && ( +
+ {getSubtitleText(item, subtitle)} +
+ ) )}
diff --git a/src/renderer/hooks/useUserAlbums.ts b/src/renderer/hooks/useUserAlbums.ts new file mode 100644 index 0000000..00d4df3 --- /dev/null +++ b/src/renderer/hooks/useUserAlbums.ts @@ -0,0 +1,16 @@ +import type { FetchUserAlbumsParams, FetchUserAlbumsResponse } from '@/api/user' +import { UserApiNames, fetchUserAlbums } from '@/api/user' + +export default function useUserAlbums(params: FetchUserAlbumsParams) { + return useQuery( + [UserApiNames.FETCH_USER_ALBUMS, params], + () => fetchUserAlbums(params), + { + placeholderData: (): FetchUserAlbumsResponse => + window.ipcRenderer?.sendSync('getApiCacheSync', { + api: 'album/sublist', + query: params, + }), + } + ) +} diff --git a/src/renderer/hooks/useUserArtists.ts b/src/renderer/hooks/useUserArtists.ts new file mode 100644 index 0000000..acf3d58 --- /dev/null +++ b/src/renderer/hooks/useUserArtists.ts @@ -0,0 +1,11 @@ +import type { FetchUserArtistsResponse } from '@/api/user' +import { UserApiNames, fetchUserArtists } from '@/api/user' + +export default function useUserArtists() { + return useQuery([UserApiNames.FETCH_USER_ARTIST], fetchUserArtists, { + placeholderData: (): FetchUserArtistsResponse => + window.ipcRenderer?.sendSync('getApiCacheSync', { + api: 'album/sublist', + }), + }) +} diff --git a/src/renderer/pages/Library.tsx b/src/renderer/pages/Library.tsx index 6f835c4..eb45df1 100644 --- a/src/renderer/pages/Library.tsx +++ b/src/renderer/pages/Library.tsx @@ -1,4 +1,6 @@ +import CoverRow, { Subtitle } from '@/components/CoverRow' import SvgIcon from '@/components/SvgIcon' +import useUserAlbums from '@/hooks/useUserAlbums' import useLyric from '@/hooks/useLyric' import usePlaylist from '@/hooks/usePlaylist' import useUser from '@/hooks/useUser' @@ -6,6 +8,7 @@ import useUserPlaylists from '@/hooks/useUserPlaylists' import { player } from '@/store' import { resizeImage } from '@/utils/common' import { sample, chunk } from 'lodash-es' +import useUserArtists from '@/hooks/useUserArtists' const LikedTracksCard = ({ className }: { className?: string }) => { const navigate = useNavigate() @@ -122,8 +125,116 @@ const OtherCard = ({ ) } +const Playlists = () => { + const { data: user } = useUser() + + const { data: playlists } = useUserPlaylists({ + uid: user?.account?.id ?? 0, + offset: 0, + }) + return ( +
+ +
+ ) +} + +const Albums = () => { + const { data: albums } = useUserAlbums({ + limit: 1000, + }) + + return ( +
+ +
+ ) +} + +const Artists = () => { + const { data: artists } = useUserArtists() + + return ( +
+ +
+ ) +} + +const MVs = () => { + return
施工中
+} + +const Podcasts = () => { + return
施工中
+} +interface TabsType { + playlist: string + album: string + artist: string + mv: string + podcast: string +} + +const TabHeader = ({ + activeTab, + tabs, + setActiveTab, +}: { + activeTab: keyof TabsType + tabs: TabsType + setActiveTab: (tab: keyof TabsType) => void +}) => { + return ( +
+ {Object.entries(tabs).map(([id, name]) => ( +
setActiveTab(id as keyof TabsType)} + className={classNames( + 'btn-pressed-animation mr-3 rounded-lg px-3.5 py-1.5 font-medium', + activeTab === id + ? 'bg-black/[.04]' + : 'btn-hover-animation after:bg-black/[.04] dark:after:bg-white/10' + )} + > + {name} +
+ ))} +
+ ) +} + const Tabs = () => { - return
+ const tabs = { + playlist: '全部歌单', + album: '专辑', + artist: '艺人', + mv: 'MV', + podcast: '播客', + } + + const [activeTab, setActiveTab] = useState('playlist') + + return ( + <> + +
+ {activeTab === 'playlist' && } + {activeTab === 'album' && } + {activeTab === 'artist' && } + {activeTab === 'mv' && } + {activeTab === 'podcast' && } +
+ + ) } const Library = () => { @@ -148,6 +259,8 @@ const Library = () => { + + ) }