mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
refactor(playback): move thin-state queue resolver out of utils/library into the feature
The queue-resolver family (queueTrackResolver, queueRestore, queueItemRef, queueTrackView) runtime-imports usePlayerStore / playerStoreTypes — it is the playback engine's thin-state queue subsystem, not shared library infra. It sat in utils/library only because it queries the local index. Co-locate into features/playback/store so those edges become intra-feature; its remaining deps (advancedSearchLocal, libraryReady, serverLookup, serverIndexKey, authStore) are plain core/infra (feature -> infra, no inversion). Removes 4 of the 6 store/utils -> feature runtime inversions that blocked the utils/library -> lib move. 8 files moved, 46 consumers rewritten. tsc 0, lint 0, targeted suites green.
This commit is contained in:
@@ -6,7 +6,7 @@ import { resetAllStores } from '../test/helpers/storeReset';
|
||||
import { invokeMock, onInvoke } from '../test/mocks/tauri';
|
||||
import { coverArtRef } from '../cover/ref';
|
||||
import { coverCacheEnsure, coverCacheRestHost, librarySqlServerId } from './coverCache';
|
||||
import { toQueueItemRefs } from '../utils/library/queueItemRef';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
|
||||
describe('librarySqlServerId', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import { reconcileLibraryTierForServer } from '@/features/offline';
|
||||
import { initMiniPlayerBridgeOnMain } from '@/features/miniPlayer';
|
||||
import { runAdvancedModeMigration } from '../utils/migrations/advancedModeMigration';
|
||||
import { bootstrapAllIndexedServers } from '../utils/library/librarySession';
|
||||
import { hydrateQueueFromIndex } from '../utils/library/queueRestore';
|
||||
import { hydrateQueueFromIndex } from '@/features/playback/store/queueRestore';
|
||||
import { useLibraryAnalysisBackfill } from '../hooks/useLibraryAnalysisBackfill';
|
||||
import { useCoverArtPrefetch } from '../cover/useCoverArtPrefetch';
|
||||
import { useLibraryCoverBackfill } from '../hooks/useLibraryCoverBackfill';
|
||||
|
||||
@@ -17,11 +17,11 @@ import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { useCachedUrl } from '@/ui/CachedImage';
|
||||
import { OpenArtistRefInline } from '@/features/artist';
|
||||
import { formatTrackTime } from '@/lib/format/formatDuration';
|
||||
import { resolveQueueTrack } from '../utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import {
|
||||
getQueueResolverVersion,
|
||||
subscribeQueueResolver,
|
||||
} from '../utils/library/queueTrackResolver';
|
||||
} from '@/features/playback/store/queueTrackResolver';
|
||||
import LyricsPane from './LyricsPane';
|
||||
import { usePlaybackDelayPress } from '../hooks/usePlaybackDelayPress';
|
||||
import PlaybackDelayModal from './PlaybackDelayModal';
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useAuthStore } from '../store/authStore';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { makeTrack } from '../test/helpers/factories';
|
||||
import { resetAllStores } from '../test/helpers/storeReset';
|
||||
import { toQueueItemRefs } from '../utils/library/queueItemRef';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
useCoverArtMock: vi.fn(
|
||||
|
||||
@@ -3,11 +3,11 @@ import { useTranslation } from 'react-i18next';
|
||||
import { X } from 'lucide-react';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import type { Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import {
|
||||
getQueueResolverVersion,
|
||||
subscribeQueueResolver,
|
||||
} from '@/utils/library/queueTrackResolver';
|
||||
} from '@/features/playback/store/queueTrackResolver';
|
||||
import { formatTrackTime } from '@/lib/format/formatDuration';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { listen, emitTo } from '@tauri-apps/api/event';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { useAuthStore } from '@/store/authStore';
|
||||
import { setTransitionMode, type TransitionMode } from '@/features/playback/utils/playback/playbackTransition';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import type { SubsonicOpenArtistRef } from '@/lib/api/subsonicTypes';
|
||||
import type { Track } from '@/features/playback/store/playerStoreTypes';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import type { MiniSyncPayload, MiniTrackInfo } from '@/features/miniPlayer/utils/miniPlayerBridge';
|
||||
import type { Track } from '@/features/playback/store/playerStoreTypes';
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useAuthStore } from '@/store/authStore';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { makeTrack } from '@/test/helpers/factories';
|
||||
import { resetAllStores } from '@/test/helpers/storeReset';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
|
||||
vi.mock('@/api/coverCache', async importOriginal => {
|
||||
const actual = await importOriginal<typeof import('@/api/coverCache')>();
|
||||
|
||||
@@ -10,8 +10,8 @@ import {
|
||||
import { clearPreloadingIds } from '@/features/playback/store/gaplessPreloadState';
|
||||
import { deriveNormalizationSnapshot } from '@/features/playback/store/normalizationSnapshot';
|
||||
import type { PlayerState, QueueItemRef } from '@/features/playback/store/playerStoreTypes';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { seedQueueResolver } from '@/utils/library/queueTrackResolver';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver';
|
||||
import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey';
|
||||
import { sameQueueTrackId } from '@/features/playback/utils/playback/queueIdentity';
|
||||
import { queueUndoRestoreAudioEngine } from '@/features/playback/store/queueUndoAudioRestore';
|
||||
|
||||
@@ -2,8 +2,8 @@ import { getPlayQueueForServer, type PlayQueueResult } from '@/lib/api/subsonicP
|
||||
import { songToTrack } from '@/features/playback/utils/playback/songToTrack';
|
||||
import { bindQueueServerId } from '@/features/playback/utils/playback/playbackServer';
|
||||
import { resolveServerIdForIndexKey } from '@/utils/server/serverLookup';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
import { seedQueueResolver } from '@/utils/library/queueTrackResolver';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver';
|
||||
import type { Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { useAuthStore } from '@/store/authStore';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
playbackReportStart,
|
||||
playbackReportStopped,
|
||||
} from '@/features/playback/store/playbackReportSession';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { getMusicNetworkRuntimeOrNull } from '@/music-network';
|
||||
import { setDeferHotCachePrefetch } from '@/utils/cache/hotCacheGate';
|
||||
|
||||
@@ -16,13 +16,13 @@ import { useAuthStore } from '@/store/authStore';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { useLibraryIndexStore } from '@/store/libraryIndexStore';
|
||||
import { resetAuthStore, resetPlayerStore } from '@/test/helpers/storeReset';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
import { bindQueueServerForPlayback } from '@/features/playback/utils/playback/playbackServer';
|
||||
import {
|
||||
_resetQueueResolverForTest,
|
||||
getCachedTrack,
|
||||
seedQueueResolver,
|
||||
} from '@/utils/library/queueTrackResolver';
|
||||
} from '@/features/playback/store/queueTrackResolver';
|
||||
import { applyQueueHistorySnapshot } from '@/features/playback/store/applyQueueHistorySnapshot';
|
||||
import {
|
||||
pushQueueUndoSnapshot,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { computeWaveformSilence, planCrossfadeTransition } from '@/utils/wavefor
|
||||
import { findLocalPlaybackUrl } from '@/store/localPlaybackResolve';
|
||||
import { playbackCacheKeyForRef } from '@/features/playback/utils/playback/playbackServer';
|
||||
import { resolvePlaybackUrl } from '@/features/playback/utils/playback/resolvePlaybackUrl';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import type { Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import {
|
||||
hasPlannedCrossfade,
|
||||
|
||||
@@ -12,9 +12,9 @@ import { reseedLoudnessForTrackId } from '@/features/playback/store/loudnessRese
|
||||
import { getPlaybackProgressSnapshot } from '@/features/playback/store/playbackProgress';
|
||||
import { shouldRebindPlaybackToHotCache } from '@/features/playback/store/playbackUrlRouting';
|
||||
import type { PlayerState } from '@/features/playback/store/playerStoreTypes';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { seedQueueResolver } from '@/utils/library/queueTrackResolver';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver';
|
||||
import { pushQueueUndoFromGetter } from '@/features/playback/store/queueUndo';
|
||||
import { syncUserQueueMutationToServer } from '@/features/playback/store/queueSync';
|
||||
import {
|
||||
|
||||
@@ -11,9 +11,9 @@ import {
|
||||
} from '@/features/playback/store/infiniteQueueState';
|
||||
import { isInOrbitSession } from '@/store/orbitRuntime';
|
||||
import type { PlayerState, QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { seedQueueResolver } from '@/utils/library/queueTrackResolver';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver';
|
||||
import {
|
||||
addRadioSessionSeen,
|
||||
getCurrentRadioArtistId,
|
||||
|
||||
@@ -29,7 +29,7 @@ vi.mock('@/features/playback/store/infiniteQueueState', () => ({
|
||||
}));
|
||||
vi.mock('@/features/playback/store/engineState', () => ({ setIsAudioPaused: vi.fn() }));
|
||||
vi.mock('@/features/playback/store/skipStarRating', () => ({ applySkipStarOnManualNext: vi.fn() }));
|
||||
vi.mock('@/utils/library/queueTrackView', () => ({
|
||||
vi.mock('@/features/playback/store/queueTrackView', () => ({
|
||||
resolveQueueTrack: (ref: { trackId: string }) => ({
|
||||
id: ref.trackId,
|
||||
artistId: 'a1',
|
||||
@@ -41,8 +41,8 @@ vi.mock('@/features/playback/utils/playback/buildInfiniteQueueCandidates', () =>
|
||||
}));
|
||||
vi.mock('@/features/playback/utils/playback/songToTrack', () => ({ songToTrack: (s: unknown) => s }));
|
||||
vi.mock('@/features/playback/utils/playback/playbackServer', () => ({ ensureQueueServerPinned: () => null }));
|
||||
vi.mock('@/utils/library/queueTrackResolver', () => ({ seedQueueResolver: vi.fn() }));
|
||||
vi.mock('@/utils/library/queueItemRef', () => ({ toQueueItemRefs: () => [] }));
|
||||
vi.mock('@/features/playback/store/queueTrackResolver', () => ({ seedQueueResolver: vi.fn() }));
|
||||
vi.mock('@/features/playback/store/queueItemRef', () => ({ toQueueItemRefs: () => [] }));
|
||||
|
||||
import { runNext } from '@/features/playback/store/nextAction';
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ vi.mock('@/features/playback/store/playerStore', () => ({
|
||||
}),
|
||||
},
|
||||
}));
|
||||
vi.mock('@/utils/library/queueTrackView', () => ({
|
||||
vi.mock('@/features/playback/store/queueTrackView', () => ({
|
||||
getQueueTracksView: vi.fn((refs: { trackId: string }[]) =>
|
||||
refs.map(r => ({
|
||||
id: r.trackId,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { getQueueTracksView } from '@/utils/library/queueTrackView';
|
||||
import { getQueueTracksView } from '@/features/playback/store/queueTrackView';
|
||||
import { scheduleHotCachePrefetchForTrack } from '@/hotCachePrefetch';
|
||||
import { getPlaybackCacheServerKey } from '@/features/playback/utils/playback/playbackServer';
|
||||
import { useAuthStore } from '@/store/authStore';
|
||||
|
||||
@@ -16,8 +16,8 @@ import {
|
||||
getCachedTrack,
|
||||
seedQueueResolver,
|
||||
_resetQueueResolverForTest,
|
||||
} from '@/utils/library/queueTrackResolver';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
} from '@/features/playback/store/queueTrackResolver';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
|
||||
const track = (id: string): Track => ({
|
||||
id, title: id, artist: '', album: 'A', albumId: 'A', duration: 1,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { setRating, star, unstar } from '@/lib/api/subsonicStarRating';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { patchCachedTrack } from '@/utils/library/queueTrackResolver';
|
||||
import { patchCachedTrack } from '@/features/playback/store/queueTrackResolver';
|
||||
|
||||
/**
|
||||
* F4 — pending-sync for **song** star + rating (spec §6.5 / R7-18).
|
||||
|
||||
@@ -58,9 +58,9 @@ import {
|
||||
recordEnginePlayUrl,
|
||||
} from '@/features/playback/store/playbackUrlRouting';
|
||||
import type { PlayerState, Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
import { getQueueTracksView, resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { seedQueueResolver } from '@/utils/library/queueTrackResolver';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
import { getQueueTracksView, resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver';
|
||||
import { promoteCompletedStreamToHotCache } from '@/features/playback/store/promoteStreamCache';
|
||||
import { pushQueueOnPlaybackStart } from '@/features/playback/store/queueSync';
|
||||
import { playListenSessionFinalize } from '@/features/playback/store/playListenSession';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { readInitialPlayerPrefs, persistPlayerPrefs } from '@/features/playback/
|
||||
import { createHydrationGatedStorage, createSafeJSONStorage } from '@/lib/util/safeStorage';
|
||||
import { emitPlaybackProgress } from '@/features/playback/store/playbackProgress';
|
||||
import type { PlayerState, QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey';
|
||||
import { readInitialQueueVisibility } from '@/features/playback/store/queueVisibilityStorage';
|
||||
import { createNetworkLoveActions } from '@/features/playback/store/networkLoveActions';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { stampTrackServerId } from '@/features/playback/utils/playback/trackServerScope';
|
||||
import { canonicalQueueServerKey } from '../server/serverIndexKey';
|
||||
import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey';
|
||||
|
||||
/**
|
||||
* Derive thin `QueueItemRef`s from a `Track[]` queue (thin-state). Per-item
|
||||
@@ -4,8 +4,8 @@ import { useAuthStore } from '@/store/authStore';
|
||||
import { setIsAudioPaused } from '@/features/playback/store/engineState';
|
||||
import { prefetchLoudnessForEnqueuedTracks } from '@/features/playback/store/loudnessPrefetch';
|
||||
import type { PlayerState, QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
import { seedQueueResolver } from '@/utils/library/queueTrackResolver';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver';
|
||||
import { pushQueueUndoFromGetter } from '@/features/playback/store/queueUndo';
|
||||
import { syncUserQueueMutationToServer } from '@/features/playback/store/queueSync';
|
||||
import {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* track here, off the render path.
|
||||
*/
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { resolveVisibleRange } from '@/utils/library/queueTrackResolver';
|
||||
import { resolveVisibleRange } from '@/features/playback/store/queueTrackResolver';
|
||||
|
||||
usePlayerStore.subscribe((state, prev) => {
|
||||
// Re-seed when the queue refs or the current index change — the prefetch
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useAuthStore } from '../../store/authStore';
|
||||
import { useAuthStore } from '@/store/authStore';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes';
|
||||
import { canonicalQueueServerKey } from '../server/serverIndexKey';
|
||||
import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey';
|
||||
import { resolveBatch } from './queueTrackResolver';
|
||||
|
||||
/**
|
||||
+4
-4
@@ -3,10 +3,10 @@ import { getSongForServer } from '@/lib/api/subsonicLibrary';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { songToTrack } from '@/features/playback/utils/playback/songToTrack';
|
||||
import { resolveServerIdForIndexKey } from '../server/serverLookup';
|
||||
import { canonicalQueueServerKey } from '../server/serverIndexKey';
|
||||
import { trackToSong } from './advancedSearchLocal';
|
||||
import { libraryIsReady } from './libraryReady';
|
||||
import { resolveServerIdForIndexKey } from '@/utils/server/serverLookup';
|
||||
import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey';
|
||||
import { trackToSong } from '@/utils/library/advancedSearchLocal';
|
||||
import { libraryIsReady } from '@/utils/library/libraryReady';
|
||||
|
||||
/**
|
||||
* Queue track resolver (thin-state phase 2). Resolves `QueueItemRef`s to full
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { seedQueueResolver, _resetQueueResolverForTest } from '@/utils/library/queueTrackResolver';
|
||||
import { seedQueueResolver, _resetQueueResolverForTest } from '@/features/playback/store/queueTrackResolver';
|
||||
import { resolveQueueTrack, getQueueTracksView } from './queueTrackView';
|
||||
|
||||
const track = (id: string, over: Partial<Track> = {}): Track =>
|
||||
@@ -5,7 +5,7 @@
|
||||
* to restore list scroll position after an undo/redo commit.
|
||||
*/
|
||||
import type { PlayerState, Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
import {
|
||||
QUEUE_UNDO_MAX,
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
recordEnginePlayUrl,
|
||||
} from '@/features/playback/store/playbackUrlRouting';
|
||||
import type { PlayerState } from '@/features/playback/store/playerStoreTypes';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import { promoteCompletedStreamToHotCache } from '@/features/playback/store/promoteStreamCache';
|
||||
import { pushQueueOnPlaybackStart, flushLocalQueueWhenTakingPlayback } from '@/features/playback/store/queueSync';
|
||||
import { markPlaybackActive } from '@/features/playback/store/queuePlaybackIdle';
|
||||
|
||||
@@ -28,7 +28,7 @@ vi.mock('@/features/playback/store/playerStore', () => ({
|
||||
}));
|
||||
|
||||
import { applySkipStarOnManualNext } from '@/features/playback/store/skipStarRating';
|
||||
import { seedQueueResolver, _resetQueueResolverForTest } from '@/utils/library/queueTrackResolver';
|
||||
import { seedQueueResolver, _resetQueueResolverForTest } from '@/features/playback/store/queueTrackResolver';
|
||||
|
||||
function track(id: string, overrides: Partial<Track> = {}): Track {
|
||||
return {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { useAuthStore } from '@/store/authStore';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { getCachedTrack } from '@/utils/library/queueTrackResolver';
|
||||
import { getCachedTrack } from '@/features/playback/store/queueTrackResolver';
|
||||
import { queueSongRating } from '@/features/playback/store/pendingStarSync';
|
||||
/**
|
||||
* Skip → 1★ behaviour: every user-initiated `next()` on an unrated track
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import { deriveNormalizationSnapshot } from '@/features/playback/store/normalizationSnapshot';
|
||||
import { invokeAudioUpdateReplayGainDeduped } from '@/features/playback/store/normalizationIpcDedupe';
|
||||
import type { PlayerState } from '@/features/playback/store/playerStoreTypes';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
|
||||
type SetState = (
|
||||
partial: Partial<PlayerState> | ((state: PlayerState) => Partial<PlayerState>),
|
||||
|
||||
@@ -11,7 +11,7 @@ import { PlaylistArtistCell } from '@/features/playlist/components/PlaylistArtis
|
||||
import { useThemeStore } from '@/store/themeStore';
|
||||
import { usePlaylistLayoutStore } from '@/features/playlist/store/playlistLayoutStore';
|
||||
import { songToTrack } from '@/features/playback/utils/playback/songToTrack';
|
||||
import { getQueueTracksView } from '@/utils/library/queueTrackView';
|
||||
import { getQueueTracksView } from '@/features/playback/store/queueTrackView';
|
||||
import { codecLabel } from '@/utils/componentHelpers/playlistDetailHelpers';
|
||||
import { formatLastSeen } from '@/utils/componentHelpers/userMgmtHelpers';
|
||||
import { formatTrackTime } from '@/lib/format/formatDuration';
|
||||
|
||||
@@ -9,11 +9,11 @@ import type { QueueDisplayMode } from '@/store/authStoreTypes';
|
||||
import type { DurationMode } from '@/utils/componentHelpers/queuePanelHelpers';
|
||||
import { formatLongDuration } from '@/lib/format/formatDuration';
|
||||
import { formatClockTime } from '@/lib/format/formatClockTime';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import {
|
||||
getQueueResolverVersion,
|
||||
subscribeQueueResolver,
|
||||
} from '@/utils/library/queueTrackResolver';
|
||||
} from '@/features/playback/store/queueTrackResolver';
|
||||
|
||||
interface Props {
|
||||
queue: QueueItemRef[];
|
||||
|
||||
@@ -8,11 +8,11 @@ import { useLuckyMixStore } from '@/store/luckyMixStore';
|
||||
import type { QueueItemRef, PlayerState } from '@/features/playback/store/playerStoreTypes';
|
||||
import type { QueueDisplayMode } from '@/store/authStoreTypes';
|
||||
import { formatTrackTime } from '@/lib/format/formatDuration';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import {
|
||||
getQueueResolverVersion,
|
||||
subscribeQueueResolver,
|
||||
} from '@/utils/library/queueTrackResolver';
|
||||
} from '@/features/playback/store/queueTrackResolver';
|
||||
import { findQueueItemRefIndex } from '@/features/playback/utils/playback/queueIdentity';
|
||||
import type { TimelineDisplayRow } from '@/utils/queue/buildTimelineDisplayRows';
|
||||
import { findTimelineScrollLocalIndex } from '@/utils/queue/buildTimelineDisplayRows';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import type { Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { getCachedTrack, _resetQueueResolverForTest } from '@/utils/library/queueTrackResolver';
|
||||
import { getCachedTrack, _resetQueueResolverForTest } from '@/features/playback/store/queueTrackResolver';
|
||||
import { seedQueue } from '@/test/helpers/factories';
|
||||
import { useQueueTrackAt, useCurrentTrack, useQueueItems } from '@/features/queue/hooks/useQueueTracks';
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useMemo, useSyncExternalStore } from 'react';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { resolveQueueTrack } from '@/utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import {
|
||||
getQueueResolverVersion,
|
||||
subscribeQueueResolver,
|
||||
} from '@/utils/library/queueTrackResolver';
|
||||
} from '@/features/playback/store/queueTrackResolver';
|
||||
|
||||
/**
|
||||
* Stable queue selectors (queue thin-state). The store is refs-canonical now:
|
||||
|
||||
@@ -3,7 +3,7 @@ import { invoke } from '@tauri-apps/api/core';
|
||||
import { getPlaybackProgressSnapshot } from '@/features/playback/store/playbackProgress';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { useAuthStore } from '../../store/authStore';
|
||||
import { resolveQueueTrack } from '../../utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
|
||||
/** Half-width of the CLI snapshot queue window (thin-state — like the mini
|
||||
* bridge, the full 50k queue must not serialize over IPC on every change). */
|
||||
|
||||
@@ -17,8 +17,8 @@ vi.mock('../utils/queue/timelineBootstrapReady', () => ({
|
||||
timelineBootstrapIndexReady: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../utils/library/queueTrackResolver', async importOriginal => {
|
||||
const actual = await importOriginal<typeof import('../utils/library/queueTrackResolver')>();
|
||||
vi.mock('@/features/playback/store/queueTrackResolver', async importOriginal => {
|
||||
const actual = await importOriginal<typeof import('@/features/playback/store/queueTrackResolver')>();
|
||||
return { ...actual, seedQueueResolver: vi.fn() };
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useSyncExternalStore } from 'react';
|
||||
import { libraryGetRecentPlaySessions, type PlaySessionRecentTrack } from '@/lib/api/library';
|
||||
import { seedQueueResolver, resolveBatch } from '../utils/library/queueTrackResolver';
|
||||
import { seedQueueResolver, resolveBatch } from '@/features/playback/store/queueTrackResolver';
|
||||
import {
|
||||
applyTimelineBootstrap,
|
||||
getTimelineSessionHistorySnapshot,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { buildStreamUrlForServer } from '@/lib/api/subsonicStreamUrl';
|
||||
import { getPlaybackCacheServerKey } from '@/features/playback/utils/playback/playbackServer';
|
||||
import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes';
|
||||
import { resolveQueueTrack } from './utils/library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { useAuthStore } from './store/authStore';
|
||||
import { selectHotCacheEntries, useHotCacheStore } from '@/features/playback/store/hotCacheStore';
|
||||
|
||||
@@ -9,8 +9,8 @@ import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||
import type { ServerProfile } from '@/store/authStoreTypes';
|
||||
import type { Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { toQueueItemRefs } from '@/utils/library/queueItemRef';
|
||||
import { seedQueueResolver } from '@/utils/library/queueTrackResolver';
|
||||
import { toQueueItemRefs } from '@/features/playback/store/queueItemRef';
|
||||
import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver';
|
||||
let trackCounter = 0;
|
||||
let songCounter = 0;
|
||||
let serverCounter = 0;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { buildDownloadUrl } from '@/lib/api/subsonicStreamUrl';
|
||||
import { useAuthStore } from '../../store/authStore';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import type { Track } from '@/features/playback/store/playerStoreTypes';
|
||||
import { resolveQueueTrack } from '../library/queueTrackView';
|
||||
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import { useZipDownloadStore } from '@/features/offline';
|
||||
import { useDownloadModalStore } from '@/features/offline';
|
||||
import type { EntityShareKind } from '../share/shareLink';
|
||||
|
||||
@@ -2,11 +2,11 @@ import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import { resetPlayerStore } from '@/test/helpers/storeReset';
|
||||
import { makeTrack, seedQueue } from '@/test/helpers/factories';
|
||||
import { seedQueueResolver } from '@/utils/library/queueTrackResolver';
|
||||
import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver';
|
||||
import { playTimelineHistoryTrack } from './playTimelineHistoryTrack';
|
||||
|
||||
vi.mock('@/utils/library/queueTrackResolver', async importOriginal => {
|
||||
const actual = await importOriginal<typeof import('@/utils/library/queueTrackResolver')>();
|
||||
vi.mock('@/features/playback/store/queueTrackResolver', async importOriginal => {
|
||||
const actual = await importOriginal<typeof import('@/features/playback/store/queueTrackResolver')>();
|
||||
return {
|
||||
...actual,
|
||||
resolveBatch: vi.fn(async () => undefined),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||
import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes';
|
||||
import { getQueueTracksView, resolveQueueTrack } from '../library/queueTrackView';
|
||||
import { resolveBatch } from '../library/queueTrackResolver';
|
||||
import { getQueueTracksView, resolveQueueTrack } from '@/features/playback/store/queueTrackView';
|
||||
import { resolveBatch } from '@/features/playback/store/queueTrackResolver';
|
||||
import { findQueueItemRefIndex, sameQueueItemRef } from '@/features/playback/utils/playback/queueIdentity';
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user