From 9058abd340e5d3c5eddda518531dfcc6751630f5 Mon Sep 17 00:00:00 2001 From: Psychotoxical <171614930+Psychotoxical@users.noreply.github.com> Date: Tue, 30 Jun 2026 17:16:56 +0200 Subject: [PATCH] refactor(lib): extract Track/QueueItemRef domain model to lib/media/trackTypes Track is the app's normalized song model and QueueItemRef its thin queue identity -- consumed app-wide (queue, cover, context menus, sharing, lucky-mix, library browse), not a playback-internal detail. They lived in features/playback/store/playerStoreTypes, forcing ~115 core/feature files to reach into the playback feature for the central media type. Move the two interfaces to lib/media/trackTypes; playerStoreTypes keeps PlayerState and now imports them from lib. 115 importers repointed (mixed 'PlayerState, Track' lines split so PlayerState stays). Pure type move (erased at runtime). tsc 0, lint 0. --- src/components/ContextMenu.tsx | 2 +- src/components/LyricsPane.tsx | 2 +- src/components/MobilePlayerView.tsx | 2 +- .../contextMenu/QueueItemContextItems.tsx | 2 +- .../contextMenu/SongContextItems.tsx | 2 +- .../contextMenu/contextMenuItemTypes.ts | 2 +- .../folderBrowser/FolderBrowserColumn.tsx | 2 +- src/components/playerBar/PlayerTrackInfo.tsx | 3 +- .../randomMix/RandomMixTrackRow.tsx | 2 +- .../album/components/AlbumTrackList.tsx | 2 +- .../album/components/AlbumTrackListMobile.tsx | 2 +- src/features/album/components/TrackRow.tsx | 2 +- .../artist/utils/runArtistDetailPlay.ts | 2 +- .../components/FsLyricsApple.tsx | 2 +- .../components/FsQueueModal.tsx | 2 +- .../miniPlayer/utils/miniPlayerBridge.ts | 2 +- .../miniPlayer/utils/miniPlayerHelpers.ts | 2 +- .../nowPlaying/hooks/useNowPlayingStarLove.ts | 2 +- .../offline/utils/offlineLibraryHelpers.ts | 2 +- .../store/applyQueueHistorySnapshot.ts | 3 +- .../store/applyServerPlayQueue.idle.test.ts | 2 +- .../playback/store/applyServerPlayQueue.ts | 2 +- .../playback/store/audioEventHandlers.ts | 2 +- .../store/b1QueueServerIdentity.test.ts | 3 +- .../playback/store/crossfadePreload.ts | 2 +- .../store/engineLoadTrackAtPosition.ts | 2 +- src/features/playback/store/hotCacheStore.ts | 2 +- .../store/loudnessBackfillWindow.test.ts | 2 +- .../playback/store/loudnessBackfillWindow.ts | 2 +- .../playback/store/loudnessPrefetch.test.ts | 2 +- .../playback/store/loudnessPrefetch.ts | 2 +- src/features/playback/store/nextAction.ts | 3 +- .../store/normalizationSnapshot.test.ts | 2 +- .../playback/store/normalizationSnapshot.ts | 3 +- .../store/pausedRestorePrepare.test.ts | 2 +- .../playback/store/pausedRestorePrepare.ts | 2 +- .../playback/store/pendingStarSync.test.ts | 2 +- .../playback/store/playListenSession.test.ts | 2 +- .../playback/store/playListenSession.ts | 2 +- .../playback/store/playTrackAction.ts | 3 +- src/features/playback/store/playerStore.ts | 3 +- .../playback/store/playerStoreTypes.ts | 54 +---------------- .../playback/store/promoteStreamCache.test.ts | 2 +- .../playback/store/promoteStreamCache.ts | 2 +- .../playback/store/queueItemRef.test.ts | 2 +- src/features/playback/store/queueItemRef.ts | 2 +- .../playback/store/queueMutationActions.ts | 3 +- .../playback/store/queueRestore.test.ts | 2 +- src/features/playback/store/queueRestore.ts | 2 +- src/features/playback/store/queueSync.test.ts | 2 +- src/features/playback/store/queueSync.ts | 2 +- .../playback/store/queueTrackResolver.test.ts | 2 +- .../playback/store/queueTrackResolver.ts | 2 +- .../playback/store/queueTrackView.test.ts | 2 +- src/features/playback/store/queueTrackView.ts | 2 +- src/features/playback/store/queueUndo.test.ts | 3 +- src/features/playback/store/queueUndo.ts | 3 +- .../store/queueUndoAudioRestore.test.ts | 2 +- .../playback/store/queueUndoAudioRestore.ts | 2 +- .../playback/store/skipStarRating.test.ts | 2 +- src/features/playback/store/skipStarRating.ts | 2 +- .../playback/store/timelineSessionHistory.ts | 2 +- .../utils/audio/resolveReplayGainDb.test.ts | 2 +- .../utils/audio/resolveReplayGainDb.ts | 2 +- .../utils/playback/autodjAutoAdvance.test.ts | 2 +- .../utils/playback/autodjAutoAdvance.ts | 2 +- .../playback/autodjInterruptPrep.test.ts | 2 +- .../utils/playback/autodjInterruptPrep.ts | 2 +- .../buildInfiniteQueueCandidates.test.ts | 2 +- .../playback/buildInfiniteQueueCandidates.ts | 2 +- .../utils/playback/genreBrowsePlayback.ts | 2 +- .../playback/utils/playback/playAlbum.test.ts | 2 +- .../playback/utils/playback/playAlbum.ts | 2 +- .../playback/utils/playback/playbackServer.ts | 2 +- .../utils/playback/queueIdentity.test.ts | 2 +- .../playback/utils/playback/queueIdentity.ts | 2 +- .../utils/playback/runBulkPlay.test.ts | 2 +- .../playback/utils/playback/runBulkPlay.ts | 2 +- .../utils/playback/songToTrack.test.ts | 2 +- .../playback/utils/playback/songToTrack.ts | 2 +- .../utils/playback/trackArtistRefs.test.ts | 2 +- .../utils/playback/trackArtistRefs.ts | 2 +- .../utils/playback/trackServerScope.test.ts | 2 +- .../utils/playback/trackServerScope.ts | 2 +- .../playlist/components/PlaylistTracklist.tsx | 2 +- .../hooks/usePlaylistBulkPlayCallbacks.ts | 2 +- .../playlist/hooks/usePlaylistDerived.ts | 2 +- .../utils/playlistBulkPlayActions.test.ts | 2 +- .../playlist/utils/playlistBulkPlayActions.ts | 2 +- .../queue/components/QueueCurrentTrack.tsx | 2 +- src/features/queue/components/QueueHeader.tsx | 2 +- src/features/queue/components/QueueList.tsx | 3 +- src/features/queue/components/QueuePanel.tsx | 2 +- .../queue/components/QueueToolbar.tsx | 2 +- .../queue/hooks/useQueueAutoScroll.ts | 2 +- src/features/queue/hooks/useQueuePanelDrag.ts | 2 +- .../queue/hooks/useQueueTracks.test.ts | 2 +- src/features/queue/hooks/useQueueTracks.ts | 2 +- src/hooks/useContextMenuRating.ts | 2 +- src/hooks/useFolderBrowserNowPlayingPath.ts | 2 +- src/hooks/useLyrics.ts | 2 +- src/hooks/useNowPlayingTrayTitle.ts | 2 +- src/hooks/useWordLyricsSync.ts | 2 +- src/hotCachePrefetch.ts | 2 +- src/hotCachePrefetch/helpers.ts | 2 +- src/lib/media/trackTypes.ts | 60 +++++++++++++++++++ src/store/localPlaybackStore.ts | 2 +- src/test/helpers/factories.ts | 2 +- .../componentHelpers/contextMenuActions.ts | 2 +- .../componentHelpers/folderBrowserHelpers.ts | 2 +- .../componentHelpers/queuePanelHelpers.tsx | 2 +- src/utils/mix/luckyMix.ts | 2 +- .../queue/buildTimelineDisplayRows.test.ts | 2 +- src/utils/queue/buildTimelineDisplayRows.ts | 2 +- src/utils/queue/playTimelineHistoryTrack.ts | 2 +- src/utils/queue/timelineHistoryRefs.ts | 4 +- src/utils/share/enqueueShareSearchPayload.ts | 2 +- 117 files changed, 189 insertions(+), 168 deletions(-) create mode 100644 src/lib/media/trackTypes.ts diff --git a/src/components/ContextMenu.tsx b/src/components/ContextMenu.tsx index f8a6f8e2..a0b91dd1 100644 --- a/src/components/ContextMenu.tsx +++ b/src/components/ContextMenu.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { useOrbitStore } from '@/features/orbit'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { useShallow } from 'zustand/react/shallow'; diff --git a/src/components/LyricsPane.tsx b/src/components/LyricsPane.tsx index 5b049cef..7848d1af 100644 --- a/src/components/LyricsPane.tsx +++ b/src/components/LyricsPane.tsx @@ -6,7 +6,7 @@ import type { LrcLine } from '../api/lrclib'; import { useLyrics, type WordLyricsLine } from '../hooks/useLyrics'; import { useAuthStore } from '../store/authStore'; import { useTranslation } from 'react-i18next'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { EaseScroller, targetForFraction } from '../utils/ui/easeScroll'; import OverlayScrollArea from '@/ui/OverlayScrollArea'; diff --git a/src/components/MobilePlayerView.tsx b/src/components/MobilePlayerView.tsx index d15494e3..4c6fe7c0 100644 --- a/src/components/MobilePlayerView.tsx +++ b/src/components/MobilePlayerView.tsx @@ -1,7 +1,7 @@ import { queueSongStar } from '@/features/playback/store/pendingStarSync'; import { usePlaybackCoverArt } from '../hooks/usePlaybackCoverArt'; import { usePlaybackTrackCoverRef } from '../cover/useLibraryCoverRef'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '@/features/playback/store/playbackProgress'; import React, { useState, useCallback, useRef, useEffect, useSyncExternalStore, CSSProperties } from 'react'; import { useNavigate } from 'react-router-dom'; diff --git a/src/components/contextMenu/QueueItemContextItems.tsx b/src/components/contextMenu/QueueItemContextItems.tsx index 92f50120..1d7f2805 100644 --- a/src/components/contextMenu/QueueItemContextItems.tsx +++ b/src/components/contextMenu/QueueItemContextItems.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next'; import { Play, Radio, Heart, ChevronRight, User, Disc3, ListMusic, Info, Sparkles, Star, Trash2, Share2 } from 'lucide-react'; import { queueSongStar } from '@/features/playback/store/pendingStarSync'; import { getMusicNetworkRuntime, useEnrichmentPrimary } from '../../music-network'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { useAuthStore } from '../../store/authStore'; import { renderPresetIcon } from '../settings/musicNetwork/presetIcon'; import StarRating from '../StarRating'; diff --git a/src/components/contextMenu/SongContextItems.tsx b/src/components/contextMenu/SongContextItems.tsx index 471194d8..845474a3 100644 --- a/src/components/contextMenu/SongContextItems.tsx +++ b/src/components/contextMenu/SongContextItems.tsx @@ -5,7 +5,7 @@ import { useNavigateToArtist } from '@/features/artist'; import { resolveAlbum, resolveMediaServerId, resolvePlaylist } from '@/features/offline'; import { queueSongStar } from '@/features/playback/store/pendingStarSync'; import { getMusicNetworkRuntime, useEnrichmentPrimary } from '../../music-network'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { useAuthStore } from '../../store/authStore'; import { usePlaylistStore } from '@/features/playlist'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; diff --git a/src/components/contextMenu/contextMenuItemTypes.ts b/src/components/contextMenu/contextMenuItemTypes.ts index 8e90e054..12412c0e 100644 --- a/src/components/contextMenu/contextMenuItemTypes.ts +++ b/src/components/contextMenu/contextMenuItemTypes.ts @@ -1,6 +1,6 @@ import type React from 'react'; import type { SubsonicAlbum, SubsonicArtist } from '@/lib/api/subsonicTypes'; -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import type { EntityShareKind } from '../../utils/share/shareLink'; import type { OfflineActionPolicy } from '@/features/offline'; diff --git a/src/components/folderBrowser/FolderBrowserColumn.tsx b/src/components/folderBrowser/FolderBrowserColumn.tsx index 2d9d6790..df90aba1 100644 --- a/src/components/folderBrowser/FolderBrowserColumn.tsx +++ b/src/components/folderBrowser/FolderBrowserColumn.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { ChevronRight, Folder, FolderOpen, Music } from 'lucide-react'; import type { SubsonicDirectoryEntry } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { folderBrowserHasKeyModifiers, isFolderBrowserArrowKey, type Column, diff --git a/src/components/playerBar/PlayerTrackInfo.tsx b/src/components/playerBar/PlayerTrackInfo.tsx index 31650067..c4bbcd1b 100644 --- a/src/components/playerBar/PlayerTrackInfo.tsx +++ b/src/components/playerBar/PlayerTrackInfo.tsx @@ -2,7 +2,8 @@ import { Cast, Heart, Maximize2, Music } from 'lucide-react'; import type { TFunction } from 'i18next'; import { queueSongRating } from '@/features/playback/store/pendingStarSync'; import type { InternetRadioStation, SubsonicOpenArtistRef } from '@/lib/api/subsonicTypes'; -import type { PlayerState, Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; import type { RadioMetadata } from '@/features/radio'; import type { PreviewingTrack } from '@/features/playback/store/previewStore'; import { CoverArtImage } from '../../cover/CoverArtImage'; diff --git a/src/components/randomMix/RandomMixTrackRow.tsx b/src/components/randomMix/RandomMixTrackRow.tsx index c88bf99e..abbe8c8a 100644 --- a/src/components/randomMix/RandomMixTrackRow.tsx +++ b/src/components/randomMix/RandomMixTrackRow.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { AudioLines, ChevronRight, Heart, Play, Square } from 'lucide-react'; import type { SubsonicSong } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { previewInputFromSong, usePreviewStore } from '@/features/playback/store/previewStore'; import { useDragDrop } from '@/lib/dnd/DragDropContext'; import { formatRandomMixDuration } from '../../utils/componentHelpers/randomMixHelpers'; diff --git a/src/features/album/components/AlbumTrackList.tsx b/src/features/album/components/AlbumTrackList.tsx index d388e574..ad129736 100644 --- a/src/features/album/components/AlbumTrackList.tsx +++ b/src/features/album/components/AlbumTrackList.tsx @@ -1,5 +1,5 @@ import type { SubsonicSong } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import React, { useMemo, useState, useEffect } from 'react'; import { useTracklistColumns } from '@/utils/useTracklistColumns'; import { usePlayerStore } from '@/features/playback/store/playerStore'; diff --git a/src/features/album/components/AlbumTrackListMobile.tsx b/src/features/album/components/AlbumTrackListMobile.tsx index 1c9dc55c..72de6807 100644 --- a/src/features/album/components/AlbumTrackListMobile.tsx +++ b/src/features/album/components/AlbumTrackListMobile.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { AudioLines } from 'lucide-react'; import type { SubsonicSong } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; import { formatLongDuration } from '@/lib/format/formatDuration'; diff --git a/src/features/album/components/TrackRow.tsx b/src/features/album/components/TrackRow.tsx index fa6c1ea8..ce0c52fa 100644 --- a/src/features/album/components/TrackRow.tsx +++ b/src/features/album/components/TrackRow.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import type { ColDef } from '@/utils/useTracklistColumns'; import type { SubsonicSong } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; import { useSelectionStore } from '@/store/selectionStore'; import { useThemeStore } from '@/store/themeStore'; diff --git a/src/features/artist/utils/runArtistDetailPlay.ts b/src/features/artist/utils/runArtistDetailPlay.ts index 58086803..ca8c15ec 100644 --- a/src/features/artist/utils/runArtistDetailPlay.ts +++ b/src/features/artist/utils/runArtistDetailPlay.ts @@ -1,7 +1,7 @@ import type { TFunction } from 'i18next'; import { getSimilarSongs2, getTopSongs } from '@/lib/api/subsonicArtists'; import type { SubsonicAlbum, SubsonicArtist, SubsonicSong } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; import { runBulkPlayAll, runBulkShuffle } from '@/features/playback/utils/playback/runBulkPlay'; import { resolveAlbum, resolveMediaServerId } from '@/features/offline'; diff --git a/src/features/fullscreenPlayer/components/FsLyricsApple.tsx b/src/features/fullscreenPlayer/components/FsLyricsApple.tsx index dea028d5..f31d0c42 100644 --- a/src/features/fullscreenPlayer/components/FsLyricsApple.tsx +++ b/src/features/fullscreenPlayer/components/FsLyricsApple.tsx @@ -5,7 +5,7 @@ import { useLyrics, type WordLyricsLine } from '@/hooks/useLyrics'; import { useWordLyricsSync } from '@/hooks/useWordLyricsSync'; import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '@/features/playback/store/playbackProgress'; import type { LrcLine } from '@/api/lrclib'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { EaseScroller, targetForFraction } from '@/utils/ui/easeScroll'; // Fullscreen synced lyrics. diff --git a/src/features/fullscreenPlayer/components/FsQueueModal.tsx b/src/features/fullscreenPlayer/components/FsQueueModal.tsx index 4ff263e9..81a00870 100644 --- a/src/features/fullscreenPlayer/components/FsQueueModal.tsx +++ b/src/features/fullscreenPlayer/components/FsQueueModal.tsx @@ -2,7 +2,7 @@ import { memo, useMemo, useSyncExternalStore } from 'react'; 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 type { Track } from '@/lib/media/trackTypes'; import { resolveQueueTrack } from '@/features/playback/store/queueTrackView'; import { getQueueResolverVersion, diff --git a/src/features/miniPlayer/utils/miniPlayerBridge.ts b/src/features/miniPlayer/utils/miniPlayerBridge.ts index d3b5926b..eab7e078 100644 --- a/src/features/miniPlayer/utils/miniPlayerBridge.ts +++ b/src/features/miniPlayer/utils/miniPlayerBridge.ts @@ -5,7 +5,7 @@ import { useAuthStore } from '@/store/authStore'; import { setTransitionMode, type TransitionMode } from '@/features/playback/utils/playback/playbackTransition'; import { resolveQueueTrack } from '@/features/playback/store/queueTrackView'; import type { SubsonicOpenArtistRef } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; export const MINI_WINDOW_LABEL = 'mini'; diff --git a/src/features/miniPlayer/utils/miniPlayerHelpers.ts b/src/features/miniPlayer/utils/miniPlayerHelpers.ts index f935bb4c..714159f4 100644 --- a/src/features/miniPlayer/utils/miniPlayerHelpers.ts +++ b/src/features/miniPlayer/utils/miniPlayerHelpers.ts @@ -1,7 +1,7 @@ import { usePlayerStore } from '@/features/playback/store/playerStore'; import { resolveQueueTrack } from '@/features/playback/store/queueTrackView'; import type { MiniSyncPayload, MiniTrackInfo } from '@/features/miniPlayer/utils/miniPlayerBridge'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; /** Half-width of the mini initial-snapshot queue window (matches the bridge). */ const MINI_SNAPSHOT_HALF = 100; diff --git a/src/features/nowPlaying/hooks/useNowPlayingStarLove.ts b/src/features/nowPlaying/hooks/useNowPlayingStarLove.ts index f70a4ebc..5cd08bb8 100644 --- a/src/features/nowPlaying/hooks/useNowPlayingStarLove.ts +++ b/src/features/nowPlaying/hooks/useNowPlayingStarLove.ts @@ -1,7 +1,7 @@ import { useCallback, useEffect, useState } from 'react'; import { queueSongStar } from '@/features/playback/store/pendingStarSync'; import type { SubsonicSong } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import type { TrackStats } from '@/music-network'; import { getMusicNetworkRuntime } from '@/music-network'; diff --git a/src/features/offline/utils/offlineLibraryHelpers.ts b/src/features/offline/utils/offlineLibraryHelpers.ts index d5d6f17e..de73a8ce 100644 --- a/src/features/offline/utils/offlineLibraryHelpers.ts +++ b/src/features/offline/utils/offlineLibraryHelpers.ts @@ -9,7 +9,7 @@ import { findLocalPlaybackEntry, hasLocalLibraryBytes } from '@/store/localPlayb import { useOfflineStore, type OfflineAlbumMeta } from '@/features/offline/store/offlineStore'; import { resolveTrackCoverArtId, trackToSong } from '@/lib/library/advancedSearchLocal'; import { canonicalQueueServerKey, resolveIndexKey } from '@/utils/server/serverIndexKey'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { findServerByIdOrIndexKey, resolveServerIdForIndexKey } from '@/utils/server/serverLookup'; import { serverIndexKeyForProfile } from '@/utils/server/serverIndexKey'; diff --git a/src/features/playback/store/applyQueueHistorySnapshot.ts b/src/features/playback/store/applyQueueHistorySnapshot.ts index 9164bb49..2a611169 100644 --- a/src/features/playback/store/applyQueueHistorySnapshot.ts +++ b/src/features/playback/store/applyQueueHistorySnapshot.ts @@ -9,7 +9,8 @@ import { } from '@/features/playback/store/engineState'; import { clearPreloadingIds } from '@/features/playback/store/gaplessPreloadState'; import { deriveNormalizationSnapshot } from '@/features/playback/store/normalizationSnapshot'; -import type { PlayerState, QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; import { resolveQueueTrack } from '@/features/playback/store/queueTrackView'; import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver'; import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey'; diff --git a/src/features/playback/store/applyServerPlayQueue.idle.test.ts b/src/features/playback/store/applyServerPlayQueue.idle.test.ts index 8cd9fa30..dbf404ab 100644 --- a/src/features/playback/store/applyServerPlayQueue.idle.test.ts +++ b/src/features/playback/store/applyServerPlayQueue.idle.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; const getPlayQueueForServerMock = vi.fn(); diff --git a/src/features/playback/store/applyServerPlayQueue.ts b/src/features/playback/store/applyServerPlayQueue.ts index 90ae83ef..b995259d 100644 --- a/src/features/playback/store/applyServerPlayQueue.ts +++ b/src/features/playback/store/applyServerPlayQueue.ts @@ -4,7 +4,7 @@ import { bindQueueServerId } from '@/features/playback/utils/playback/playbackSe import { resolveServerIdForIndexKey } from '@/utils/server/serverLookup'; import { toQueueItemRefs } from '@/features/playback/store/queueItemRef'; import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { useAuthStore } from '@/store/authStore'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { preparePausedRestoreOnStartup } from '@/features/playback/store/pausedRestorePrepare'; diff --git a/src/features/playback/store/audioEventHandlers.ts b/src/features/playback/store/audioEventHandlers.ts index 8d5fe59f..a35e06d7 100644 --- a/src/features/playback/store/audioEventHandlers.ts +++ b/src/features/playback/store/audioEventHandlers.ts @@ -1,5 +1,5 @@ import { scrobbleSong } from '@/lib/api/subsonicScrobble'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { playbackReportPlaying, playbackReportStart, diff --git a/src/features/playback/store/b1QueueServerIdentity.test.ts b/src/features/playback/store/b1QueueServerIdentity.test.ts index 4cdb0f14..72ee9f59 100644 --- a/src/features/playback/store/b1QueueServerIdentity.test.ts +++ b/src/features/playback/store/b1QueueServerIdentity.test.ts @@ -28,7 +28,8 @@ import { pushQueueUndoSnapshot, type QueueUndoSnapshot, } from '@/features/playback/store/queueUndo'; -import type { PlayerState, QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; import { savePlayQueue } from '@/lib/api/subsonicPlayQueue'; import { _resetQueueSyncForTest, flushPlayQueuePosition } from '@/features/playback/store/queueSync'; diff --git a/src/features/playback/store/crossfadePreload.ts b/src/features/playback/store/crossfadePreload.ts index 16b87765..1246840c 100644 --- a/src/features/playback/store/crossfadePreload.ts +++ b/src/features/playback/store/crossfadePreload.ts @@ -6,7 +6,7 @@ import { findLocalPlaybackUrl } from '@/store/localPlaybackResolve'; import { playbackCacheKeyForRef } from '@/features/playback/utils/playback/playbackServer'; import { resolvePlaybackUrl } from '@/features/playback/utils/playback/resolvePlaybackUrl'; import { resolveQueueTrack } from '@/features/playback/store/queueTrackView'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { hasPlannedCrossfade, markPlannedCrossfade, diff --git a/src/features/playback/store/engineLoadTrackAtPosition.ts b/src/features/playback/store/engineLoadTrackAtPosition.ts index a802d4c7..900600c7 100644 --- a/src/features/playback/store/engineLoadTrackAtPosition.ts +++ b/src/features/playback/store/engineLoadTrackAtPosition.ts @@ -1,4 +1,4 @@ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { invoke } from '@tauri-apps/api/core'; import { setDeferHotCachePrefetch } from '@/utils/cache/hotCacheGate'; import { diff --git a/src/features/playback/store/hotCacheStore.ts b/src/features/playback/store/hotCacheStore.ts index d99bebe8..05064ebc 100644 --- a/src/features/playback/store/hotCacheStore.ts +++ b/src/features/playback/store/hotCacheStore.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import { create } from 'zustand'; import type { HotCacheEntry } from '@/features/playback/store/hotCacheStoreTypes'; import { useLocalPlaybackStore, type LocalPlaybackEntry } from '@/store/localPlaybackStore'; diff --git a/src/features/playback/store/loudnessBackfillWindow.test.ts b/src/features/playback/store/loudnessBackfillWindow.test.ts index 138b0372..fbc8369e 100644 --- a/src/features/playback/store/loudnessBackfillWindow.test.ts +++ b/src/features/playback/store/loudnessBackfillWindow.test.ts @@ -4,7 +4,7 @@ * = current track + next `LOUDNESS_BACKFILL_WINDOW_AHEAD` entries, with * duplicates collapsed. */ -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { describe, expect, it } from 'vitest'; import { LOUDNESS_BACKFILL_WINDOW_AHEAD, diff --git a/src/features/playback/store/loudnessBackfillWindow.ts b/src/features/playback/store/loudnessBackfillWindow.ts index 2d488e6f..a03d0b24 100644 --- a/src/features/playback/store/loudnessBackfillWindow.ts +++ b/src/features/playback/store/loudnessBackfillWindow.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; /** * After a bulk enqueue (queue replace, append-many, lucky-mix) the runtime * warms the loudness cache for the current track + the next N entries so diff --git a/src/features/playback/store/loudnessPrefetch.test.ts b/src/features/playback/store/loudnessPrefetch.test.ts index 005773e5..1ed07667 100644 --- a/src/features/playback/store/loudnessPrefetch.test.ts +++ b/src/features/playback/store/loudnessPrefetch.test.ts @@ -4,7 +4,7 @@ * guard, the window collection, and the no-sync-engine flag on each * refresh call. */ -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { beforeEach, describe, expect, it, vi } from 'vitest'; const hoisted = vi.hoisted(() => { const auth = { normalizationEngine: 'loudness' as 'off' | 'replaygain' | 'loudness' }; diff --git a/src/features/playback/store/loudnessPrefetch.ts b/src/features/playback/store/loudnessPrefetch.ts index 2e0a1e82..d69dd34a 100644 --- a/src/features/playback/store/loudnessPrefetch.ts +++ b/src/features/playback/store/loudnessPrefetch.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import { useAuthStore } from '@/store/authStore'; import { collectLoudnessBackfillWindowTrackIds } from '@/features/playback/store/loudnessBackfillWindow'; import { refreshLoudnessForTrack } from '@/features/playback/store/loudnessRefresh'; diff --git a/src/features/playback/store/nextAction.ts b/src/features/playback/store/nextAction.ts index 37faea25..c53f34ab 100644 --- a/src/features/playback/store/nextAction.ts +++ b/src/features/playback/store/nextAction.ts @@ -10,7 +10,8 @@ import { setInfiniteQueueFetching, } from '@/features/playback/store/infiniteQueueState'; import { isInOrbitSession } from '@/store/orbitRuntime'; -import type { PlayerState, QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; import { toQueueItemRefs } from '@/features/playback/store/queueItemRef'; import { resolveQueueTrack } from '@/features/playback/store/queueTrackView'; import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver'; diff --git a/src/features/playback/store/normalizationSnapshot.test.ts b/src/features/playback/store/normalizationSnapshot.test.ts index 8e8bf22a..da66a949 100644 --- a/src/features/playback/store/normalizationSnapshot.test.ts +++ b/src/features/playback/store/normalizationSnapshot.test.ts @@ -4,7 +4,7 @@ * album-mode resolution). useAuthStore is mocked through a hoisted state * object so each test can flip flags without rebuilding the store. */ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { beforeEach, describe, expect, it, vi } from 'vitest'; const { authState } = vi.hoisted(() => ({ authState: { diff --git a/src/features/playback/store/normalizationSnapshot.ts b/src/features/playback/store/normalizationSnapshot.ts index 76bf80b6..fea1e8bf 100644 --- a/src/features/playback/store/normalizationSnapshot.ts +++ b/src/features/playback/store/normalizationSnapshot.ts @@ -1,4 +1,5 @@ -import type { PlayerState, Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; import { useAuthStore } from '@/store/authStore'; import { resolveReplayGainDb } from '@/features/playback/utils/audio/resolveReplayGainDb'; /** diff --git a/src/features/playback/store/pausedRestorePrepare.test.ts b/src/features/playback/store/pausedRestorePrepare.test.ts index 354ab35f..d674db17 100644 --- a/src/features/playback/store/pausedRestorePrepare.test.ts +++ b/src/features/playback/store/pausedRestorePrepare.test.ts @@ -1,4 +1,4 @@ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { beforeEach, describe, expect, it, vi } from 'vitest'; const hoisted = vi.hoisted(() => ({ diff --git a/src/features/playback/store/pausedRestorePrepare.ts b/src/features/playback/store/pausedRestorePrepare.ts index a100e33b..e6cce755 100644 --- a/src/features/playback/store/pausedRestorePrepare.ts +++ b/src/features/playback/store/pausedRestorePrepare.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { getQueueTracksView } from '@/features/playback/store/queueTrackView'; import { scheduleHotCachePrefetchForTrack } from '@/hotCachePrefetch'; import { getPlaybackCacheServerKey } from '@/features/playback/utils/playback/playbackServer'; diff --git a/src/features/playback/store/pendingStarSync.test.ts b/src/features/playback/store/pendingStarSync.test.ts index 46ec409e..c6bf9e38 100644 --- a/src/features/playback/store/pendingStarSync.test.ts +++ b/src/features/playback/store/pendingStarSync.test.ts @@ -10,7 +10,7 @@ vi.mock('@/lib/api/subsonicStarRating', () => ({ })); import { usePlayerStore } from '@/features/playback/store/playerStore'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { queueSongStar, queueSongRating, _resetPendingStarSyncForTest } from '@/features/playback/store/pendingStarSync'; import { getCachedTrack, diff --git a/src/features/playback/store/playListenSession.test.ts b/src/features/playback/store/playListenSession.test.ts index 767aa252..c38e981b 100644 --- a/src/features/playback/store/playListenSession.test.ts +++ b/src/features/playback/store/playListenSession.test.ts @@ -22,7 +22,7 @@ vi.mock('@/features/playback/utils/playback/playbackServer', () => ({ getPlaybackServerId: vi.fn(() => 'server-1'), })); -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; const testTrack: Track = { id: 't1', diff --git a/src/features/playback/store/playListenSession.ts b/src/features/playback/store/playListenSession.ts index 7a3ffa84..3f97ccbb 100644 --- a/src/features/playback/store/playListenSession.ts +++ b/src/features/playback/store/playListenSession.ts @@ -1,4 +1,4 @@ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { usePreviewStore } from '@/features/playback/store/previewStore'; import { diff --git a/src/features/playback/store/playTrackAction.ts b/src/features/playback/store/playTrackAction.ts index 6a6685bc..d923caff 100644 --- a/src/features/playback/store/playTrackAction.ts +++ b/src/features/playback/store/playTrackAction.ts @@ -57,7 +57,8 @@ import { playbackSourceHintForResolvedUrl, recordEnginePlayUrl, } from '@/features/playback/store/playbackUrlRouting'; -import type { PlayerState, Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; import { toQueueItemRefs } from '@/features/playback/store/queueItemRef'; import { getQueueTracksView, resolveQueueTrack } from '@/features/playback/store/queueTrackView'; import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver'; diff --git a/src/features/playback/store/playerStore.ts b/src/features/playback/store/playerStore.ts index dc5868e6..76c0b5c1 100644 --- a/src/features/playback/store/playerStore.ts +++ b/src/features/playback/store/playerStore.ts @@ -4,7 +4,8 @@ import { readInitialNetworkLovedCache, persistNetworkLovedCache } from '@/featur import { readInitialPlayerPrefs, persistPlayerPrefs } from '@/features/playback/store/playerPrefsStorage'; 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 type { QueueItemRef, Track } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; import { toQueueItemRefs } from '@/features/playback/store/queueItemRef'; import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey'; import { readInitialQueueVisibility } from '@/features/playback/store/queueVisibilityStorage'; diff --git a/src/features/playback/store/playerStoreTypes.ts b/src/features/playback/store/playerStoreTypes.ts index 85b81c10..93e1747a 100644 --- a/src/features/playback/store/playerStoreTypes.ts +++ b/src/features/playback/store/playerStoreTypes.ts @@ -1,56 +1,6 @@ -import type { InternetRadioStation, SubsonicOpenArtistRef } from '@/lib/api/subsonicTypes'; +import type { InternetRadioStation } from '@/lib/api/subsonicTypes'; import type { PlaybackSourceKind } from '@/features/playback/utils/playback/resolvePlaybackUrl'; - -export interface Track { - id: string; - title: string; - artist: string; - album: string; - albumId: string; - artistId?: string; - /** OpenSubsonic `artists` on the child song — multiple performers with ids. */ - artists?: SubsonicOpenArtistRef[]; - duration: number; - coverArt?: string; - discNumber?: number; - track?: number; - year?: number; - bitRate?: number; - suffix?: string; - userRating?: number; - replayGainTrackDb?: number; - replayGainAlbumDb?: number; - replayGainPeak?: number; - starred?: string; - genre?: string; - samplingRate?: number; - bitDepth?: number; - /** Subsonic `size` in bytes when provided by the server (helps hot-cache budgeting). */ - size?: number; - /** Owning server profile id when the queue spans multiple servers (e.g. offline favorites). */ - serverId?: string; - autoAdded?: boolean; - radioAdded?: boolean; - /** Inserted via "Play Next". Used by the preserve-order toggle to find the - * end of the current Play-Next streak. Stale flags behind queueIndex are - * harmless — the streak scan only looks forward from queueIndex+1. */ - playNextAdded?: boolean; -} - -/** - * Thin canonical queue item (queue thin-state plan, §5.10). Identity plus the - * queue-only flags; library metadata (title/artist/cover/…) is resolved from - * the local index or network on demand from Phase 2 on. `serverId` is per-item - * (day-1 schema for mixed-server queues); v1 fills it with the single playback - * server. - */ -export interface QueueItemRef { - serverId: string; - trackId: string; - autoAdded?: boolean; - radioAdded?: boolean; - playNextAdded?: boolean; -} +import type { Track, QueueItemRef } from '@/lib/media/trackTypes'; export interface PlayerState { currentTrack: Track | null; diff --git a/src/features/playback/store/promoteStreamCache.test.ts b/src/features/playback/store/promoteStreamCache.test.ts index f0cdc578..dc2b8371 100644 --- a/src/features/playback/store/promoteStreamCache.test.ts +++ b/src/features/playback/store/promoteStreamCache.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; const invokeMock = vi.fn(); const setEntryMock = vi.fn(); diff --git a/src/features/playback/store/promoteStreamCache.ts b/src/features/playback/store/promoteStreamCache.ts index 3459ae22..64d742cc 100644 --- a/src/features/playback/store/promoteStreamCache.ts +++ b/src/features/playback/store/promoteStreamCache.ts @@ -1,5 +1,5 @@ import { buildStreamUrlForServer } from '@/lib/api/subsonicStreamUrl'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { invoke } from '@tauri-apps/api/core'; import { useHotCacheStore } from '@/features/playback/store/hotCacheStore'; import { getMediaDir } from '@/utils/media/mediaDir'; diff --git a/src/features/playback/store/queueItemRef.test.ts b/src/features/playback/store/queueItemRef.test.ts index 09d14fe8..870457d8 100644 --- a/src/features/playback/store/queueItemRef.test.ts +++ b/src/features/playback/store/queueItemRef.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; import { toQueueItemRefs } from './queueItemRef'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; describe('toQueueItemRefs', () => { it('uses per-track serverId when present', () => { diff --git a/src/features/playback/store/queueItemRef.ts b/src/features/playback/store/queueItemRef.ts index dbc79c1e..c2fd7c3c 100644 --- a/src/features/playback/store/queueItemRef.ts +++ b/src/features/playback/store/queueItemRef.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { stampTrackServerId } from '@/features/playback/utils/playback/trackServerScope'; import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey'; diff --git a/src/features/playback/store/queueMutationActions.ts b/src/features/playback/store/queueMutationActions.ts index 1261245c..3b9e1fd1 100644 --- a/src/features/playback/store/queueMutationActions.ts +++ b/src/features/playback/store/queueMutationActions.ts @@ -3,7 +3,8 @@ import { orbitBulkGuard } from '@/store/orbitRuntime'; 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 type { QueueItemRef, Track } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; import { toQueueItemRefs } from '@/features/playback/store/queueItemRef'; import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver'; import { pushQueueUndoFromGetter } from '@/features/playback/store/queueUndo'; diff --git a/src/features/playback/store/queueRestore.test.ts b/src/features/playback/store/queueRestore.test.ts index 9e37a24c..ff59bb71 100644 --- a/src/features/playback/store/queueRestore.test.ts +++ b/src/features/playback/store/queueRestore.test.ts @@ -3,7 +3,7 @@ import { onInvoke } from '@/test/mocks/tauri'; import { useLibraryIndexStore } from '@/store/libraryIndexStore'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import type { TrackRefDto } from '@/lib/api/library'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { getCachedTrack, _resetQueueResolverForTest, diff --git a/src/features/playback/store/queueRestore.ts b/src/features/playback/store/queueRestore.ts index 25602aba..8336262a 100644 --- a/src/features/playback/store/queueRestore.ts +++ b/src/features/playback/store/queueRestore.ts @@ -1,6 +1,6 @@ import { useAuthStore } from '@/store/authStore'; import { usePlayerStore } from '@/features/playback/store/playerStore'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey'; import { resolveBatch } from './queueTrackResolver'; diff --git a/src/features/playback/store/queueSync.test.ts b/src/features/playback/store/queueSync.test.ts index cf47ef40..652d9064 100644 --- a/src/features/playback/store/queueSync.test.ts +++ b/src/features/playback/store/queueSync.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; const { savePlayQueueMock, playerState, progressSnapshot, isSubsonicServerReachableMock } = vi.hoisted(() => ({ savePlayQueueMock: vi.fn(async () => undefined), diff --git a/src/features/playback/store/queueSync.ts b/src/features/playback/store/queueSync.ts index e1c1b1f5..145f51e9 100644 --- a/src/features/playback/store/queueSync.ts +++ b/src/features/playback/store/queueSync.ts @@ -1,5 +1,5 @@ import { savePlayQueue } from '@/lib/api/subsonicPlayQueue'; -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { isSubsonicServerReachable } from '@/utils/network/subsonicNetworkGuard'; import { filterQueueRefsForPlaybackServer, diff --git a/src/features/playback/store/queueTrackResolver.test.ts b/src/features/playback/store/queueTrackResolver.test.ts index 3695add1..62803c9d 100644 --- a/src/features/playback/store/queueTrackResolver.test.ts +++ b/src/features/playback/store/queueTrackResolver.test.ts @@ -3,7 +3,7 @@ import { onInvoke } from '@/test/mocks/tauri'; import { useLibraryIndexStore } from '@/store/libraryIndexStore'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import type { TrackRefDto } from '@/lib/api/library'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import * as subsonic from '@/lib/api/subsonicLibrary'; import { resolveBatch, diff --git a/src/features/playback/store/queueTrackResolver.ts b/src/features/playback/store/queueTrackResolver.ts index 3560fbe6..d382f5de 100644 --- a/src/features/playback/store/queueTrackResolver.ts +++ b/src/features/playback/store/queueTrackResolver.ts @@ -1,7 +1,7 @@ import { libraryGetTracksBatch, type TrackRefDto } from '@/lib/api/library'; import { getSongForServer } from '@/lib/api/subsonicLibrary'; import { usePlayerStore } from '@/features/playback/store/playerStore'; -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; import { resolveServerIdForIndexKey } from '@/utils/server/serverLookup'; import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey'; diff --git a/src/features/playback/store/queueTrackView.test.ts b/src/features/playback/store/queueTrackView.test.ts index c7e64222..879af63c 100644 --- a/src/features/playback/store/queueTrackView.test.ts +++ b/src/features/playback/store/queueTrackView.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeEach } from 'vitest'; import { usePlayerStore } from '@/features/playback/store/playerStore'; -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { seedQueueResolver, _resetQueueResolverForTest } from '@/features/playback/store/queueTrackResolver'; import { resolveQueueTrack, getQueueTracksView } from './queueTrackView'; diff --git a/src/features/playback/store/queueTrackView.ts b/src/features/playback/store/queueTrackView.ts index edb17746..23540d50 100644 --- a/src/features/playback/store/queueTrackView.ts +++ b/src/features/playback/store/queueTrackView.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { getCachedTrack, placeholderTrack, applyQueueOverrides } from './queueTrackResolver'; /** diff --git a/src/features/playback/store/queueUndo.test.ts b/src/features/playback/store/queueUndo.test.ts index 048dc9bb..d8b0ec47 100644 --- a/src/features/playback/store/queueUndo.test.ts +++ b/src/features/playback/store/queueUndo.test.ts @@ -4,7 +4,8 @@ * push, and (c) the scroll-top reader / consumer pair that QueuePanel uses * to restore list scroll position after an undo/redo commit. */ -import type { PlayerState, Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; import { toQueueItemRefs } from '@/features/playback/store/queueItemRef'; import { beforeEach, describe, expect, it } from 'vitest'; import { diff --git a/src/features/playback/store/queueUndo.ts b/src/features/playback/store/queueUndo.ts index dba0b6b3..42401879 100644 --- a/src/features/playback/store/queueUndo.ts +++ b/src/features/playback/store/queueUndo.ts @@ -1,4 +1,5 @@ -import type { PlayerState, QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; /** Hard cap on undo/redo depth — keeps memory bounded for very long sessions. */ export const QUEUE_UNDO_MAX = 32; diff --git a/src/features/playback/store/queueUndoAudioRestore.test.ts b/src/features/playback/store/queueUndoAudioRestore.test.ts index f4021fc2..1a3fc310 100644 --- a/src/features/playback/store/queueUndoAudioRestore.test.ts +++ b/src/features/playback/store/queueUndoAudioRestore.test.ts @@ -4,7 +4,7 @@ * atSeconds > 0.05, the wantPlaying=false branch that issues audio_pause, * and the generation-mismatch bail-out. */ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { beforeEach, describe, expect, it, vi } from 'vitest'; const hoisted = vi.hoisted(() => { const auth = { diff --git a/src/features/playback/store/queueUndoAudioRestore.ts b/src/features/playback/store/queueUndoAudioRestore.ts index 4a1900bb..42f72a73 100644 --- a/src/features/playback/store/queueUndoAudioRestore.ts +++ b/src/features/playback/store/queueUndoAudioRestore.ts @@ -1,4 +1,4 @@ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { engineLoadTrackAtPosition } from '@/features/playback/store/engineLoadTrackAtPosition'; /** diff --git a/src/features/playback/store/skipStarRating.test.ts b/src/features/playback/store/skipStarRating.test.ts index 149cbe54..2f47c50b 100644 --- a/src/features/playback/store/skipStarRating.test.ts +++ b/src/features/playback/store/skipStarRating.test.ts @@ -4,7 +4,7 @@ * (pending-sync, F4) — its optimistic patch + retry behaviour is covered in * `pendingStarSync.test.ts`, so here we only assert the delegation + guards. */ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { beforeEach, describe, expect, it, vi } from 'vitest'; const { queueSongRatingMock, recordSkipStarMock, playerStateGet } = vi.hoisted(() => { const playerState = { diff --git a/src/features/playback/store/skipStarRating.ts b/src/features/playback/store/skipStarRating.ts index 52072be0..07fa81c4 100644 --- a/src/features/playback/store/skipStarRating.ts +++ b/src/features/playback/store/skipStarRating.ts @@ -1,4 +1,4 @@ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { useAuthStore } from '@/store/authStore'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { getCachedTrack } from '@/features/playback/store/queueTrackResolver'; diff --git a/src/features/playback/store/timelineSessionHistory.ts b/src/features/playback/store/timelineSessionHistory.ts index 21867f31..1d624536 100644 --- a/src/features/playback/store/timelineSessionHistory.ts +++ b/src/features/playback/store/timelineSessionHistory.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { getPlaybackServerId, playbackProfileIdForTrack, diff --git a/src/features/playback/utils/audio/resolveReplayGainDb.test.ts b/src/features/playback/utils/audio/resolveReplayGainDb.test.ts index a852335e..771440bd 100644 --- a/src/features/playback/utils/audio/resolveReplayGainDb.test.ts +++ b/src/features/playback/utils/audio/resolveReplayGainDb.test.ts @@ -5,7 +5,7 @@ * Originally lived in `playerStore.ts`; extracted in M0 of the frontend * refactor (2026-05-12). */ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { describe, expect, it } from 'vitest'; import { resolveReplayGainDb } from '@/features/playback/utils/audio/resolveReplayGainDb'; describe('resolveReplayGainDb', () => { diff --git a/src/features/playback/utils/audio/resolveReplayGainDb.ts b/src/features/playback/utils/audio/resolveReplayGainDb.ts index 980ee990..0839116e 100644 --- a/src/features/playback/utils/audio/resolveReplayGainDb.ts +++ b/src/features/playback/utils/audio/resolveReplayGainDb.ts @@ -1,4 +1,4 @@ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; /** * Resolve the ReplayGain dB value for a track based on the configured mode. * In 'auto' mode, picks album-gain when an adjacent queue neighbour shares the diff --git a/src/features/playback/utils/playback/autodjAutoAdvance.test.ts b/src/features/playback/utils/playback/autodjAutoAdvance.test.ts index 06c5a13d..7745bfcc 100644 --- a/src/features/playback/utils/playback/autodjAutoAdvance.test.ts +++ b/src/features/playback/utils/playback/autodjAutoAdvance.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import { autodjJsTriggerAtSec, computeAutodjJsOverlap, diff --git a/src/features/playback/utils/playback/autodjAutoAdvance.ts b/src/features/playback/utils/playback/autodjAutoAdvance.ts index d18a2928..b02fb278 100644 --- a/src/features/playback/utils/playback/autodjAutoAdvance.ts +++ b/src/features/playback/utils/playback/autodjAutoAdvance.ts @@ -1,5 +1,5 @@ import { DYNAMIC_OVERLAP_HARD_CAP_SEC, STANDARD_BLEND_SEC } from '@/utils/waveform/waveformSilence'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; export type QueueRepeatMode = 'off' | 'all' | 'one'; diff --git a/src/features/playback/utils/playback/autodjInterruptPrep.test.ts b/src/features/playback/utils/playback/autodjInterruptPrep.test.ts index a19a7b57..ecf7c77d 100644 --- a/src/features/playback/utils/playback/autodjInterruptPrep.test.ts +++ b/src/features/playback/utils/playback/autodjInterruptPrep.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { invoke } from '@tauri-apps/api/core'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import * as crossfadePreload from '@/features/playback/store/crossfadePreload'; import { armInterruptHandoff, diff --git a/src/features/playback/utils/playback/autodjInterruptPrep.ts b/src/features/playback/utils/playback/autodjInterruptPrep.ts index a4cb1a1c..eb6983f0 100644 --- a/src/features/playback/utils/playback/autodjInterruptPrep.ts +++ b/src/features/playback/utils/playback/autodjInterruptPrep.ts @@ -1,5 +1,5 @@ import { invoke } from '@tauri-apps/api/core'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { INTERRUPT_BLEND_PREP_FADE_SEC, isCrossfadeNextReady, diff --git a/src/features/playback/utils/playback/buildInfiniteQueueCandidates.test.ts b/src/features/playback/utils/playback/buildInfiniteQueueCandidates.test.ts index ef779e44..ba66a928 100644 --- a/src/features/playback/utils/playback/buildInfiniteQueueCandidates.test.ts +++ b/src/features/playback/utils/playback/buildInfiniteQueueCandidates.test.ts @@ -8,7 +8,7 @@ */ import { getSimilarSongs2, getTopSongs } from '@/lib/api/subsonicArtists'; import { getRandomSongs } from '@/lib/api/subsonicLibrary'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; // Mock only the artist Subsonic API submodule (the pre-move target was diff --git a/src/features/playback/utils/playback/buildInfiniteQueueCandidates.ts b/src/features/playback/utils/playback/buildInfiniteQueueCandidates.ts index 44e92b20..c7d9dba1 100644 --- a/src/features/playback/utils/playback/buildInfiniteQueueCandidates.ts +++ b/src/features/playback/utils/playback/buildInfiniteQueueCandidates.ts @@ -1,6 +1,6 @@ import { getSimilarSongs2, getTopSongs } from '@/lib/api/subsonicArtists'; import { getRandomSongs } from '@/lib/api/subsonicLibrary'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { enrichSongsForMixRatingFilter, getMixMinRatingsConfigFromAuth, diff --git a/src/features/playback/utils/playback/genreBrowsePlayback.ts b/src/features/playback/utils/playback/genreBrowsePlayback.ts index a901c46f..fddcde0a 100644 --- a/src/features/playback/utils/playback/genreBrowsePlayback.ts +++ b/src/features/playback/utils/playback/genreBrowsePlayback.ts @@ -5,7 +5,7 @@ import { libraryAdvancedSearch, libraryGetGenreAlbumCounts, type LibrarySortClau import { fetchAllSongsByGenre, getGenres } from '@/lib/api/subsonicGenres'; import type { SubsonicGenre } from '@/lib/api/subsonicTypes'; import { libraryScopeForServer } from '@/lib/api/subsonicClient'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; import { shuffleArray } from '@/lib/util/shuffleArray'; import { trackToSong } from '@/lib/library/advancedSearchLocal'; diff --git a/src/features/playback/utils/playback/playAlbum.test.ts b/src/features/playback/utils/playback/playAlbum.test.ts index 13f79d08..852603bd 100644 --- a/src/features/playback/utils/playback/playAlbum.test.ts +++ b/src/features/playback/utils/playback/playAlbum.test.ts @@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { makeSubsonicSong } from '@/test/helpers/factories'; import { onInvoke } from '@/test/mocks/tauri'; import { resetOrbitStore, resetPlayerStore } from '@/test/helpers/storeReset'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; // Spread the real module so registerMediaResolver stays callable — the offline // barrel loads offlineMediaResolve transitively, which registers at module init. diff --git a/src/features/playback/utils/playback/playAlbum.ts b/src/features/playback/utils/playback/playAlbum.ts index 665527ce..fe197c46 100644 --- a/src/features/playback/utils/playback/playAlbum.ts +++ b/src/features/playback/utils/playback/playAlbum.ts @@ -4,7 +4,7 @@ import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; import { orbitSnapshot } from '@/store/orbitRuntime'; import { fadeOut } from '@/features/playback/utils/playback/fadeOut'; import { shouldAutodjInterruptBlend } from '@/features/playback/utils/playback/autodjManualBlend'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { shuffleArray } from '@/lib/util/shuffleArray'; export async function fetchAlbumTracks(albumId: string, serverId?: string): Promise { diff --git a/src/features/playback/utils/playback/playbackServer.ts b/src/features/playback/utils/playback/playbackServer.ts index 5cda37c1..c9092c5e 100644 --- a/src/features/playback/utils/playback/playbackServer.ts +++ b/src/features/playback/utils/playback/playbackServer.ts @@ -8,7 +8,7 @@ import type { ServerProfile } from '@/store/authStoreTypes'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { switchActiveServer } from '@/utils/server/switchActiveServer'; import { sameQueueTrackId } from '@/features/playback/utils/playback/queueIdentity'; -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { findServerByIdOrIndexKey, resolveServerIdForIndexKey } from '@/utils/server/serverLookup'; import { canonicalQueueServerKey, diff --git a/src/features/playback/utils/playback/queueIdentity.test.ts b/src/features/playback/utils/playback/queueIdentity.test.ts index 65070332..9cfb6fbd 100644 --- a/src/features/playback/utils/playback/queueIdentity.test.ts +++ b/src/features/playback/utils/playback/queueIdentity.test.ts @@ -4,7 +4,7 @@ * routing through the HTTP source) and the no-op detection in * `queuesStructuralEqual` that prevents unnecessary store rewrites. */ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { describe, expect, it } from 'vitest'; import { normalizeAnalysisTrackId, diff --git a/src/features/playback/utils/playback/queueIdentity.ts b/src/features/playback/utils/playback/queueIdentity.ts index b5b676e8..48d1150f 100644 --- a/src/features/playback/utils/playback/queueIdentity.ts +++ b/src/features/playback/utils/playback/queueIdentity.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; /** * Strip the `stream:` prefix that some Rust events attach to track ids when diff --git a/src/features/playback/utils/playback/runBulkPlay.test.ts b/src/features/playback/utils/playback/runBulkPlay.test.ts index bcc4d58f..b7e7be0f 100644 --- a/src/features/playback/utils/playback/runBulkPlay.test.ts +++ b/src/features/playback/utils/playback/runBulkPlay.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, vi } from 'vitest'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { runBulkEnqueue, runBulkPlayAll, runBulkShuffle } from '@/features/playback/utils/playback/runBulkPlay'; function track(id: string): Track { diff --git a/src/features/playback/utils/playback/runBulkPlay.ts b/src/features/playback/utils/playback/runBulkPlay.ts index 05d6fabe..ec360a2a 100644 --- a/src/features/playback/utils/playback/runBulkPlay.ts +++ b/src/features/playback/utils/playback/runBulkPlay.ts @@ -1,4 +1,4 @@ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { shuffleArray } from '@/lib/util/shuffleArray'; /** diff --git a/src/features/playback/utils/playback/songToTrack.test.ts b/src/features/playback/utils/playback/songToTrack.test.ts index 8ce2b93a..3cf503a0 100644 --- a/src/features/playback/utils/playback/songToTrack.test.ts +++ b/src/features/playback/utils/playback/songToTrack.test.ts @@ -5,7 +5,7 @@ * playback queue. Originally lived in `playerStore.ts`; extracted in M0 of * the frontend refactor (2026-05-12). */ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { describe, expect, it } from 'vitest'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; import { makeSubsonicSong } from '@/test/helpers/factories'; diff --git a/src/features/playback/utils/playback/songToTrack.ts b/src/features/playback/utils/playback/songToTrack.ts index 08cde482..cdf541ec 100644 --- a/src/features/playback/utils/playback/songToTrack.ts +++ b/src/features/playback/utils/playback/songToTrack.ts @@ -1,5 +1,5 @@ import type { SubsonicSong } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { coerceOpenArtistRefs } from '@/lib/api/openArtistRefs'; import { activeServerProfileId } from '@/features/playback/utils/playback/trackServerScope'; diff --git a/src/features/playback/utils/playback/trackArtistRefs.test.ts b/src/features/playback/utils/playback/trackArtistRefs.test.ts index 75eb0aa1..80863002 100644 --- a/src/features/playback/utils/playback/trackArtistRefs.test.ts +++ b/src/features/playback/utils/playback/trackArtistRefs.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { primaryTrackArtistRef, resolveTrackArtistRefs } from '@/features/playback/utils/playback/trackArtistRefs'; describe('resolveTrackArtistRefs', () => { diff --git a/src/features/playback/utils/playback/trackArtistRefs.ts b/src/features/playback/utils/playback/trackArtistRefs.ts index e7a1391b..d3c4b0d6 100644 --- a/src/features/playback/utils/playback/trackArtistRefs.ts +++ b/src/features/playback/utils/playback/trackArtistRefs.ts @@ -1,5 +1,5 @@ import type { SubsonicOpenArtistRef } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { coerceOpenArtistRefs } from '@/lib/api/openArtistRefs'; type TrackArtistFields = Pick; diff --git a/src/features/playback/utils/playback/trackServerScope.test.ts b/src/features/playback/utils/playback/trackServerScope.test.ts index 6bae3c2d..5fbbdf95 100644 --- a/src/features/playback/utils/playback/trackServerScope.test.ts +++ b/src/features/playback/utils/playback/trackServerScope.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, it } from 'vitest'; import { useAuthStore } from '@/store/authStore'; import { usePlayerStore } from '@/features/playback/store/playerStore'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { activeServerQueueTrackIds, filterQueueRefsForActiveServer, diff --git a/src/features/playback/utils/playback/trackServerScope.ts b/src/features/playback/utils/playback/trackServerScope.ts index 6355ec16..f718b221 100644 --- a/src/features/playback/utils/playback/trackServerScope.ts +++ b/src/features/playback/utils/playback/trackServerScope.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { useAuthStore } from '@/store/authStore'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { canonicalQueueServerKey } from '@/utils/server/serverIndexKey'; diff --git a/src/features/playlist/components/PlaylistTracklist.tsx b/src/features/playlist/components/PlaylistTracklist.tsx index 09004f77..04138b06 100644 --- a/src/features/playlist/components/PlaylistTracklist.tsx +++ b/src/features/playlist/components/PlaylistTracklist.tsx @@ -11,7 +11,7 @@ import { } from 'lucide-react'; import type { ColDef } from '@/utils/useTracklistColumns'; import type { SubsonicSong } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { previewInputFromSong, usePreviewStore } from '@/features/playback/store/previewStore'; import { useThemeStore } from '@/store/themeStore'; diff --git a/src/features/playlist/hooks/usePlaylistBulkPlayCallbacks.ts b/src/features/playlist/hooks/usePlaylistBulkPlayCallbacks.ts index d8c12127..99ced506 100644 --- a/src/features/playlist/hooks/usePlaylistBulkPlayCallbacks.ts +++ b/src/features/playlist/hooks/usePlaylistBulkPlayCallbacks.ts @@ -1,5 +1,5 @@ import { useCallback } from 'react'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { enqueuePlaylistAll, playPlaylistAll, shufflePlaylistAll } from '@/features/playlist/utils/playlistBulkPlayActions'; export interface PlaylistBulkPlayCallbacksDeps { diff --git a/src/features/playlist/hooks/usePlaylistDerived.ts b/src/features/playlist/hooks/usePlaylistDerived.ts index 0c60685c..b2cde553 100644 --- a/src/features/playlist/hooks/usePlaylistDerived.ts +++ b/src/features/playlist/hooks/usePlaylistDerived.ts @@ -1,6 +1,6 @@ import { useMemo } from 'react'; import type { SubsonicSong } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; import { getDisplayedSongs, type PlaylistSortDir, type PlaylistSortKey } from '@/features/playlist/utils/playlistDisplayedSongs'; diff --git a/src/features/playlist/utils/playlistBulkPlayActions.test.ts b/src/features/playlist/utils/playlistBulkPlayActions.test.ts index 39dde17d..5fd2f924 100644 --- a/src/features/playlist/utils/playlistBulkPlayActions.test.ts +++ b/src/features/playlist/utils/playlistBulkPlayActions.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, vi } from 'vitest'; import { enqueuePlaylistAll, playPlaylistAll, shufflePlaylistAll } from '@/features/playlist/utils/playlistBulkPlayActions'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; // Only id/queue identity matters for these actions. const tracks = [{ id: 'a' }, { id: 'b' }, { id: 'c' }] as unknown as Track[]; diff --git a/src/features/playlist/utils/playlistBulkPlayActions.ts b/src/features/playlist/utils/playlistBulkPlayActions.ts index edea3882..8e1a2ee9 100644 --- a/src/features/playlist/utils/playlistBulkPlayActions.ts +++ b/src/features/playlist/utils/playlistBulkPlayActions.ts @@ -1,4 +1,4 @@ -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; // No `touchPlaylist` here: playing/shuffling/enqueuing does not modify the // playlist. Touching it bumps `lastModified`, which is the playlist detail diff --git a/src/features/queue/components/QueueCurrentTrack.tsx b/src/features/queue/components/QueueCurrentTrack.tsx index 724667e0..cd269e91 100644 --- a/src/features/queue/components/QueueCurrentTrack.tsx +++ b/src/features/queue/components/QueueCurrentTrack.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { ChevronDown, FolderOpen, HardDrive, Music, Waves } from 'lucide-react'; import type { TFunction } from 'i18next'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import type { LoudnessLufsPreset, NormalizationEngine } from '@/store/authStoreTypes'; import type { PlaybackSourceKind } from '@/features/playback/utils/playback/resolvePlaybackUrl'; import { diff --git a/src/features/queue/components/QueueHeader.tsx b/src/features/queue/components/QueueHeader.tsx index 5a2ba1ca..7f2bae03 100644 --- a/src/features/queue/components/QueueHeader.tsx +++ b/src/features/queue/components/QueueHeader.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'; import type { TFunction } from 'i18next'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { useAuthStore } from '@/store/authStore'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import type { QueueDisplayMode } from '@/store/authStoreTypes'; import type { DurationMode } from '@/utils/componentHelpers/queuePanelHelpers'; import { formatLongDuration } from '@/lib/format/formatDuration'; diff --git a/src/features/queue/components/QueueList.tsx b/src/features/queue/components/QueueList.tsx index 715040d3..e82d00e8 100644 --- a/src/features/queue/components/QueueList.tsx +++ b/src/features/queue/components/QueueList.tsx @@ -5,7 +5,8 @@ import type { TFunction } from 'i18next'; import OverlayScrollArea from '@/ui/OverlayScrollArea'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { useLuckyMixStore } from '@/store/luckyMixStore'; -import type { QueueItemRef, PlayerState } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; +import type { PlayerState } from '@/features/playback/store/playerStoreTypes'; import type { QueueDisplayMode } from '@/store/authStoreTypes'; import { formatTrackTime } from '@/lib/format/formatDuration'; import { resolveQueueTrack } from '@/features/playback/store/queueTrackView'; diff --git a/src/features/queue/components/QueuePanel.tsx b/src/features/queue/components/QueuePanel.tsx index 9724eea8..8851a3da 100644 --- a/src/features/queue/components/QueuePanel.tsx +++ b/src/features/queue/components/QueuePanel.tsx @@ -2,7 +2,7 @@ import { Play } from 'lucide-react'; import { updatePlaylist } from '@/lib/api/subsonicPlaylists'; import { resolvePlaylist, resolveMediaServerId } from '@/features/offline'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { useState, useRef, useMemo } from 'react'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { useOrbitStore } from '@/features/orbit'; diff --git a/src/features/queue/components/QueueToolbar.tsx b/src/features/queue/components/QueueToolbar.tsx index be58bfe3..659ee749 100644 --- a/src/features/queue/components/QueueToolbar.tsx +++ b/src/features/queue/components/QueueToolbar.tsx @@ -3,7 +3,7 @@ import { Blend, Check, FolderOpen, Infinity as InfinityIcon, ListMusic, MoveRight, Save, Share2, Shuffle, Trash2, Waves, } from 'lucide-react'; import type { TFunction } from 'i18next'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import type { QueueToolbarButtonConfig, QueueToolbarButtonId, diff --git a/src/features/queue/hooks/useQueueAutoScroll.ts b/src/features/queue/hooks/useQueueAutoScroll.ts index 99d08008..05e3768b 100644 --- a/src/features/queue/hooks/useQueueAutoScroll.ts +++ b/src/features/queue/hooks/useQueueAutoScroll.ts @@ -1,6 +1,6 @@ import React, { useLayoutEffect } from 'react'; import { registerQueueListScrollTopReader, consumePendingQueueListScrollTop } from '@/features/playback/store/queueUndo'; -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; interface Args { queue: QueueItemRef[]; diff --git a/src/features/queue/hooks/useQueuePanelDrag.ts b/src/features/queue/hooks/useQueuePanelDrag.ts index fc52f75b..26eebedb 100644 --- a/src/features/queue/hooks/useQueuePanelDrag.ts +++ b/src/features/queue/hooks/useQueuePanelDrag.ts @@ -3,7 +3,7 @@ import { resolveAlbum, resolveMediaServerId } from '@/features/offline'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; import { useDragDrop, registerQueueDragHitTest } from '@/lib/dnd/DragDropContext'; import { usePlayerStore } from '@/features/playback/store/playerStore'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; /** Drag types that may be dropped into the queue panel. */ const QUEUE_DROP_TYPES = new Set(['song', 'album', 'queue_reorder']); diff --git a/src/features/queue/hooks/useQueueTracks.test.ts b/src/features/queue/hooks/useQueueTracks.test.ts index 92cbd735..01c55f8f 100644 --- a/src/features/queue/hooks/useQueueTracks.test.ts +++ b/src/features/queue/hooks/useQueueTracks.test.ts @@ -1,7 +1,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 type { Track } from '@/lib/media/trackTypes'; 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 0c5f8f71..84b085d6 100644 --- a/src/features/queue/hooks/useQueueTracks.ts +++ b/src/features/queue/hooks/useQueueTracks.ts @@ -1,6 +1,6 @@ import { useMemo, useSyncExternalStore } from 'react'; import { usePlayerStore } from '@/features/playback/store/playerStore'; -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { resolveQueueTrack } from '@/features/playback/store/queueTrackView'; import { getQueueResolverVersion, diff --git a/src/hooks/useContextMenuRating.ts b/src/hooks/useContextMenuRating.ts index 28697bbd..44fb39df 100644 --- a/src/hooks/useContextMenuRating.ts +++ b/src/hooks/useContextMenuRating.ts @@ -2,7 +2,7 @@ import { useCallback } from 'react'; import { setRating } from '@/lib/api/subsonicStarRating'; import { queueSongRating } from '@/features/playback/store/pendingStarSync'; import type { SubsonicAlbum, SubsonicArtist } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { useAuthStore } from '../store/authStore'; import { showToast } from '../utils/ui/toast'; diff --git a/src/hooks/useFolderBrowserNowPlayingPath.ts b/src/hooks/useFolderBrowserNowPlayingPath.ts index a29ef056..ac78673c 100644 --- a/src/hooks/useFolderBrowserNowPlayingPath.ts +++ b/src/hooks/useFolderBrowserNowPlayingPath.ts @@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { useLocation } from 'react-router-dom'; import { getMusicDirectory, getMusicIndexes } from '@/lib/api/subsonicLibrary'; import type { SubsonicDirectoryEntry } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import type { Column, NavPos } from '../utils/componentHelpers/folderBrowserHelpers'; let persistedPlayingPathIds: string[] = []; diff --git a/src/hooks/useLyrics.ts b/src/hooks/useLyrics.ts index 9c49b950..63f6a0cb 100644 --- a/src/hooks/useLyrics.ts +++ b/src/hooks/useLyrics.ts @@ -1,6 +1,6 @@ import { getLyricsBySongId } from '@/lib/api/subsonicLyrics'; import type { SubsonicStructuredLyrics } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { useEffect, useState } from 'react'; import { useShallow } from 'zustand/react/shallow'; import { invoke } from '@tauri-apps/api/core'; diff --git a/src/hooks/useNowPlayingTrayTitle.ts b/src/hooks/useNowPlayingTrayTitle.ts index d95f61cf..cdfa9e50 100644 --- a/src/hooks/useNowPlayingTrayTitle.ts +++ b/src/hooks/useNowPlayingTrayTitle.ts @@ -1,7 +1,7 @@ import { useEffect } from 'react'; import { invoke } from '@tauri-apps/api/core'; import { getCurrentWindow } from '@tauri-apps/api/window'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; /** * Keep `document.title`, the OS window title, and the tray tooltip in sync diff --git a/src/hooks/useWordLyricsSync.ts b/src/hooks/useWordLyricsSync.ts index c1887a42..f6e99f99 100644 --- a/src/hooks/useWordLyricsSync.ts +++ b/src/hooks/useWordLyricsSync.ts @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react'; import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '@/features/playback/store/playbackProgress'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import type { WordLyricsLine } from './useLyrics'; interface Args { diff --git a/src/hotCachePrefetch.ts b/src/hotCachePrefetch.ts index b267a1dd..45e9d7ba 100644 --- a/src/hotCachePrefetch.ts +++ b/src/hotCachePrefetch.ts @@ -1,6 +1,6 @@ import { buildStreamUrlForServer } from '@/lib/api/subsonicStreamUrl'; import { getPlaybackCacheServerKey } from '@/features/playback/utils/playback/playbackServer'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import { resolveQueueTrack } from '@/features/playback/store/queueTrackView'; import { invoke } from '@tauri-apps/api/core'; import { useAuthStore } from './store/authStore'; diff --git a/src/hotCachePrefetch/helpers.ts b/src/hotCachePrefetch/helpers.ts index 14ff1afd..d5fb5e46 100644 --- a/src/hotCachePrefetch/helpers.ts +++ b/src/hotCachePrefetch/helpers.ts @@ -1,5 +1,5 @@ import { invoke } from '@tauri-apps/api/core'; -import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef, Track } from '@/lib/media/trackTypes'; import { useAuthStore } from '../store/authStore'; import { HOT_CACHE_PROTECT_AFTER_CURRENT, type HotCacheEntry } from '@/features/playback/store/hotCacheStore'; diff --git a/src/lib/media/trackTypes.ts b/src/lib/media/trackTypes.ts new file mode 100644 index 00000000..83820dd0 --- /dev/null +++ b/src/lib/media/trackTypes.ts @@ -0,0 +1,60 @@ +import type { SubsonicOpenArtistRef } from '@/lib/api/subsonicTypes'; + +/** + * Shared media-domain model. `Track` is the app's normalized song shape (built + * from a Subsonic child via `songToTrack`) and `QueueItemRef` its thin queue + * identity; both are consumed app-wide (queue, playback, cover, context menus, + * sharing, lucky-mix, library browse). They live in `lib/media` -- not inside + * the playback feature -- so every layer can depend on the model without an + * inverted edge into `@/features/playback`. + */ +export interface Track { + id: string; + title: string; + artist: string; + album: string; + albumId: string; + artistId?: string; + /** OpenSubsonic `artists` on the child song — multiple performers with ids. */ + artists?: SubsonicOpenArtistRef[]; + duration: number; + coverArt?: string; + discNumber?: number; + track?: number; + year?: number; + bitRate?: number; + suffix?: string; + userRating?: number; + replayGainTrackDb?: number; + replayGainAlbumDb?: number; + replayGainPeak?: number; + starred?: string; + genre?: string; + samplingRate?: number; + bitDepth?: number; + /** Subsonic `size` in bytes when provided by the server (helps hot-cache budgeting). */ + size?: number; + /** Owning server profile id when the queue spans multiple servers (e.g. offline favorites). */ + serverId?: string; + autoAdded?: boolean; + radioAdded?: boolean; + /** Inserted via "Play Next". Used by the preserve-order toggle to find the + * end of the current Play-Next streak. Stale flags behind queueIndex are + * harmless — the streak scan only looks forward from queueIndex+1. */ + playNextAdded?: boolean; +} + +/** + * Thin canonical queue item (queue thin-state plan, §5.10). Identity plus the + * queue-only flags; library metadata (title/artist/cover/…) is resolved from + * the local index or network on demand from Phase 2 on. `serverId` is per-item + * (day-1 schema for mixed-server queues); v1 fills it with the single playback + * server. + */ +export interface QueueItemRef { + serverId: string; + trackId: string; + autoAdded?: boolean; + radioAdded?: boolean; + playNextAdded?: boolean; +} diff --git a/src/store/localPlaybackStore.ts b/src/store/localPlaybackStore.ts index fa56251f..fb407418 100644 --- a/src/store/localPlaybackStore.ts +++ b/src/store/localPlaybackStore.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import { create } from 'zustand'; import { persist, createJSONStorage } from 'zustand/middleware'; import { invoke } from '@tauri-apps/api/core'; diff --git a/src/test/helpers/factories.ts b/src/test/helpers/factories.ts index 36a7bbf8..92f48bbd 100644 --- a/src/test/helpers/factories.ts +++ b/src/test/helpers/factories.ts @@ -7,7 +7,7 @@ */ import type { SubsonicSong } from '@/lib/api/subsonicTypes'; import type { ServerProfile } from '@/store/authStoreTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { toQueueItemRefs } from '@/features/playback/store/queueItemRef'; import { seedQueueResolver } from '@/features/playback/store/queueTrackResolver'; diff --git a/src/utils/componentHelpers/contextMenuActions.ts b/src/utils/componentHelpers/contextMenuActions.ts index 6cfb483e..c2b16962 100644 --- a/src/utils/componentHelpers/contextMenuActions.ts +++ b/src/utils/componentHelpers/contextMenuActions.ts @@ -5,7 +5,7 @@ import { filterSongsForLuckyMixRatings, getMixMinRatingsConfigFromAuth } from '. 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 type { Track } from '@/lib/media/trackTypes'; import { resolveQueueTrack } from '@/features/playback/store/queueTrackView'; import { useZipDownloadStore } from '@/features/offline'; import { useDownloadModalStore } from '@/features/offline'; diff --git a/src/utils/componentHelpers/folderBrowserHelpers.ts b/src/utils/componentHelpers/folderBrowserHelpers.ts index fd173e66..6d27e687 100644 --- a/src/utils/componentHelpers/folderBrowserHelpers.ts +++ b/src/utils/componentHelpers/folderBrowserHelpers.ts @@ -1,6 +1,6 @@ import type React from 'react'; import type { SubsonicAlbum, SubsonicDirectoryEntry } from '@/lib/api/subsonicTypes'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; export type ColumnKind = 'roots' | 'indexes' | 'directory'; export type NavPos = { colIndex: number; rowIndex: number }; diff --git a/src/utils/componentHelpers/queuePanelHelpers.tsx b/src/utils/componentHelpers/queuePanelHelpers.tsx index 423e533f..f8571fba 100644 --- a/src/utils/componentHelpers/queuePanelHelpers.tsx +++ b/src/utils/componentHelpers/queuePanelHelpers.tsx @@ -1,6 +1,6 @@ import { Star } from 'lucide-react'; import type { TFunction } from 'i18next'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; export type { DurationMode } from '../../store/authStoreTypes'; diff --git a/src/utils/mix/luckyMix.ts b/src/utils/mix/luckyMix.ts index b1b984df..33b64134 100644 --- a/src/utils/mix/luckyMix.ts +++ b/src/utils/mix/luckyMix.ts @@ -1,7 +1,7 @@ import { fetchSimilarTracksRouted } from '@/lib/api/subsonicArtists'; import { filterSongsToActiveLibrary, getRandomSongs } from '@/lib/api/subsonicLibrary'; import type { SubsonicAlbum, SubsonicSong } from '@/lib/api/subsonicTypes'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; import { invoke } from '@tauri-apps/api/core'; import i18n from '@/lib/i18n'; diff --git a/src/utils/queue/buildTimelineDisplayRows.test.ts b/src/utils/queue/buildTimelineDisplayRows.test.ts index d641fb32..e6ed8aa0 100644 --- a/src/utils/queue/buildTimelineDisplayRows.test.ts +++ b/src/utils/queue/buildTimelineDisplayRows.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect } from 'vitest'; import { buildTimelineDisplayRows, findTimelineScrollLocalIndex } from './buildTimelineDisplayRows'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; const ref = (trackId: string, extra?: Partial): QueueItemRef => ({ serverId: 's1', diff --git a/src/utils/queue/buildTimelineDisplayRows.ts b/src/utils/queue/buildTimelineDisplayRows.ts index a4f436c5..2d1c4c21 100644 --- a/src/utils/queue/buildTimelineDisplayRows.ts +++ b/src/utils/queue/buildTimelineDisplayRows.ts @@ -1,4 +1,4 @@ -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import type { TimelinePlayedRef } from '@/features/playback/store/timelineSessionHistory'; export type TimelineDisplayRow = diff --git a/src/utils/queue/playTimelineHistoryTrack.ts b/src/utils/queue/playTimelineHistoryTrack.ts index b7f76e31..bb406593 100644 --- a/src/utils/queue/playTimelineHistoryTrack.ts +++ b/src/utils/queue/playTimelineHistoryTrack.ts @@ -1,5 +1,5 @@ import { usePlayerStore } from '@/features/playback/store/playerStore'; -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import { getQueueTracksView, resolveQueueTrack } from '@/features/playback/store/queueTrackView'; import { resolveBatch } from '@/features/playback/store/queueTrackResolver'; import { findQueueItemRefIndex, sameQueueItemRef } from '@/features/playback/utils/playback/queueIdentity'; diff --git a/src/utils/queue/timelineHistoryRefs.ts b/src/utils/queue/timelineHistoryRefs.ts index 3a7e6c99..9c0450af 100644 --- a/src/utils/queue/timelineHistoryRefs.ts +++ b/src/utils/queue/timelineHistoryRefs.ts @@ -1,7 +1,7 @@ -import type { QueueItemRef } from '@/features/playback/store/playerStoreTypes'; +import type { QueueItemRef } from '@/lib/media/trackTypes'; import type { PlaySessionRecentTrack } from '@/lib/api/library'; import type { TimelinePlayedRef } from '@/features/playback/store/timelineSessionHistory'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; export function timelineHistoryToQueueRefs( history: TimelinePlayedRef[], diff --git a/src/utils/share/enqueueShareSearchPayload.ts b/src/utils/share/enqueueShareSearchPayload.ts index 2bb5d7f9..4e0042f7 100644 --- a/src/utils/share/enqueueShareSearchPayload.ts +++ b/src/utils/share/enqueueShareSearchPayload.ts @@ -11,7 +11,7 @@ import { useAuthStore } from '../../store/authStore'; import type { ServerProfile } from '../../store/authStoreTypes'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { songToTrack } from '@/features/playback/utils/playback/songToTrack'; -import type { Track } from '@/features/playback/store/playerStoreTypes'; +import type { Track } from '@/lib/media/trackTypes'; import { orbitBulkGuard } from '@/features/orbit'; import { findServerIdForShareUrl } from './shareLink'; import { connectBaseUrlForServer } from '../server/serverEndpoint';