mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +00:00
feat(queue): switchable queue display mode (Queue vs Playlist) (#922)
* feat(queue): add queueDisplayMode setting with rehydrate (default queue) * feat(queue): render upcoming-only or full timeline by mode, with header toggle * feat(settings): add queue display mode toggle to Personalisation * i18n: queue display mode strings across all locales * test(queue): display-mode rendering and absolute index mapping * docs: changelog + credits for queue display mode (#922)
This commit is contained in:
committed by
GitHub
parent
7b06be5ba2
commit
1de2b0e850
@@ -1,6 +1,7 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Disc3, LayoutGrid, ListMusic, ListTodo, PanelLeft, RotateCcw, Users } from 'lucide-react';
|
||||
import { Disc3, LayoutGrid, ListMusic, ListOrdered, ListTodo, PanelLeft, RotateCcw, Users } from 'lucide-react';
|
||||
import { useArtistLayoutStore } from '../../store/artistLayoutStore';
|
||||
import { useAuthStore } from '../../store/authStore';
|
||||
import { useHomeStore } from '../../store/homeStore';
|
||||
import { usePlayerBarLayoutStore } from '../../store/playerBarLayoutStore';
|
||||
import { usePlaylistLayoutStore } from '../../store/playlistLayoutStore';
|
||||
@@ -16,6 +17,8 @@ import { SidebarCustomizer } from './SidebarCustomizer';
|
||||
|
||||
export function PersonalisationTab() {
|
||||
const { t } = useTranslation();
|
||||
const queueDisplayMode = useAuthStore(s => s.queueDisplayMode);
|
||||
const setQueueDisplayMode = useAuthStore(s => s.setQueueDisplayMode);
|
||||
return (
|
||||
<>
|
||||
<SettingsSubSection
|
||||
@@ -76,6 +79,46 @@ export function PersonalisationTab() {
|
||||
<ArtistLayoutCustomizer />
|
||||
</SettingsSubSection>
|
||||
|
||||
<SettingsSubSection
|
||||
title={t('settings.queueModeTitle')}
|
||||
icon={<ListOrdered size={16} />}
|
||||
>
|
||||
<div className="settings-card">
|
||||
{/* Two mutually exclusive modes — exactly one is always active, so
|
||||
turning one on turns the other off; the active one cannot be
|
||||
switched off directly (ignore the uncheck). */}
|
||||
<div className="settings-toggle-row">
|
||||
<div>
|
||||
<div style={{ fontWeight: 500 }}>{t('queue.title')}</div>
|
||||
<div style={{ fontSize: 12, color: 'var(--text-muted)' }}>{t('settings.queueModeQueueSub')}</div>
|
||||
</div>
|
||||
<label className="toggle-switch" aria-label={t('queue.title')}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={queueDisplayMode === 'queue'}
|
||||
onChange={e => { if (e.target.checked) setQueueDisplayMode('queue'); }}
|
||||
/>
|
||||
<span className="toggle-track" />
|
||||
</label>
|
||||
</div>
|
||||
<div className="settings-section-divider" />
|
||||
<div className="settings-toggle-row">
|
||||
<div>
|
||||
<div style={{ fontWeight: 500 }}>{t('queue.modePlaylist')}</div>
|
||||
<div style={{ fontSize: 12, color: 'var(--text-muted)' }}>{t('settings.queueModePlaylistSub')}</div>
|
||||
</div>
|
||||
<label className="toggle-switch" aria-label={t('queue.modePlaylist')}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={queueDisplayMode === 'playlist'}
|
||||
onChange={e => { if (e.target.checked) setQueueDisplayMode('playlist'); }}
|
||||
/>
|
||||
<span className="toggle-track" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</SettingsSubSection>
|
||||
|
||||
<SettingsSubSection
|
||||
title={t('settings.queueToolbarTitle')}
|
||||
icon={<ListMusic size={16} />}
|
||||
|
||||
Reference in New Issue
Block a user