mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-21 22:15:40 +00:00
5231169a71
The mm:ss track-time formatter was hand-rolled in 11 places and the h:mm:ss total-duration formatter in 4 — extract two tested functions: - formatTrackTime(seconds, fallback='0:00') — m:ss, used for track / playback times. fallback param covers the '–' placeholder rows. - formatLongDuration(seconds) — h:mm:ss when >=1h, else m:ss, used for album / queue totals. Behaviour preserved per call site: the unified guard (!seconds || !isFinite || <0 -> fallback) produces identical output to every prior variant for all real inputs; SongRow keeps its '–' via the fallback arg. Removes the formatter exports from 6 componentHelpers files (playerBarHelpers / fullscreenPlayerHelpers deleted — they only exported the formatter) and 7 inline component copies. + formatDuration.test.ts
76 lines
2.6 KiB
TypeScript
76 lines
2.6 KiB
TypeScript
import { usePlayerStore } from '../../store/playerStore';
|
|
import type { MiniSyncPayload, MiniTrackInfo } from '../miniPlayerBridge';
|
|
|
|
export const COLLAPSED_SIZE = { w: 340, h: 260 };
|
|
export const EXPANDED_SIZE = { w: 340, h: 500 };
|
|
// Minimum window dimensions per state. When the queue is open the floor must
|
|
// keep at least two queue rows visible; a stricter min would let the user
|
|
// collapse the queue area to nothing while it's still toggled on.
|
|
export const COLLAPSED_MIN = { w: 320, h: 240 };
|
|
export const EXPANDED_MIN = { w: 320, h: 340 };
|
|
|
|
// Persist the expanded-window height so reopening the queue restores the
|
|
// user's preferred size instead of snapping back to EXPANDED_SIZE.h.
|
|
export const EXPANDED_H_KEY = 'psysonic_mini_expanded_h';
|
|
export function readStoredExpandedHeight(): number {
|
|
try {
|
|
const raw = localStorage.getItem(EXPANDED_H_KEY);
|
|
if (raw) {
|
|
const n = parseInt(raw, 10);
|
|
if (Number.isFinite(n) && n >= EXPANDED_MIN.h) return n;
|
|
}
|
|
} catch {}
|
|
return EXPANDED_SIZE.h;
|
|
}
|
|
|
|
// Persist whether the queue panel was open so the next launch restores
|
|
// the same state. Same scope as the height: localStorage of the mini
|
|
// webview (shared across mini sessions, separate from the main store).
|
|
export const QUEUE_OPEN_KEY = 'psysonic_mini_queue_open';
|
|
export function readQueueOpen(): boolean {
|
|
try { return localStorage.getItem(QUEUE_OPEN_KEY) === '1'; } catch { return false; }
|
|
}
|
|
|
|
export function toMini(t: any): MiniTrackInfo {
|
|
return {
|
|
id: t.id,
|
|
title: t.title,
|
|
artist: t.artist,
|
|
album: t.album,
|
|
albumId: t.albumId,
|
|
artistId: t.artistId,
|
|
coverArt: t.coverArt,
|
|
duration: t.duration,
|
|
starred: !!t.starred,
|
|
year: t.year,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Hydrate from the persisted playerStore so initial paint shows real content
|
|
* instead of "—" while we wait for the mini:sync event from the main window.
|
|
* The persisted state covers the cold-start window (webview boot + bundle).
|
|
*/
|
|
export function initialSnapshot(): MiniSyncPayload {
|
|
try {
|
|
const s = usePlayerStore.getState();
|
|
return {
|
|
track: s.currentTrack ? toMini(s.currentTrack) : null,
|
|
queue: (s.queue ?? []).map(toMini),
|
|
queueIndex: s.queueIndex ?? 0,
|
|
isPlaying: s.isPlaying,
|
|
volume: s.volume ?? 1,
|
|
gaplessEnabled: false,
|
|
crossfadeEnabled: false,
|
|
infiniteQueueEnabled: false,
|
|
isMobile: false,
|
|
};
|
|
} catch {
|
|
return {
|
|
track: null, queue: [], queueIndex: 0, isPlaying: false,
|
|
volume: 1, gaplessEnabled: false, crossfadeEnabled: false,
|
|
infiniteQueueEnabled: false, isMobile: false,
|
|
};
|
|
}
|
|
}
|