mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
9fac6eb490
Migrates ~74 call sites away from the playerStore re-export shims that were kept during M0–E.41 to avoid touching 30+ imports per PR. Now that the bigger refactor work is done, each helper goes back to its real home: - `initAudioListeners`, `installQueueUndoHotkey`, `flushPlayQueuePosition` → from their own store modules - `getPlaybackProgressSnapshot`, `subscribePlaybackProgress`, `PlaybackProgressSnapshot` → from `playbackProgress` - `resolveReplayGainDb`, `shuffleArray`, `songToTrack` → from `utils/*` - `_resetQueueUndoStacksForTest`, `consumePendingQueueListScrollTop`, `registerQueueListScrollTopReader` → from `queueUndo` - `PlayerState`, `Track` types → from `playerStoreTypes` Drops the corresponding 13 re-export stubs from `playerStore.ts` and the now-unused imports. Also drops dead section banners + per-wrapper comments above one-line action delegates. Trims one stale "(separate PR)" note in `transportLightActions.ts` since that follow-up landed in E.39. `playerStore.ts`: 180 → 112 LOC (−68). Down from Phase E's starting 3732 LOC. `bootstrap.test.ts` mock target updated from `../store/playerStore` to `../store/queueUndoHotkey` to keep the spy reachable after the import change.
56 lines
2.0 KiB
TypeScript
56 lines
2.0 KiB
TypeScript
import { getAlbum } from '../api/subsonic';
|
|
import { usePlayerStore } from '../store/playerStore';
|
|
import { songToTrack } from './songToTrack';
|
|
import { useOrbitStore } from '../store/orbitStore';
|
|
|
|
function fadeOut(setVolume: (v: number) => void, from: number, durationMs: number): Promise<void> {
|
|
return new Promise(resolve => {
|
|
const steps = 16;
|
|
const stepMs = durationMs / steps;
|
|
let step = 0;
|
|
const id = setInterval(() => {
|
|
step++;
|
|
setVolume(Math.max(0, from * (1 - step / steps)));
|
|
if (step >= steps) {
|
|
clearInterval(id);
|
|
resolve();
|
|
}
|
|
}, stepMs);
|
|
});
|
|
}
|
|
|
|
export async function playAlbum(albumId: string): Promise<void> {
|
|
const albumData = await getAlbum(albumId);
|
|
const albumGenre = albumData.album.genre;
|
|
const tracks = albumData.songs.map(s => {
|
|
const track = songToTrack(s);
|
|
if (!track.genre && albumGenre) track.genre = albumGenre;
|
|
return track;
|
|
});
|
|
if (!tracks.length) return;
|
|
|
|
// In Orbit sessions, playAlbum is effectively an append operation (the
|
|
// playerStore bulk-gate also routes replaces into enqueue). Skip the
|
|
// fadeOut entirely — the current track keeps playing, the album goes
|
|
// onto the end of the queue after the user confirms the bulk dialog.
|
|
const orbitRole = useOrbitStore.getState().role;
|
|
if (orbitRole === 'host' || orbitRole === 'guest') {
|
|
usePlayerStore.getState().enqueue(tracks);
|
|
return;
|
|
}
|
|
|
|
const store = usePlayerStore.getState();
|
|
const { isPlaying, volume } = store;
|
|
|
|
if (isPlaying) {
|
|
await fadeOut(store.setVolume, volume, 700);
|
|
// Restore volume only in the Zustand store — do NOT call audio_set_volume here,
|
|
// otherwise the old track glitches back to full volume before playTrack stops it.
|
|
// playTrack reads state.volume and passes it to audio_play, so the new track
|
|
// starts at the correct volume without the Rust engine ever hearing a restore.
|
|
usePlayerStore.setState({ volume });
|
|
}
|
|
|
|
usePlayerStore.getState().playTrack(tracks[0], tracks);
|
|
}
|