From d73a161e84d895989485a6c9d47ee00d23d7ae1d Mon Sep 17 00:00:00 2001 From: DiheChen Date: Mon, 9 Nov 2026 21:32:21 +0800 Subject: [PATCH] feat: browse my playlists as a sortable list or a glowing cover grid and open each one --- web/src/app/app.tsx | 61 +++-- web/src/features/playlists/index.ts | 4 + .../features/playlists/my-playlist-page.tsx | 175 ++++++++++++++ web/src/features/playlists/playlist-cover.tsx | 3 + .../features/playlists/playlist-date.test.ts | 35 +++ web/src/features/playlists/playlist-date.ts | 20 ++ web/src/features/playlists/playlist-menu.tsx | 177 ++++++++++++++ web/src/features/playlists/playlist-sort.ts | 8 + web/src/features/playlists/playlists-page.tsx | 220 ++++++++++++++++++ web/src/features/playlists/playlists.css | 103 ++++++++ .../playlists/view-preference.test.ts | 49 ++++ web/src/features/playlists/view-preference.ts | 42 ++++ web/src/shared/ui/theme.css | 3 + web/src/shared/ui/ui.css | 1 + 14 files changed, 881 insertions(+), 20 deletions(-) create mode 100644 web/src/features/playlists/my-playlist-page.tsx create mode 100644 web/src/features/playlists/playlist-date.test.ts create mode 100644 web/src/features/playlists/playlist-date.ts create mode 100644 web/src/features/playlists/playlist-menu.tsx create mode 100644 web/src/features/playlists/playlists-page.tsx create mode 100644 web/src/features/playlists/view-preference.test.ts create mode 100644 web/src/features/playlists/view-preference.ts diff --git a/web/src/app/app.tsx b/web/src/app/app.tsx index d115ede..1f9c756 100644 --- a/web/src/app/app.tsx +++ b/web/src/app/app.tsx @@ -1,13 +1,14 @@ import type { LucideIcon } from 'lucide-react' import type { Page, Panel, RoomPage } from './route' import type { SearchQuery } from '@/features/search' -import { ChevronLeft, ChevronRight, Headphones, History, House, ListMusic, MessageCircle, MoreHorizontal, Search, Settings, Share2, UserRound, Wifi, WifiOff, X } from 'lucide-react' +import { ChevronLeft, ChevronRight, Headphones, History, House, Library, ListMusic, MessageCircle, MoreHorizontal, Search, Settings, Share2, UserRound, Wifi, WifiOff, X } from 'lucide-react' import { Suspense } from 'react' import { roomStore } from '@/core/room' import { ChatPanel } from '@/features/chat' import { HistoryPage } from '@/features/history' import { ListenPage } from '@/features/lyrics' import { AudioEngine, ManualStartPrompt, PlayerBar, playerStore } from '@/features/playback' +import { MyPlaylistPage, PlaylistsPage } from '@/features/playlists' import { QueuePage, voteSkip } from '@/features/queue' import { copyInviteLink, EntryDialog, Lobby, roomEntryStore, RoomGate } from '@/features/rooms' import { HeaderSearch, PlaylistPage, SearchPage, searchStore } from '@/features/search' @@ -29,11 +30,12 @@ const AdminPage = lazyPage(() => import('@/features/admin').then((module) => { const pageLoading =
-const menu: { page: 'lobby' | 'settings' | 'history' | RoomPage, label: string, icon: LucideIcon }[] = [ +const menu: { page: 'lobby' | 'settings' | 'history' | 'playlists' | RoomPage, label: string, icon: LucideIcon }[] = [ { page: 'listen', label: '正在聆听', icon: Headphones }, { page: 'queue', label: '播放列表', icon: ListMusic }, { page: 'chat', label: '房间聊天', icon: MessageCircle }, { page: 'history', label: '播放历史', icon: History }, + { page: 'playlists', label: '我的歌单', icon: Library }, { page: 'lobby', label: '发现房间', icon: House }, { page: 'settings', label: '设置', icon: Settings }, ] @@ -45,9 +47,11 @@ const mobileMenu: { page: RoomPage, label: string, icon: LucideIcon }[] = [ ] const pageClasses: Partial> = { - queue: 'scrollbar-hidden', - history: 'scrollbar-hidden', - settings: 'settings-view', + 'queue': 'scrollbar-hidden', + 'history': 'scrollbar-hidden', + 'playlists': 'scrollbar-hidden', + 'my-playlist': 'scrollbar-hidden', + 'settings': 'settings-view', } function closeMenu(element: HTMLElement): void { @@ -112,21 +116,24 @@ function Header({ page }: { page: Page }) {