mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +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
@@ -99,6 +99,7 @@ export const useAuthStore = create<AuthState>()(
|
||||
seekbarStyle: 'truewave',
|
||||
queueNowPlayingCollapsed: false,
|
||||
queueDurationDisplayMode: 'total',
|
||||
queueDisplayMode: 'queue',
|
||||
enableHiRes: false,
|
||||
audioOutputDevice: null,
|
||||
hotCacheEnabled: false,
|
||||
|
||||
@@ -17,6 +17,7 @@ import type {
|
||||
DiscordCoverSource,
|
||||
DurationMode,
|
||||
LyricsSourceConfig,
|
||||
QueueDisplayMode,
|
||||
SeekbarStyle,
|
||||
} from './authStoreTypes';
|
||||
|
||||
@@ -103,6 +104,15 @@ export function computeAuthStoreRehydration(state: AuthState): Partial<AuthState
|
||||
? {}
|
||||
: { queueDurationDisplayMode: 'total' as DurationMode };
|
||||
|
||||
// Missing key (pre-feature persist) / garbage maps to 'queue' — the default
|
||||
// mode, which lists only upcoming tracks.
|
||||
const VALID_QUEUE_DISPLAY_MODES = new Set<string>(['playlist', 'queue']);
|
||||
const queueDisplayModeMigrated = VALID_QUEUE_DISPLAY_MODES.has(
|
||||
(state as { queueDisplayMode?: unknown }).queueDisplayMode as string,
|
||||
)
|
||||
? {}
|
||||
: { queueDisplayMode: 'queue' as QueueDisplayMode };
|
||||
|
||||
const VALID_WAYLAND_TEXT_PROFILE = new Set<string>(['balanced', 'sharp', 'gpu', 'minimal']);
|
||||
const rawWaylandProfile = (state as { linuxWaylandTextRenderProfile?: unknown }).linuxWaylandTextRenderProfile;
|
||||
const linuxWaylandTextRenderProfileMigrated = VALID_WAYLAND_TEXT_PROFILE.has(rawWaylandProfile as string)
|
||||
@@ -162,6 +172,7 @@ export function computeAuthStoreRehydration(state: AuthState): Partial<AuthState
|
||||
...wheelSmoothOneTime,
|
||||
...seekbarStyleMigrated,
|
||||
...queueDurationDisplayModeMigrated,
|
||||
...queueDisplayModeMigrated,
|
||||
...linuxWaylandTextRenderProfileMigrated,
|
||||
...discordCoverSourceMigrated,
|
||||
};
|
||||
|
||||
@@ -33,6 +33,16 @@ export interface ServerProfile {
|
||||
export type SeekbarStyle = 'truewave' | 'pseudowave' | 'linedot' | 'bar' | 'thick' | 'segmented' | 'neon' | 'pulsewave' | 'particletrail' | 'liquidfill' | 'retrotape';
|
||||
/** Queue header duration chip: total duration / time left / ETA finish clock. */
|
||||
export type DurationMode = 'total' | 'remaining' | 'eta';
|
||||
|
||||
/**
|
||||
* Queue panel render mode.
|
||||
* - `playlist`: the full queue stays visible; the now-playing row sits at the
|
||||
* top of the list, the highlight wanders down as tracks play, and the list
|
||||
* only re-pins the current track once it scrolls out of view.
|
||||
* - `queue`: the list shows upcoming tracks only — the current track lives in
|
||||
* the header and drops out of the list once it has played.
|
||||
*/
|
||||
export type QueueDisplayMode = 'playlist' | 'queue';
|
||||
export type LoggingMode = 'off' | 'normal' | 'debug';
|
||||
/**
|
||||
* Wall-clock format for ETA / sleep-timer labels. `'auto'` follows the user's
|
||||
@@ -181,6 +191,8 @@ export interface AuthState {
|
||||
queueNowPlayingCollapsed: boolean;
|
||||
/** Queue header duration chip mode (cycle: total → remaining → ETA). */
|
||||
queueDurationDisplayMode: DurationMode;
|
||||
/** Queue panel render mode: full timeline (`playlist`) vs. upcoming-only (`queue`). */
|
||||
queueDisplayMode: QueueDisplayMode;
|
||||
|
||||
/** Alpha: native hi-res sample rate output (disabled = safe 44.1 kHz mode) */
|
||||
enableHiRes: boolean;
|
||||
@@ -339,6 +351,7 @@ export interface AuthState {
|
||||
setSeekbarStyle: (v: SeekbarStyle) => void;
|
||||
setQueueNowPlayingCollapsed: (v: boolean) => void;
|
||||
setQueueDurationDisplayMode: (v: DurationMode) => void;
|
||||
setQueueDisplayMode: (v: QueueDisplayMode) => void;
|
||||
setEnableHiRes: (v: boolean) => void;
|
||||
setAudioOutputDevice: (v: string | null) => void;
|
||||
setHotCacheEnabled: (v: boolean) => void;
|
||||
|
||||
@@ -26,6 +26,7 @@ export function createUiAppearanceActions(set: SetState): Pick<
|
||||
| 'setSeekbarStyle'
|
||||
| 'setQueueNowPlayingCollapsed'
|
||||
| 'setQueueDurationDisplayMode'
|
||||
| 'setQueueDisplayMode'
|
||||
| 'setShowFullscreenLyrics'
|
||||
| 'setFsLyricsStyle'
|
||||
| 'setSidebarLyricsStyle'
|
||||
@@ -50,6 +51,7 @@ export function createUiAppearanceActions(set: SetState): Pick<
|
||||
setSeekbarStyle: (v) => set({ seekbarStyle: v }),
|
||||
setQueueNowPlayingCollapsed: (v) => set({ queueNowPlayingCollapsed: v }),
|
||||
setQueueDurationDisplayMode: (v) => set({ queueDurationDisplayMode: v }),
|
||||
setQueueDisplayMode: (v) => set({ queueDisplayMode: v }),
|
||||
setShowFullscreenLyrics: (v) => set({ showFullscreenLyrics: v }),
|
||||
setFsLyricsStyle: (v) => set({ fsLyricsStyle: v }),
|
||||
setSidebarLyricsStyle: (v) => set({ sidebarLyricsStyle: v }),
|
||||
|
||||
Reference in New Issue
Block a user