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