Files
Psychotoxical-psysonic/src/store/loudnessBackfillWindow.ts
T
Frank Stellmacher 9fac6eb490 refactor(player): E.42 — migrate playerStore re-exports to direct imports (#607)
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.
2026-05-12 22:46:13 +02:00

48 lines
1.7 KiB
TypeScript

import type { Track } from './playerStoreTypes';
/**
* After a bulk enqueue (queue replace, append-many, lucky-mix) the runtime
* warms the loudness cache for the current track + the next N entries so
* the engine's `audio_chain_preload` sees a real cached gain instead of
* the startup trim. These helpers compute that window — both as a
* "does this id sit inside it?" predicate and as the explicit id list
* the prefetch loop iterates over.
*
* Pure functions of the state slice — no store imports, no side effects.
* The caller passes the queue + index + current track so the test surface
* stays trivial and there's no top-level coupling back to playerStore.
*/
export const LOUDNESS_BACKFILL_WINDOW_AHEAD = 5;
export function isTrackInsideLoudnessBackfillWindow(
trackId: string,
queue: Track[],
queueIndex: number,
currentTrack: Track | null,
): boolean {
if (!trackId) return false;
if (currentTrack?.id === trackId) return true;
if (queue.length === 0) return false;
const start = Math.max(0, queueIndex + 1);
const end = Math.min(queue.length, start + LOUDNESS_BACKFILL_WINDOW_AHEAD);
for (let i = start; i < end; i++) {
if (queue[i]?.id === trackId) return true;
}
return false;
}
export function collectLoudnessBackfillWindowTrackIds(
queue: Track[],
queueIndex: number,
currentTrack: Track | null,
): string[] {
const ids = new Set<string>();
if (currentTrack?.id) ids.add(currentTrack.id);
const start = Math.max(0, queueIndex + 1);
const end = Math.min(queue.length, start + LOUDNESS_BACKFILL_WINDOW_AHEAD);
for (let i = start; i < end; i++) {
const tid = queue[i]?.id;
if (tid) ids.add(tid);
}
return Array.from(ids);
}