mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
refactor(decouple): orbit seam — invert orbit off the audio core
Add core seam store/orbitRuntime.ts: a registry (registerOrbitRuntime) exposing a
neutral session snapshot {role,phase,state} + an async bulkGuard, plus pure
derivations mirrored from the feature (isInOrbitSession, isOrbitPlaybackSyncActive,
estimateLivePosition). Default (unregistered) = neutral snapshot + bulkGuard allow
— bit-identical to today's no-session behavior, and a session can only start via
the topbar which loads the @/features/orbit barrel (→ registers) first.
features/orbit/utils/orbitBulkGuard registers the runtime at module init
(store-backed getSnapshot + the existing confirm-modal orbitBulkGuard as the gate).
The orbit feature keeps its own copies of the pure helpers for UI (incl. the
arg-form isOrbitPlaybackSyncActive(role,phase) used by two settings/player-bar
components), so nothing UI-facing changes.
Repointed the 9 audio-core sites (playbackRateStore, previewStore,
playbackReportSession, nextAction, resumeAction, playTrackAction,
queueMutationActions, playAlbum) from @/features/orbit to @/store/orbitRuntime;
state reads (useOrbitStore.getState().role/.state) become orbitSnapshot().
Migrated 6 audio-core test mocks to @/store/orbitRuntime via importOriginal-spread
(keeps registerOrbitRuntime callable). enqueueShareSearchPayload stays on the orbit
barrel (share util, not audio core) — its test mock unchanged.
Decouple Step 3 — last seam. The audio ENGINE is now free of @/features/* runtime
imports (only type-only edges + the non-engine composerBrowseSessionStore browse
store remain). Unblocks the playback-core move + utils/library→lib.
tsc 0, lint 0, full suite 319/2353 green.
NEEDS Frank's live-session QA before relying on it (host+guest bulk-replace modal,
guest catch-up, rate/preview/scrobble suppression).
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useOrbitStore } from '@/features/orbit/store/orbitStore';
|
||||
import { useConfirmModalStore } from '@/store/confirmModalStore';
|
||||
import i18n from '@/lib/i18n';
|
||||
import { registerOrbitRuntime } from '@/store/orbitRuntime';
|
||||
|
||||
/**
|
||||
* Ask the user before dropping many tracks into the shared Orbit queue.
|
||||
@@ -9,8 +10,8 @@ import i18n from '@/lib/i18n';
|
||||
* when the user accepted the confirm dialog. Returns `false` only when an
|
||||
* active-Orbit user explicitly cancelled.
|
||||
*
|
||||
* Lives in its own module so `playerStore` can use it without pulling the
|
||||
* full `utils/orbit.ts` (which itself imports `playerStore` — circular).
|
||||
* The audio core reaches this (and the orbit session snapshot) through the
|
||||
* neutral `@/store/orbitRuntime` seam, not by importing the orbit feature.
|
||||
*/
|
||||
export async function orbitBulkGuard(count: number): Promise<boolean> {
|
||||
const role = useOrbitStore.getState().role;
|
||||
@@ -24,3 +25,14 @@ export async function orbitBulkGuard(count: number): Promise<boolean> {
|
||||
cancelLabel: i18n.t('orbit.bulkConfirmNo'),
|
||||
});
|
||||
}
|
||||
|
||||
// Install the orbit runtime into the core seam at module init. The
|
||||
// @/features/orbit barrel re-exports this module, so the topbar's barrel import
|
||||
// evaluates it at boot — before any Orbit session can start.
|
||||
registerOrbitRuntime({
|
||||
getSnapshot: () => {
|
||||
const o = useOrbitStore.getState();
|
||||
return { role: o.role, phase: o.phase, state: o.state };
|
||||
},
|
||||
bulkGuard: orbitBulkGuard,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user