diff --git a/web/src/features/history/history-page.tsx b/web/src/features/history/history-page.tsx index 245d0c6..c0dcf39 100644 --- a/web/src/features/history/history-page.tsx +++ b/web/src/features/history/history-page.tsx @@ -2,6 +2,7 @@ import type { PlayRecord } from './records' import { CirclePlus, Download, History, Search, Trash2 } from 'lucide-react' import { useState } from 'react' import { roomStore, sameTrack } from '@/core/room' +import { SaveToPlaylistButton } from '@/features/playlists' import { enqueue, sourceName } from '@/features/queue' import { bookTitle } from '@/shared/lib/book-title' import { formatClock } from '@/shared/lib/time' @@ -46,6 +47,7 @@ function HistoryRow({ record, compact, connected, playing }: { record: PlayRecor await enqueue(record.track) }} /> +
+ {nowPlaying && } volumeStore.setMuted(!muted)} />
void, onCancel: () => void }) { + const [name, setName] = useState('') + const [saving, setSaving] = useState(false) + return ( +
{ + if (event.key !== 'Escape' || event.nativeEvent.isComposing) + return + // 拦下对话框的 Esc:在“保存到歌单”里,Esc 只回到列表。 + event.preventDefault() + onCancel() + }} + onSubmit={async (event) => { + event.preventDefault() + if (saving) + return + setSaving(true) + const playlist = await playlistsStore.create(name) + if (playlist) + onCreated(playlist) + else + setSaving(false) + }} + > + +
+ + +
+
+ ) +} diff --git a/web/src/features/playlists/index.ts b/web/src/features/playlists/index.ts index 277bca5..5d028a4 100644 --- a/web/src/features/playlists/index.ts +++ b/web/src/features/playlists/index.ts @@ -1 +1,3 @@ export { playlistsStore } from './playlists-store' +export { saveToPlaylistLabel } from './save-label' +export { SaveToPlaylistButton, SaveToPlaylistDialog } from './save-to-playlist' diff --git a/web/src/features/playlists/playlist-cover.tsx b/web/src/features/playlists/playlist-cover.tsx new file mode 100644 index 0000000..f967936 --- /dev/null +++ b/web/src/features/playlists/playlist-cover.tsx @@ -0,0 +1,26 @@ +import { Music2, Star } from 'lucide-react' +import { useState } from 'react' + +export function FavoritesMark({ size = 14 }: { size?: number }) { + return