mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
d5bbabac1d
Extract the queue UI (QueuePanel + queuePanel/* components + useQueue* hooks)
into features/queue/ with a barrel. This is the chosen playback/queue boundary:
queue = the QueuePanel UI that CONSUMES the playback store; queue STATE and the
audio engine stay in store/ (playback-core, moved separately). Verified
one-way: no playback-core file imports the queue UI back (only doc comments
mention it).
Excluded as NOT queue-UI: useIdlePlayQueuePull (AppShell) and
usePlayQueueSyncLedState (ConnectionIndicator) are queue-SYNC orchestration,
not panel UI — left in hooks/ to move with playback.
Pure move. One test fix: QueuePanel.test.tsx reads its subject via a hardcoded
readFileSync('src/components/QueuePanel.tsx') path (architecture-pin grep for
forbidden HTML5 DnD) — repointed to the new location (the move tool can't
rewrite non-import string paths). tsc 0, lint 0/0, suite 319/2353 green.
42 lines
1.1 KiB
TypeScript
42 lines
1.1 KiB
TypeScript
import { Info, ListMusic, MicVocal } from 'lucide-react';
|
|
import type { TFunction } from 'i18next';
|
|
|
|
type LyricsTab = 'queue' | 'lyrics' | 'info';
|
|
|
|
interface Props {
|
|
activeTab: LyricsTab;
|
|
setTab: (tab: LyricsTab) => void;
|
|
t: TFunction;
|
|
}
|
|
|
|
export function QueueTabBar({ activeTab, setTab, t }: Props) {
|
|
return (
|
|
<div className="queue-tab-bar">
|
|
<button
|
|
className={`queue-tab-btn${activeTab === 'queue' ? ' active' : ''}`}
|
|
onClick={() => setTab('queue')}
|
|
aria-label={t('queue.title')}
|
|
>
|
|
<ListMusic size={14} />
|
|
{t('queue.title')}
|
|
</button>
|
|
<button
|
|
className={`queue-tab-btn${activeTab === 'lyrics' ? ' active' : ''}`}
|
|
onClick={() => setTab('lyrics')}
|
|
aria-label={t('player.lyrics')}
|
|
>
|
|
<MicVocal size={14} />
|
|
{t('player.lyrics')}
|
|
</button>
|
|
<button
|
|
className={`queue-tab-btn${activeTab === 'info' ? ' active' : ''}`}
|
|
onClick={() => setTab('info')}
|
|
aria-label={t('nowPlayingInfo.tab')}
|
|
>
|
|
<Info size={14} />
|
|
{t('nowPlayingInfo.tab')}
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|