diff --git a/src/api/coverCache.test.ts b/src/api/coverCache.test.ts index 408a771f..9730ea8a 100644 --- a/src/api/coverCache.test.ts +++ b/src/api/coverCache.test.ts @@ -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(() => { diff --git a/src/app/MainApp.tsx b/src/app/MainApp.tsx index 41ceddd2..cfc782bf 100644 --- a/src/app/MainApp.tsx +++ b/src/app/MainApp.tsx @@ -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'; diff --git a/src/components/MobilePlayerView.tsx b/src/components/MobilePlayerView.tsx index 8fe9db7b..d15494e3 100644 --- a/src/components/MobilePlayerView.tsx +++ b/src/components/MobilePlayerView.tsx @@ -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'; diff --git a/src/cover/usePlaybackCoverArt.test.ts b/src/cover/usePlaybackCoverArt.test.ts index 708eba1b..9139fb76 100644 --- a/src/cover/usePlaybackCoverArt.test.ts +++ b/src/cover/usePlaybackCoverArt.test.ts @@ -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( diff --git a/src/features/fullscreenPlayer/components/FsQueueModal.tsx b/src/features/fullscreenPlayer/components/FsQueueModal.tsx index b2446037..4ff263e9 100644 --- a/src/features/fullscreenPlayer/components/FsQueueModal.tsx +++ b/src/features/fullscreenPlayer/components/FsQueueModal.tsx @@ -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 { diff --git a/src/features/miniPlayer/utils/miniPlayerBridge.ts b/src/features/miniPlayer/utils/miniPlayerBridge.ts index dd916b5f..d3b5926b 100644 --- a/src/features/miniPlayer/utils/miniPlayerBridge.ts +++ b/src/features/miniPlayer/utils/miniPlayerBridge.ts @@ -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'; diff --git a/src/features/miniPlayer/utils/miniPlayerHelpers.ts b/src/features/miniPlayer/utils/miniPlayerHelpers.ts index e05b60d2..f935bb4c 100644 --- a/src/features/miniPlayer/utils/miniPlayerHelpers.ts +++ b/src/features/miniPlayer/utils/miniPlayerHelpers.ts @@ -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'; diff --git a/src/features/nowPlaying/hooks/useNowPlayingPrewarm.test.ts b/src/features/nowPlaying/hooks/useNowPlayingPrewarm.test.ts index 95b767b9..bfc0568f 100644 --- a/src/features/nowPlaying/hooks/useNowPlayingPrewarm.test.ts +++ b/src/features/nowPlaying/hooks/useNowPlayingPrewarm.test.ts @@ -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(); diff --git a/src/features/playback/store/applyQueueHistorySnapshot.ts b/src/features/playback/store/applyQueueHistorySnapshot.ts index 16e4bf19..9164bb49 100644 --- a/src/features/playback/store/applyQueueHistorySnapshot.ts +++ b/src/features/playback/store/applyQueueHistorySnapshot.ts @@ -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'; diff --git a/src/features/playback/store/applyServerPlayQueue.ts b/src/features/playback/store/applyServerPlayQueue.ts index ef186500..90ae83ef 100644 --- a/src/features/playback/store/applyServerPlayQueue.ts +++ b/src/features/playback/store/applyServerPlayQueue.ts @@ -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'; diff --git a/src/features/playback/store/audioEventHandlers.ts b/src/features/playback/store/audioEventHandlers.ts index 57c48952..8d5fe59f 100644 --- a/src/features/playback/store/audioEventHandlers.ts +++ b/src/features/playback/store/audioEventHandlers.ts @@ -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'; diff --git a/src/features/playback/store/b1QueueServerIdentity.test.ts b/src/features/playback/store/b1QueueServerIdentity.test.ts index 93632630..4cdb0f14 100644 --- a/src/features/playback/store/b1QueueServerIdentity.test.ts +++ b/src/features/playback/store/b1QueueServerIdentity.test.ts @@ -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, diff --git a/src/features/playback/store/crossfadePreload.ts b/src/features/playback/store/crossfadePreload.ts index 19357a44..16b87765 100644 --- a/src/features/playback/store/crossfadePreload.ts +++ b/src/features/playback/store/crossfadePreload.ts @@ -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, diff --git a/src/features/playback/store/miscActions.ts b/src/features/playback/store/miscActions.ts index 05dce615..305b3d84 100644 --- a/src/features/playback/store/miscActions.ts +++ b/src/features/playback/store/miscActions.ts @@ -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 { diff --git a/src/features/playback/store/nextAction.ts b/src/features/playback/store/nextAction.ts index d0cf4b3f..37faea25 100644 --- a/src/features/playback/store/nextAction.ts +++ b/src/features/playback/store/nextAction.ts @@ -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, diff --git a/src/features/playback/store/nextActionOrbitRadio.test.ts b/src/features/playback/store/nextActionOrbitRadio.test.ts index 31d92302..8dbcb705 100644 --- a/src/features/playback/store/nextActionOrbitRadio.test.ts +++ b/src/features/playback/store/nextActionOrbitRadio.test.ts @@ -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'; diff --git a/src/features/playback/store/pausedRestorePrepare.test.ts b/src/features/playback/store/pausedRestorePrepare.test.ts index 93e38f1d..354ab35f 100644 --- a/src/features/playback/store/pausedRestorePrepare.test.ts +++ b/src/features/playback/store/pausedRestorePrepare.test.ts @@ -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, diff --git a/src/features/playback/store/pausedRestorePrepare.ts b/src/features/playback/store/pausedRestorePrepare.ts index 4134e739..a100e33b 100644 --- a/src/features/playback/store/pausedRestorePrepare.ts +++ b/src/features/playback/store/pausedRestorePrepare.ts @@ -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'; diff --git a/src/features/playback/store/pendingStarSync.test.ts b/src/features/playback/store/pendingStarSync.test.ts index 55d9dc14..46ec409e 100644 --- a/src/features/playback/store/pendingStarSync.test.ts +++ b/src/features/playback/store/pendingStarSync.test.ts @@ -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, diff --git a/src/features/playback/store/pendingStarSync.ts b/src/features/playback/store/pendingStarSync.ts index 835f0500..2e9edf06 100644 --- a/src/features/playback/store/pendingStarSync.ts +++ b/src/features/playback/store/pendingStarSync.ts @@ -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). diff --git a/src/features/playback/store/playTrackAction.ts b/src/features/playback/store/playTrackAction.ts index 3468ba8a..6a6685bc 100644 --- a/src/features/playback/store/playTrackAction.ts +++ b/src/features/playback/store/playTrackAction.ts @@ -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'; diff --git a/src/features/playback/store/playerStore.ts b/src/features/playback/store/playerStore.ts index a00fcdd7..dc5868e6 100644 --- a/src/features/playback/store/playerStore.ts +++ b/src/features/playback/store/playerStore.ts @@ -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'; diff --git a/src/utils/library/queueItemRef.test.ts b/src/features/playback/store/queueItemRef.test.ts similarity index 100% rename from src/utils/library/queueItemRef.test.ts rename to src/features/playback/store/queueItemRef.test.ts diff --git a/src/utils/library/queueItemRef.ts b/src/features/playback/store/queueItemRef.ts similarity index 94% rename from src/utils/library/queueItemRef.ts rename to src/features/playback/store/queueItemRef.ts index 99fb5e83..dbc79c1e 100644 --- a/src/utils/library/queueItemRef.ts +++ b/src/features/playback/store/queueItemRef.ts @@ -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 diff --git a/src/features/playback/store/queueMutationActions.ts b/src/features/playback/store/queueMutationActions.ts index 498822ba..1261245c 100644 --- a/src/features/playback/store/queueMutationActions.ts +++ b/src/features/playback/store/queueMutationActions.ts @@ -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 { diff --git a/src/features/playback/store/queueResolverBridge.ts b/src/features/playback/store/queueResolverBridge.ts index f35abca8..26a7480c 100644 --- a/src/features/playback/store/queueResolverBridge.ts +++ b/src/features/playback/store/queueResolverBridge.ts @@ -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 diff --git a/src/utils/library/queueRestore.test.ts b/src/features/playback/store/queueRestore.test.ts similarity index 100% rename from src/utils/library/queueRestore.test.ts rename to src/features/playback/store/queueRestore.test.ts diff --git a/src/utils/library/queueRestore.ts b/src/features/playback/store/queueRestore.ts similarity index 95% rename from src/utils/library/queueRestore.ts rename to src/features/playback/store/queueRestore.ts index 1086e834..25602aba 100644 --- a/src/utils/library/queueRestore.ts +++ b/src/features/playback/store/queueRestore.ts @@ -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'; /** diff --git a/src/utils/library/queueTrackResolver.test.ts b/src/features/playback/store/queueTrackResolver.test.ts similarity index 100% rename from src/utils/library/queueTrackResolver.test.ts rename to src/features/playback/store/queueTrackResolver.test.ts diff --git a/src/utils/library/queueTrackResolver.ts b/src/features/playback/store/queueTrackResolver.ts similarity index 96% rename from src/utils/library/queueTrackResolver.ts rename to src/features/playback/store/queueTrackResolver.ts index 60024f36..c03b2cd1 100644 --- a/src/utils/library/queueTrackResolver.ts +++ b/src/features/playback/store/queueTrackResolver.ts @@ -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 diff --git a/src/utils/library/queueTrackView.test.ts b/src/features/playback/store/queueTrackView.test.ts similarity index 97% rename from src/utils/library/queueTrackView.test.ts rename to src/features/playback/store/queueTrackView.test.ts index f884e897..c7e64222 100644 --- a/src/utils/library/queueTrackView.test.ts +++ b/src/features/playback/store/queueTrackView.test.ts @@ -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 => diff --git a/src/utils/library/queueTrackView.ts b/src/features/playback/store/queueTrackView.ts similarity index 100% rename from src/utils/library/queueTrackView.ts rename to src/features/playback/store/queueTrackView.ts diff --git a/src/features/playback/store/queueUndo.test.ts b/src/features/playback/store/queueUndo.test.ts index ebd3f807..048dc9bb 100644 --- a/src/features/playback/store/queueUndo.test.ts +++ b/src/features/playback/store/queueUndo.test.ts @@ -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, diff --git a/src/features/playback/store/resumeAction.ts b/src/features/playback/store/resumeAction.ts index d7457125..5ac2b575 100644 --- a/src/features/playback/store/resumeAction.ts +++ b/src/features/playback/store/resumeAction.ts @@ -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'; diff --git a/src/features/playback/store/skipStarRating.test.ts b/src/features/playback/store/skipStarRating.test.ts index 74f8f8eb..149cbe54 100644 --- a/src/features/playback/store/skipStarRating.test.ts +++ b/src/features/playback/store/skipStarRating.test.ts @@ -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 { return { diff --git a/src/features/playback/store/skipStarRating.ts b/src/features/playback/store/skipStarRating.ts index 1bf0237a..52072be0 100644 --- a/src/features/playback/store/skipStarRating.ts +++ b/src/features/playback/store/skipStarRating.ts @@ -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 diff --git a/src/features/playback/store/updateReplayGainAction.ts b/src/features/playback/store/updateReplayGainAction.ts index 79c4b350..e4faae4d 100644 --- a/src/features/playback/store/updateReplayGainAction.ts +++ b/src/features/playback/store/updateReplayGainAction.ts @@ -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 | ((state: PlayerState) => Partial), diff --git a/src/features/playlist/components/PlaylistSuggestions.tsx b/src/features/playlist/components/PlaylistSuggestions.tsx index 4d8caace..a2b51c9c 100644 --- a/src/features/playlist/components/PlaylistSuggestions.tsx +++ b/src/features/playlist/components/PlaylistSuggestions.tsx @@ -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'; diff --git a/src/features/queue/components/QueueHeader.tsx b/src/features/queue/components/QueueHeader.tsx index 26f99807..5a2ba1ca 100644 --- a/src/features/queue/components/QueueHeader.tsx +++ b/src/features/queue/components/QueueHeader.tsx @@ -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[]; diff --git a/src/features/queue/components/QueueList.tsx b/src/features/queue/components/QueueList.tsx index abea7feb..715040d3 100644 --- a/src/features/queue/components/QueueList.tsx +++ b/src/features/queue/components/QueueList.tsx @@ -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'; diff --git a/src/features/queue/hooks/useQueueTracks.test.ts b/src/features/queue/hooks/useQueueTracks.test.ts index 3cb098e7..92cbd735 100644 --- a/src/features/queue/hooks/useQueueTracks.test.ts +++ b/src/features/queue/hooks/useQueueTracks.test.ts @@ -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'; diff --git a/src/features/queue/hooks/useQueueTracks.ts b/src/features/queue/hooks/useQueueTracks.ts index ddccd37a..0c5f8f71 100644 --- a/src/features/queue/hooks/useQueueTracks.ts +++ b/src/features/queue/hooks/useQueueTracks.ts @@ -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: diff --git a/src/hooks/tauriBridge/usePlayerSnapshotPublisher.ts b/src/hooks/tauriBridge/usePlayerSnapshotPublisher.ts index 8d60dc9e..17aceab8 100644 --- a/src/hooks/tauriBridge/usePlayerSnapshotPublisher.ts +++ b/src/hooks/tauriBridge/usePlayerSnapshotPublisher.ts @@ -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). */ diff --git a/src/hooks/useTimelinePlayHistory.test.ts b/src/hooks/useTimelinePlayHistory.test.ts index b47043c7..df764206 100644 --- a/src/hooks/useTimelinePlayHistory.test.ts +++ b/src/hooks/useTimelinePlayHistory.test.ts @@ -17,8 +17,8 @@ vi.mock('../utils/queue/timelineBootstrapReady', () => ({ timelineBootstrapIndexReady: vi.fn(), })); -vi.mock('../utils/library/queueTrackResolver', async importOriginal => { - const actual = await importOriginal(); +vi.mock('@/features/playback/store/queueTrackResolver', async importOriginal => { + const actual = await importOriginal(); return { ...actual, seedQueueResolver: vi.fn() }; }); diff --git a/src/hooks/useTimelinePlayHistory.ts b/src/hooks/useTimelinePlayHistory.ts index a9e3ee2b..0f6185fe 100644 --- a/src/hooks/useTimelinePlayHistory.ts +++ b/src/hooks/useTimelinePlayHistory.ts @@ -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, diff --git a/src/hotCachePrefetch.ts b/src/hotCachePrefetch.ts index 18c513fa..b267a1dd 100644 --- a/src/hotCachePrefetch.ts +++ b/src/hotCachePrefetch.ts @@ -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'; diff --git a/src/test/helpers/factories.ts b/src/test/helpers/factories.ts index db25610a..36a7bbf8 100644 --- a/src/test/helpers/factories.ts +++ b/src/test/helpers/factories.ts @@ -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; diff --git a/src/utils/componentHelpers/contextMenuActions.ts b/src/utils/componentHelpers/contextMenuActions.ts index 9d6b8e5a..6cfb483e 100644 --- a/src/utils/componentHelpers/contextMenuActions.ts +++ b/src/utils/componentHelpers/contextMenuActions.ts @@ -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'; diff --git a/src/utils/queue/playTimelineHistoryTrack.test.ts b/src/utils/queue/playTimelineHistoryTrack.test.ts index 687ff7fd..db69d453 100644 --- a/src/utils/queue/playTimelineHistoryTrack.test.ts +++ b/src/utils/queue/playTimelineHistoryTrack.test.ts @@ -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(); +vi.mock('@/features/playback/store/queueTrackResolver', async importOriginal => { + const actual = await importOriginal(); return { ...actual, resolveBatch: vi.fn(async () => undefined), diff --git a/src/utils/queue/playTimelineHistoryTrack.ts b/src/utils/queue/playTimelineHistoryTrack.ts index 20ba60bd..b7f76e31 100644 --- a/src/utils/queue/playTimelineHistoryTrack.ts +++ b/src/utils/queue/playTimelineHistoryTrack.ts @@ -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'; /**