diff --git a/.dependency-cruiser-known-violations.json b/.dependency-cruiser-known-violations.json index 811bea9f..f7b23281 100644 --- a/.dependency-cruiser-known-violations.json +++ b/.dependency-cruiser-known-violations.json @@ -1397,159 +1397,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -1721,159 +1569,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -2005,159 +1701,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -2255,159 +1799,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -2519,159 +1911,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -2882,7 +2122,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -2892,7 +2132,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -2902,74 +2142,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -2980,14 +2153,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -2997,48 +2170,8 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -3117,7 +2250,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3127,7 +2260,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3137,74 +2270,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3215,14 +2281,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3232,48 +2298,8 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -3564,7 +2590,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3574,7 +2600,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3584,74 +2610,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3662,14 +2621,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3679,48 +2638,15 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", + "name": "src/cover/ensureQueue.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -3776,7 +2702,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3786,7 +2712,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3796,74 +2722,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3874,14 +2733,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -3891,48 +2750,15 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", + "name": "src/cover/ensureQueue.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -3995,7 +2821,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4005,7 +2831,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4015,74 +2841,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4093,14 +2852,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4110,274 +2869,8 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/cover/ensureQueue.ts", - "dependencyTypes": [ - "local", - "import" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/cover/ensureQueue.ts", - "to": "src/cover/diskSrcLookup.ts", - "unresolvedTo": "./diskSrcLookup", - "dependencyTypes": [ - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/cover/diskSrcLookup.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/cover/diskSrcCache.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/cover/storageKeys.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/playback/utils/playback/playbackServer.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -4433,7 +2926,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4443,7 +2936,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4453,74 +2946,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4531,14 +2957,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4548,48 +2974,8 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -4661,7 +3047,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4671,7 +3057,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4681,74 +3067,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4759,14 +3078,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -4776,48 +3095,8 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -5078,159 +3357,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -5348,159 +3475,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -5618,159 +3593,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -5902,159 +3725,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -6179,159 +3850,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -6456,159 +3975,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -6726,159 +4093,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -7060,159 +4275,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -7344,159 +4407,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -7621,159 +4532,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -7898,159 +4657,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8175,7 +4782,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8185,7 +4792,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8195,74 +4802,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8273,14 +4813,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8290,48 +4830,22 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", + "name": "src/cover/ensureQueue.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, { - "name": "src/features/playlist/index.ts", + "name": "src/cover/coverTraffic.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -8401,7 +4915,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8411,7 +4925,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8421,74 +4935,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8499,14 +4946,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8516,48 +4963,22 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", + "name": "src/cover/ensureQueue.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, { - "name": "src/features/playlist/index.ts", + "name": "src/cover/coverTraffic.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -8629,7 +5050,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8639,7 +5060,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8649,74 +5070,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8727,14 +5081,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -8744,48 +5098,22 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", + "name": "src/cover/ensureQueue.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, { - "name": "src/features/playlist/index.ts", + "name": "src/cover/coverTraffic.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/useCoverArt.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -8799,211 +5127,6 @@ } ] }, - { - "type": "cycle", - "from": "src/cover/prefetchRegistry.ts", - "to": "src/cover/storageKeys.ts", - "unresolvedTo": "./storageKeys", - "dependencyTypes": [ - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/cover/storageKeys.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/playback/utils/playback/playbackServer.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/prefetchRegistry.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, { "type": "cycle", "from": "src/cover/prefetchRegistry.ts", @@ -9062,7 +5185,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -9072,7 +5195,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -9082,74 +5205,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -9160,14 +5216,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -9177,48 +5233,15 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, { "name": "src/cover/prefetchRegistry.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -9306,159 +5329,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -9599,159 +5470,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -9834,211 +5553,6 @@ } ] }, - { - "type": "cycle", - "from": "src/cover/resolveEntryLibrary.ts", - "to": "src/cover/ref.ts", - "unresolvedTo": "./ref", - "dependencyTypes": [ - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/cover/ref.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/playback/utils/playback/playbackServer.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/resolveEntryLibrary.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, { "type": "cycle", "from": "src/cover/resolveEntryLibrary.ts", @@ -10081,7 +5595,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10091,7 +5605,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10101,74 +5615,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10179,14 +5626,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10196,7 +5643,14 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", + "dependencyTypes": [ + "local", + "import" + ] + }, + { + "name": "src/ui/CachedImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10206,7 +5660,7 @@ ] }, { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", + "name": "src/cover/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10215,31 +5669,11 @@ "import" ] }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, { "name": "src/cover/resolveEntryLibrary.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", - "import" + "export" ] } ] @@ -10302,7 +5736,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10312,7 +5746,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10322,74 +5756,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10400,14 +5767,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10417,7 +5784,14 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", + "dependencyTypes": [ + "local", + "import" + ] + }, + { + "name": "src/ui/CachedImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10427,7 +5801,7 @@ ] }, { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", + "name": "src/cover/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10436,31 +5810,11 @@ "import" ] }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, { "name": "src/cover/resolveEntryLibrary.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", - "import" + "export" ] } ] @@ -10521,159 +5875,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -10798,159 +6000,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -11072,284 +6122,6 @@ } ] }, - { - "type": "cycle", - "from": "src/cover/TrackCoverArtImage.tsx", - "to": "src/cover/CoverArtImage.tsx", - "unresolvedTo": "./CoverArtImage", - "dependencyTypes": [ - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/cover/CoverArtImage.tsx", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/cover/ensureQueue.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/cover/coverTraffic.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/cover/peekQueue.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/cover/diskSrcCache.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/cover/storageKeys.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/playback/utils/playback/playbackServer.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/orbitRuntime.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/orbit/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/orbit/components/OrbitGuestQueue.tsx", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/TrackCoverArtImage.tsx", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, { "type": "cycle", "from": "src/cover/TrackCoverArtImage.tsx", @@ -11399,159 +6171,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -11817,8 +6437,8 @@ { "type": "cycle", "from": "src/cover/useCoverArt.ts", - "to": "src/cover/diskSrcCache.ts", - "unresolvedTo": "./diskSrcCache", + "to": "src/cover/diskSrcLookup.ts", + "unresolvedTo": "./diskSrcLookup", "dependencyTypes": [ "local", "import" @@ -11828,6 +6448,13 @@ "name": "no-circular" }, "cycle": [ + { + "name": "src/cover/diskSrcLookup.ts", + "dependencyTypes": [ + "local", + "import" + ] + }, { "name": "src/cover/diskSrcCache.ts", "dependencyTypes": [ @@ -11863,7 +6490,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -11873,7 +6500,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -11883,74 +6510,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -11961,14 +6521,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -11978,48 +6538,15 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, { "name": "src/cover/useCoverArt.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -12096,7 +6623,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -12106,7 +6633,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -12116,74 +6643,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -12194,14 +6654,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -12211,48 +6671,15 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, { "name": "src/cover/useCoverArt.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -12301,7 +6728,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -12311,7 +6738,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/store/orbitRuntime.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -12321,74 +6748,7 @@ ] }, { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", + "name": "src/features/orbit/index.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -12399,14 +6759,14 @@ ] }, { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", + "name": "src/features/orbit/components/OrbitGuestQueue.tsx", "dependencyTypes": [ "local", "export" ] }, { - "name": "src/features/offline/utils/offlineBrowseContext.ts", + "name": "src/cover/TrackCoverArtImage.tsx", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -12416,48 +6776,15 @@ ] }, { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", + "name": "src/cover/CoverArtImage.tsx", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, { "name": "src/cover/useCoverArt.ts", "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", "local", "import" ] @@ -12513,159 +6840,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -12797,159 +6972,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -13061,159 +7084,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -20326,184 +14197,6 @@ } ] }, - { - "type": "cycle", - "from": "src/features/offline/utils/pinnedOfflineSync.ts", - "to": "src/features/playlist/index.ts", - "unresolvedTo": "@/features/playlist", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistCovers.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/cover/prefetchRegistry.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/cover/storageKeys.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/playback/utils/playback/playbackServer.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, { "type": "cycle", "from": "src/features/offline/utils/pinnedOfflineSync.ts", @@ -22022,159 +15715,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -33406,7 +26947,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -33416,7 +26957,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/features/playback/store/skipStarRating.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -33425,138 +26966,6 @@ "import" ] }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistStarRating.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, { "name": "src/features/playback/store/pendingStarSync.ts", "dependencyTypes": [ @@ -36985,7 +30394,7 @@ ] }, { - "name": "src/features/playback/store/miscActions.ts", + "name": "src/features/playback/store/playTrackAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -36995,7 +30404,7 @@ ] }, { - "name": "src/features/playback/store/applyServerPlayQueue.ts", + "name": "src/features/playback/store/playListenSession.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -37004,138 +30413,6 @@ "import" ] }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, { "name": "src/features/playback/store/previewStore.ts", "dependencyTypes": [ @@ -38367,169 +31644,7 @@ ] }, { - "name": "src/features/playback/store/networkLoveActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/playerStoreTypes.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/playback/utils/playback/resolvePlaybackUrl.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/previewStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/orbitRuntime.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/orbit/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/orbit/components/OrbitJoinModal.tsx", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/utils/server/switchActiveServer.ts", + "name": "src/features/playback/store/nextAction.ts", "dependencyTypes": [ "aliased", "aliased-tsconfig", @@ -43055,2861 +36170,6 @@ } ] }, - { - "type": "cycle", - "from": "src/features/playlist/hooks/usePlaylistDerived.ts", - "to": "src/features/playback/store/playerStore.ts", - "unresolvedTo": "@/features/playback/store/playerStore", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistDerived.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/hooks/usePlaylistPreview.ts", - "to": "src/features/playback/store/previewStore.ts", - "unresolvedTo": "@/features/playback/store/previewStore", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playback/store/previewStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistPreview.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/hooks/usePlaylistRouteEffects.ts", - "to": "src/features/playback/store/playerStore.ts", - "unresolvedTo": "@/features/playback/store/playerStore", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistRouteEffects.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/hooks/usePlaylistsLibraryScopeCounts.ts", - "to": "src/lib/api/subsonicLibrary.ts", - "unresolvedTo": "@/lib/api/subsonicLibrary", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/lib/api/subsonicLibrary.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/lib/network/subsonicNetworkGuard.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistsLibraryScopeCounts.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/hooks/usePlaylistsLibraryScopeCounts.ts", - "to": "src/lib/api/subsonicPlaylists.ts", - "unresolvedTo": "@/lib/api/subsonicPlaylists", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/lib/api/subsonicPlaylists.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "dynamic-import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistsLibraryScopeCounts.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/hooks/usePlaylistStarRating.ts", - "to": "src/features/playback/store/pendingStarSync.ts", - "unresolvedTo": "@/features/playback/store/pendingStarSync", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playback/store/pendingStarSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistStarRating.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/hooks/usePlaylistStarRating.ts", - "to": "src/features/playback/store/playerStore.ts", - "unresolvedTo": "@/features/playback/store/playerStore", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistStarRating.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/hooks/usePlaylistSuggestions.ts", - "to": "src/lib/api/subsonicLibrary.ts", - "unresolvedTo": "@/lib/api/subsonicLibrary", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/lib/api/subsonicLibrary.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/lib/network/subsonicNetworkGuard.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/hooks/usePlaylistSuggestions.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/index.ts", - "to": "src/features/playlist/hooks/usePlaylistsLibraryScopeCounts.ts", - "unresolvedTo": "./hooks/usePlaylistsLibraryScopeCounts", - "dependencyTypes": [ - "local", - "export" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playlist/hooks/usePlaylistsLibraryScopeCounts.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/index.ts", - "to": "src/features/playlist/store/playlistStore.ts", - "unresolvedTo": "./store/playlistStore", - "dependencyTypes": [ - "local", - "export" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playlist/store/playlistStore.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/index.ts", - "to": "src/features/playlist/utils/playPlaylistById.ts", - "unresolvedTo": "./utils/playPlaylistById", - "dependencyTypes": [ - "local", - "export" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playlist/utils/playPlaylistById.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/index.ts", - "to": "src/features/playlist/utils/runPlaylistLoad.ts", - "unresolvedTo": "./utils/runPlaylistLoad", - "dependencyTypes": [ - "local", - "export" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playlist/utils/runPlaylistLoad.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/index.ts", - "to": "src/features/playlist/utils/runPlaylistsActions.ts", - "unresolvedTo": "./utils/runPlaylistsActions", - "dependencyTypes": [ - "local", - "export" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playlist/utils/runPlaylistsActions.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playlist/store/playlistStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/index.ts", - "to": "src/features/playlist/utils/runPlaylistSaveMeta.ts", - "unresolvedTo": "./utils/runPlaylistSaveMeta", - "dependencyTypes": [ - "local", - "export" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playlist/utils/runPlaylistSaveMeta.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/lib/api/subsonicPlaylists.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "dynamic-import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/index.ts", - "to": "src/features/playlist/utils/runPlaylistsSaveSmart.ts", - "unresolvedTo": "./utils/runPlaylistsSaveSmart", - "dependencyTypes": [ - "local", - "export" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playlist/utils/runPlaylistsSaveSmart.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/playlist/store/playlistStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/index.ts", - "to": "src/features/playlist/utils/runPlaylistZipDownload.ts", - "unresolvedTo": "./utils/runPlaylistZipDownload", - "dependencyTypes": [ - "local", - "export" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playlist/utils/runPlaylistZipDownload.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/store/playlistStore.ts", - "to": "src/lib/api/subsonicPlaylists.ts", - "unresolvedTo": "@/lib/api/subsonicPlaylists", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/lib/api/subsonicPlaylists.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "dynamic-import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/store/playlistStore.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/utils/playPlaylistById.ts", - "to": "src/lib/api/subsonicPlaylists.ts", - "unresolvedTo": "@/lib/api/subsonicPlaylists", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/lib/api/subsonicPlaylists.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "dynamic-import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/utils/playPlaylistById.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/utils/runPlaylistLoad.ts", - "to": "src/features/playlist/store/playlistStore.ts", - "unresolvedTo": "@/features/playlist/store/playlistStore", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/features/playlist/store/playlistStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/utils/runPlaylistLoad.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/utils/runPlaylistLoad.ts", - "to": "src/lib/api/subsonicLibrary.ts", - "unresolvedTo": "@/lib/api/subsonicLibrary", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/lib/api/subsonicLibrary.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/lib/network/subsonicNetworkGuard.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/utils/runPlaylistLoad.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/utils/runPlaylistLoad.ts", - "to": "src/lib/api/subsonicPlaylists.ts", - "unresolvedTo": "@/lib/api/subsonicPlaylists", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/lib/api/subsonicPlaylists.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "dynamic-import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/utils/runPlaylistLoad.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/utils/runPlaylistsActions.ts", - "to": "src/lib/api/subsonicPlaylists.ts", - "unresolvedTo": "@/lib/api/subsonicPlaylists", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/lib/api/subsonicPlaylists.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "dynamic-import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/utils/runPlaylistsActions.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, - { - "type": "cycle", - "from": "src/features/playlist/utils/runPlaylistZipDownload.ts", - "to": "src/lib/api/subsonicStreamUrl.ts", - "unresolvedTo": "@/lib/api/subsonicStreamUrl", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ], - "rule": { - "severity": "error", - "name": "no-circular" - }, - "cycle": [ - { - "name": "src/lib/api/subsonicStreamUrl.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/cover/storageKeys.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/utils/playback/playbackServer.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/playerStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/miscActions.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/applyServerPlayQueue.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/pausedRestorePrepare.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/engineLoadTrackAtPosition.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheTouch.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playback/store/hotCacheStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackResolve.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackStore.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/store/localPlaybackMigration.ts", - "dependencyTypes": [ - "local", - "import" - ] - }, - { - "name": "src/features/offline/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "type-only", - "import" - ] - }, - { - "name": "src/features/offline/hooks/useOfflineBrowseContext.ts", - "dependencyTypes": [ - "local", - "export" - ] - }, - { - "name": "src/features/offline/utils/offlineBrowseContext.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/offlinePlaylistBrowse.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/offline/utils/pinnedOfflineSync.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/index.ts", - "dependencyTypes": [ - "aliased", - "aliased-tsconfig", - "aliased-tsconfig-paths", - "local", - "import" - ] - }, - { - "name": "src/features/playlist/utils/runPlaylistZipDownload.ts", - "dependencyTypes": [ - "local", - "export" - ] - } - ] - }, { "type": "cycle", "from": "src/hotCachePrefetch.ts", diff --git a/CHANGELOG.md b/CHANGELOG.md index 23b2812d..231f3333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Desktop builds no longer get stuck showing "offline" when WebKitGTK leaves `navigator.onLine` stuck at `false` while the server is actually reachable — the app now confirms with a real server probe instead of trusting that hint, so browse and playback keep working. Web builds are unchanged. * Pending favorite/rating sync now flushes when the server actually becomes reachable again, rather than relying on a browser `online` event that may never fire on desktop. +### Playlists — add more than ~341 tracks; faster large-playlist edits + +**By [@cucadmuh](https://github.com/cucadmuh), PR [#1235](https://github.com/Psychotoxical/psysonic/pull/1235)** + +* Adding tracks to a playlist no longer fails past ~341 songs — writes are sent to the server in batches instead of one oversized request, so playlists of any size build correctly. +* Adding and merging into large playlists is faster: playlist membership is cached in memory for de-duplication instead of re-fetching the whole playlist on every add. + ## [1.49.0] - 2026-06-29 diff --git a/src/config/settingsCredits.ts b/src/config/settingsCredits.ts index 3d78a8f6..976f4a55 100644 --- a/src/config/settingsCredits.ts +++ b/src/config/settingsCredits.ts @@ -181,6 +181,7 @@ const CONTRIBUTOR_ENTRIES = [ 'Playback — ReplayGain index prefetch, gapless playbar sync, library replayGainPeak column, live RG refresh after sync (PR #1231)', 'Artists browse — album vs track credit mode toggle, starred favorites in both modes, persisted credit mode, SQL letter-bucket filter (PR #1232)', 'Connection — ignore spurious WebKitGTK navigator.onLine offline hint on desktop; confirm via server probe; flush pending favorite/rating sync on real reachability (report: mikmik on Psysonic Discord, PR #1234)', + 'Playlists — batch playlist writes past the GET URL limit (add >341 tracks), in-memory membership cache for fast dedup, offline↔playlist layering detangle (PR #1235)', ], }, { diff --git a/src/features/contextMenu/components/AddToPlaylistSubmenu.tsx b/src/features/contextMenu/components/AddToPlaylistSubmenu.tsx index b88ca2ee..872688f6 100644 --- a/src/features/contextMenu/components/AddToPlaylistSubmenu.tsx +++ b/src/features/contextMenu/components/AddToPlaylistSubmenu.tsx @@ -1,14 +1,11 @@ import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ListMusic, Plus } from 'lucide-react'; -import { getPlaylist, updatePlaylist } from '@/lib/api/subsonicPlaylists'; import type { SubsonicPlaylist } from '@/lib/api/subsonicTypes'; import { usePlaylistStore } from '@/features/playlist'; +import { addTracksToPlaylistWithDedup, showAddTracksDedupToast } from '@/features/playlist'; import { showToast } from '@/lib/dom/toast'; -import { - confirmAddAllDuplicates, - isSmartPlaylistName, -} from '@/features/contextMenu/utils/contextMenuHelpers'; +import { isSmartPlaylistName } from '@/features/contextMenu/utils/contextMenuHelpers'; interface Props { songIds: string[]; @@ -74,23 +71,9 @@ export function AddToPlaylistSubmenu({ songIds, resolveSongIds, onDone, dropDown const ids = idsForAction(); setAdding(pl.id); try { - const { songs } = await getPlaylist(pl.id); - const existingIds = new Set(songs.map((s) => s.id)); - const newIds = ids.filter((id) => !existingIds.has(id)); - if (newIds.length > 0) { - await updatePlaylist(pl.id, [...songs.map((s) => s.id), ...newIds]); - showToast(t('playlists.addSuccess', { count: newIds.length, playlist: pl.name })); - touchPlaylist(pl.id); - } else { - const accepted = await confirmAddAllDuplicates(pl.name, ids.length, t); - if (accepted) { - await updatePlaylist(pl.id, [...songs.map((s) => s.id), ...ids]); - showToast(t('playlists.addedAsDuplicates', { count: ids.length, playlist: pl.name }), 3000, 'info'); - touchPlaylist(pl.id); - } else { - showToast(t('playlists.addAllSkipped', { count: ids.length, playlist: pl.name }), 3000, 'info'); - } - } + const result = await addTracksToPlaylistWithDedup(pl.id, pl.name, ids, t); + showAddTracksDedupToast(t, pl.name, result); + if (result.outcome !== 'skipped') touchPlaylist(pl.id); } catch { showToast(t('playlists.addError'), 3000, 'error'); } diff --git a/src/features/contextMenu/components/MultiAlbumToPlaylistSubmenu.tsx b/src/features/contextMenu/components/MultiAlbumToPlaylistSubmenu.tsx index 6266168e..70608be3 100644 --- a/src/features/contextMenu/components/MultiAlbumToPlaylistSubmenu.tsx +++ b/src/features/contextMenu/components/MultiAlbumToPlaylistSubmenu.tsx @@ -1,14 +1,12 @@ import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ListMusic, Plus } from 'lucide-react'; -import { resolveAlbum, resolveMediaServerId, resolvePlaylist } from '@/features/offline'; +import { resolveAlbum, resolveMediaServerId } from '@/features/offline'; import type { SubsonicPlaylist } from '@/lib/api/subsonicTypes'; import { usePlaylistStore } from '@/features/playlist'; +import { addTracksToPlaylistWithDedup, showAddTracksDedupToast } from '@/features/playlist'; import { showToast } from '@/lib/dom/toast'; -import { - confirmAddAllDuplicates, - isSmartPlaylistName, -} from '@/features/contextMenu/utils/contextMenuHelpers'; +import { isSmartPlaylistName } from '@/features/contextMenu/utils/contextMenuHelpers'; interface Props { albumIds: string[]; @@ -39,46 +37,12 @@ export function MultiAlbumToPlaylistSubmenu({ albumIds, onDone, triggerId: _trig }, [albumIds]); const handleAddWithToast = async (pl: SubsonicPlaylist, songIds: string[]) => { - const { updatePlaylist } = await import('@/lib/api/subsonicPlaylists'); const touchPlaylist = usePlaylistStore.getState().touchPlaylist; try { - const serverId = resolveMediaServerId(); - if (!serverId) return; - const resolved = await resolvePlaylist(serverId, pl.id); - if (!resolved) return; - const { songs: existingSongs } = resolved; - const existingIds = new Set(existingSongs.map((s) => s.id)); - - const newIds: string[] = []; - const duplicateIds: string[] = []; - - for (const id of songIds) { - if (existingIds.has(id)) duplicateIds.push(id); - else newIds.push(id); - } - - const addedCount = newIds.length; - const duplicateCount = duplicateIds.length; - - if (addedCount > 0) { - await updatePlaylist(pl.id, [...existingSongs.map((s) => s.id), ...newIds]); - touchPlaylist(pl.id); - if (duplicateCount > 0) { - showToast(t('playlists.addPartial', { added: addedCount, skipped: duplicateCount, playlist: pl.name }), 4000, 'info'); - } else { - showToast(t('playlists.addSuccess', { count: addedCount, playlist: pl.name }), 3000, 'info'); - } - } else if (duplicateCount > 0) { - const accepted = await confirmAddAllDuplicates(pl.name, duplicateCount, t); - if (accepted) { - await updatePlaylist(pl.id, [...existingSongs.map((s) => s.id), ...songIds]); - touchPlaylist(pl.id); - showToast(t('playlists.addedAsDuplicates', { count: duplicateCount, playlist: pl.name }), 3000, 'info'); - } else { - showToast(t('playlists.addAllSkipped', { count: duplicateCount, playlist: pl.name }), 4000, 'info'); - } - } + const result = await addTracksToPlaylistWithDedup(pl.id, pl.name, songIds, t); + showAddTracksDedupToast(t, pl.name, result); + if (result.outcome !== 'skipped') touchPlaylist(pl.id); } catch { showToast(t('playlists.addError'), 4000, 'error'); } diff --git a/src/features/contextMenu/components/MultiArtistToPlaylistSubmenu.tsx b/src/features/contextMenu/components/MultiArtistToPlaylistSubmenu.tsx index bf37e6af..463a2795 100644 --- a/src/features/contextMenu/components/MultiArtistToPlaylistSubmenu.tsx +++ b/src/features/contextMenu/components/MultiArtistToPlaylistSubmenu.tsx @@ -1,15 +1,13 @@ import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ListMusic, Plus } from 'lucide-react'; -import { resolveAlbum, resolveArtist, resolveMediaServerId, resolvePlaylist } from '@/features/offline'; +import { resolveAlbum, resolveArtist, resolveMediaServerId } from '@/features/offline'; import { getPlaylists } from '@/lib/api/subsonicPlaylists'; import type { SubsonicPlaylist } from '@/lib/api/subsonicTypes'; import { usePlaylistStore } from '@/features/playlist'; +import { addTracksToPlaylistWithDedup, showAddTracksDedupToast } from '@/features/playlist'; import { showToast } from '@/lib/dom/toast'; -import { - confirmAddAllDuplicates, - isSmartPlaylistName, -} from '@/features/contextMenu/utils/contextMenuHelpers'; +import { isSmartPlaylistName } from '@/features/contextMenu/utils/contextMenuHelpers'; interface Props { artistIds: string[]; @@ -53,46 +51,12 @@ export function MultiArtistToPlaylistSubmenu({ artistIds, onDone, triggerId: _tr }, [artistIds]); const handleAddWithToast = async (pl: SubsonicPlaylist, songIds: string[]) => { - const { updatePlaylist } = await import('@/lib/api/subsonicPlaylists'); const touchPlaylist = usePlaylistStore.getState().touchPlaylist; try { - const serverId = resolveMediaServerId(); - if (!serverId) return; - const resolved = await resolvePlaylist(serverId, pl.id); - if (!resolved) return; - const { songs: existingSongs } = resolved; - const existingIds = new Set(existingSongs.map((s) => s.id)); - - const newIds: string[] = []; - const duplicateIds: string[] = []; - - for (const id of songIds) { - if (existingIds.has(id)) duplicateIds.push(id); - else newIds.push(id); - } - - const addedCount = newIds.length; - const duplicateCount = duplicateIds.length; - - if (addedCount > 0) { - await updatePlaylist(pl.id, [...existingSongs.map((s) => s.id), ...newIds]); - touchPlaylist(pl.id); - if (duplicateCount > 0) { - showToast(t('playlists.addPartial', { added: addedCount, skipped: duplicateCount, playlist: pl.name }), 4000, 'info'); - } else { - showToast(t('playlists.addSuccess', { count: addedCount, playlist: pl.name }), 3000, 'info'); - } - } else if (duplicateCount > 0) { - const accepted = await confirmAddAllDuplicates(pl.name, duplicateCount, t); - if (accepted) { - await updatePlaylist(pl.id, [...existingSongs.map((s) => s.id), ...songIds]); - touchPlaylist(pl.id); - showToast(t('playlists.addedAsDuplicates', { count: duplicateCount, playlist: pl.name }), 3000, 'info'); - } else { - showToast(t('playlists.addAllSkipped', { count: duplicateCount, playlist: pl.name }), 4000, 'info'); - } - } + const result = await addTracksToPlaylistWithDedup(pl.id, pl.name, songIds, t); + showAddTracksDedupToast(t, pl.name, result); + if (result.outcome !== 'skipped') touchPlaylist(pl.id); } catch { showToast(t('playlists.addError'), 4000, 'error'); } diff --git a/src/features/contextMenu/components/PlaylistToPlaylistSubmenus.tsx b/src/features/contextMenu/components/PlaylistToPlaylistSubmenus.tsx index 5a2c58fb..f20f6d8a 100644 --- a/src/features/contextMenu/components/PlaylistToPlaylistSubmenus.tsx +++ b/src/features/contextMenu/components/PlaylistToPlaylistSubmenus.tsx @@ -1,7 +1,13 @@ import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ListMusic, Plus } from 'lucide-react'; -import { usePlaylistStore } from '@/features/playlist'; +import { + usePlaylistStore, + addTracksToPlaylistWithDedup, + collectMergeSongIds, + resolvePlaylistSongIds, +} from '@/features/playlist'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; import { showToast } from '@/lib/dom/toast'; import { isSmartPlaylistName } from '@/features/contextMenu/utils/contextMenuHelpers'; @@ -41,7 +47,7 @@ export function SinglePlaylistToPlaylistSubmenu({ playlist, onDone, triggerId }: const handleCreate = async () => { if (!newName.trim()) return; - const { createPlaylist } = await import('@/lib/api/subsonicPlaylists'); + const createPlaylist = usePlaylistStore.getState().createPlaylist; try { const newPl = await createPlaylist(newName.trim(), []); if (newPl?.id) { @@ -55,15 +61,20 @@ export function SinglePlaylistToPlaylistSubmenu({ playlist, onDone, triggerId }: }; const handleAddToNewPlaylist = async (targetId: string, targetName: string) => { - const { getPlaylist, updatePlaylist } = await import('@/lib/api/subsonicPlaylists'); const touchPlaylist = usePlaylistStore.getState().touchPlaylist; try { - const { songs: sourceSongs } = await getPlaylist(playlist.id); - if (sourceSongs.length > 0) { - await updatePlaylist(targetId, sourceSongs.map((s: { id: string }) => s.id)); - touchPlaylist(targetId); - showToast(t('playlists.createAndAddSuccess', { count: sourceSongs.length, playlist: targetName }), 3000, 'info'); + const { getPlaylist } = await import('@/lib/api/subsonicPlaylists'); + const sourceIds = await resolvePlaylistSongIds(playlist.id, async () => { + const { songs } = await getPlaylist(playlist.id); + return songs.map(s => s.id); + }); + if (sourceIds.length > 0) { + const result = await addTracksToPlaylistWithDedup(targetId, targetName, sourceIds, t); + if (result.addedCount > 0) { + showToast(t('playlists.createAndAddSuccess', { count: result.addedCount, playlist: targetName }), 3000, 'info'); + touchPlaylist(targetId); + } } onDone(); } catch { @@ -73,22 +84,20 @@ export function SinglePlaylistToPlaylistSubmenu({ playlist, onDone, triggerId }: }; const handleAdd = async (targetId: string, targetName: string) => { - const { getPlaylist, updatePlaylist } = await import('@/lib/api/subsonicPlaylists'); const touchPlaylist = usePlaylistStore.getState().touchPlaylist; try { - const { songs: targetSongs } = await getPlaylist(targetId); - const targetIds = new Set(targetSongs.map((s: { id: string }) => s.id)); - const { songs: sourceSongs } = await getPlaylist(playlist.id); - const newSongs = sourceSongs.filter((s: { id: string }) => !targetIds.has(s.id)); - - if (newSongs.length > 0) { - newSongs.forEach((s: { id: string }) => targetIds.add(s.id)); - await updatePlaylist(targetId, Array.from(targetIds)); - touchPlaylist(targetId); - showToast(t('playlists.addToPlaylistSuccess', { count: newSongs.length, playlist: targetName }), 3000, 'info'); - } else { + const { getPlaylist } = await import('@/lib/api/subsonicPlaylists'); + const sourceIds = await resolvePlaylistSongIds(playlist.id, async () => { + const { songs } = await getPlaylist(playlist.id); + return songs.map(s => s.id); + }); + const result = await addTracksToPlaylistWithDedup(targetId, targetName, sourceIds, t); + if (result.outcome === 'skipped') { showToast(t('playlists.addToPlaylistNoNew', { playlist: targetName }), 3000, 'info'); + } else { + showToast(t('playlists.addToPlaylistSuccess', { count: result.addedCount, playlist: targetName }), 3000, 'info'); + touchPlaylist(targetId); } onDone(); } catch { @@ -180,7 +189,7 @@ export function MultiPlaylistToPlaylistSubmenu({ playlists, onDone, triggerId }: const handleCreate = async () => { if (!newName.trim()) return; - const { createPlaylist } = await import('@/lib/api/subsonicPlaylists'); + const createPlaylist = usePlaylistStore.getState().createPlaylist; try { const newPl = await createPlaylist(newName.trim(), []); if (newPl?.id) { @@ -194,61 +203,44 @@ export function MultiPlaylistToPlaylistSubmenu({ playlists, onDone, triggerId }: }; const handleMergeToNewPlaylist = async (targetId: string, targetName: string) => { - const { getPlaylist, updatePlaylist } = await import('@/lib/api/subsonicPlaylists'); + const { addSongsToPlaylist } = await import('@/lib/api/subsonicPlaylists'); const touchPlaylist = usePlaylistStore.getState().touchPlaylist; + const membership = usePlaylistMembershipStore.getState(); try { - const targetIds = new Set(); - let totalAdded = 0; - - for (const pl of playlists) { - const { songs } = await getPlaylist(pl.id); - const newSongs = songs.filter((s: { id: string }) => !targetIds.has(s.id)); - if (newSongs.length > 0) { - newSongs.forEach((s: { id: string }) => targetIds.add(s.id)); - totalAdded += newSongs.length; - } - } - - if (totalAdded > 0) { - await updatePlaylist(targetId, Array.from(targetIds)); + const idsToAdd = await collectMergeSongIds(targetId, playlists.map(p => p.id)); + if (idsToAdd.length > 0) { + await addSongsToPlaylist(targetId, idsToAdd); + membership.appendPlaylistSongIds(targetId, idsToAdd); touchPlaylist(targetId); - showToast(t('playlists.createAndAddSuccess', { count: totalAdded, playlist: targetName }), 3000, 'info'); + showToast(t('playlists.createAndAddSuccess', { count: idsToAdd.length, playlist: targetName }), 3000, 'info'); } onDone(); } catch { + membership.invalidatePlaylistSongIds(targetId); showToast(t('playlists.mergeError'), 4000, 'error'); onDone(); } }; const handleMerge = async (targetId: string, targetName: string) => { - const { getPlaylist, updatePlaylist } = await import('@/lib/api/subsonicPlaylists'); + const { addSongsToPlaylist } = await import('@/lib/api/subsonicPlaylists'); const touchPlaylist = usePlaylistStore.getState().touchPlaylist; + const membership = usePlaylistMembershipStore.getState(); try { - const { songs: targetSongs } = await getPlaylist(targetId); - const targetIds = new Set(targetSongs.map((s: { id: string }) => s.id)); - let totalAdded = 0; - - for (const pl of playlists) { - const { songs } = await getPlaylist(pl.id); - const newSongs = songs.filter((s: { id: string }) => !targetIds.has(s.id)); - if (newSongs.length > 0) { - newSongs.forEach((s: { id: string }) => targetIds.add(s.id)); - totalAdded += newSongs.length; - } - } - - if (totalAdded > 0) { - await updatePlaylist(targetId, Array.from(targetIds)); + const idsToAdd = await collectMergeSongIds(targetId, playlists.map(p => p.id)); + if (idsToAdd.length > 0) { + await addSongsToPlaylist(targetId, idsToAdd); + membership.appendPlaylistSongIds(targetId, idsToAdd); touchPlaylist(targetId); - showToast(t('playlists.mergeSuccess', { count: totalAdded, playlist: targetName }), 3000, 'info'); + showToast(t('playlists.mergeSuccess', { count: idsToAdd.length, playlist: targetName }), 3000, 'info'); } else { showToast(t('playlists.mergeNoNewSongs'), 3000, 'info'); } onDone(); } catch { + membership.invalidatePlaylistSongIds(targetId); showToast(t('playlists.mergeError'), 4000, 'error'); onDone(); } diff --git a/src/features/contextMenu/components/SongContextItems.tsx b/src/features/contextMenu/components/SongContextItems.tsx index fddf1cd0..680f180f 100644 --- a/src/features/contextMenu/components/SongContextItems.tsx +++ b/src/features/contextMenu/components/SongContextItems.tsx @@ -2,12 +2,13 @@ import { useTranslation } from 'react-i18next'; import { Play, ListPlus, Radio, Heart, ChevronRight, ChevronsRight, User, Disc3, ListMusic, Info, Sparkles, Star, Trash2, HeartCrack, Share2, Orbit as OrbitIcon } from 'lucide-react'; import { useNavigateToAlbum } from '@/features/album'; import { useNavigateToArtist } from '@/features/artist'; -import { resolveAlbum, resolveMediaServerId, resolvePlaylist } from '@/features/offline'; +import { resolveAlbum, resolveMediaServerId } from '@/features/offline'; import { queueSongStar } from '@/features/playback/store/pendingStarSync'; import { getMusicNetworkRuntime, useEnrichmentPrimary } from '@/music-network'; import type { Track } from '@/lib/media/trackTypes'; import { useAuthStore } from '@/store/authStore'; import { usePlaylistStore } from '@/features/playlist'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; import { songToTrack } from '@/lib/media/songToTrack'; import { showToast } from '@/lib/dom/toast'; import { suggestOrbitTrack, hostEnqueueToOrbit, evaluateOrbitSuggestGate, OrbitSuggestBlockedError } from '@/features/orbit'; @@ -178,21 +179,17 @@ export default function SongContextItems(props: ContextMenuItemsProps) { {offlinePolicy.canEditPlaylist && playlistId && playlistSongIndex !== undefined && (
handleAction(async () => { - const { updatePlaylist } = await import('@/lib/api/subsonicPlaylists'); + const { removePlaylistSongsAtIndices } = await import('@/lib/api/subsonicPlaylists'); const { showToast } = await import('@/lib/dom/toast'); - const touchPlaylist = usePlaylistStore.getState().touchPlaylist; + const { touchPlaylist } = usePlaylistStore.getState(); + const membership = usePlaylistMembershipStore.getState(); try { - const serverId = resolveMediaServerId(); - if (!serverId) return; - const resolved = await resolvePlaylist(serverId, playlistId); - if (!resolved) return; - const { songs } = resolved; - const prevCount = songs.length; - const updatedIds = songs.filter((_, i) => i !== playlistSongIndex).map(s => s.id); - await updatePlaylist(playlistId, updatedIds, prevCount); + await removePlaylistSongsAtIndices(playlistId, [playlistSongIndex]); + membership.removePlaylistSongIdsAtIndices(playlistId, [playlistSongIndex]); touchPlaylist(playlistId); showToast(t('playlists.removeSuccess'), 3000, 'info'); } catch { + membership.invalidatePlaylistSongIds(playlistId); showToast(t('playlists.removeError'), 4000, 'error'); } })}> diff --git a/src/features/contextMenu/utils/contextMenuHelpers.ts b/src/features/contextMenu/utils/contextMenuHelpers.ts index 8397260a..f1ee4aae 100644 --- a/src/features/contextMenu/utils/contextMenuHelpers.ts +++ b/src/features/contextMenu/utils/contextMenuHelpers.ts @@ -1,5 +1,3 @@ -import { useConfirmModalStore } from '@/store/confirmModalStore'; - /** Psysonic smart playlists (Navidrome); not valid targets for manual add-to-playlist. */ export const SMART_PLAYLIST_PREFIX = 'psy-smart-'; @@ -25,18 +23,3 @@ export function shuffleArray(arr: T[]): T[] { return result; } -/** Ask user before re-adding songs to a playlist when *all* selected ids are - * already present. Returns true → caller should append them as duplicates, - * false → caller should keep today's silent-skip toast behavior. */ -export async function confirmAddAllDuplicates( - playlistName: string, - count: number, - t: (key: string, opts?: Record) => string, -): Promise { - return useConfirmModalStore.getState().request({ - title: t('playlists.duplicateConfirmTitle'), - message: t('playlists.duplicateConfirmMessage', { count, playlist: playlistName }), - confirmLabel: t('playlists.duplicateConfirmAction'), - cancelLabel: t('common.cancel'), - }); -} diff --git a/src/features/offline/utils/pinnedOfflineSync.ts b/src/features/offline/utils/pinnedOfflineSync.ts index b3d34319..a4b8dba5 100644 --- a/src/features/offline/utils/pinnedOfflineSync.ts +++ b/src/features/offline/utils/pinnedOfflineSync.ts @@ -7,7 +7,6 @@ import { useAuthStore } from '@/store/authStore'; import type { PinSource } from '@/store/localPlaybackStore'; import { useLocalPlaybackStore } from '@/store/localPlaybackStore'; import { useOfflineStore } from '@/features/offline/store/offlineStore'; -import { usePlaylistStore } from '@/features/playlist'; import { isSmartPlaylistName } from '@/lib/format/playlistDetailHelpers'; import { getMediaDir } from '@/lib/media/mediaDir'; import { deleteMediaFile } from '@/lib/api/syncfs'; @@ -58,8 +57,11 @@ function offlineMeta(sourceId: string, serverId: string) { } function resolvePlaylistName(playlistId: string, serverId: string): string | undefined { - return offlineMeta(playlistId, serverId)?.name - ?? usePlaylistStore.getState().playlists.find(p => p.id === playlistId)?.name; + // Only pinned playlists reach the nameless internal callers (all gated by + // isSourcePinnedOffline), so offline meta always carries the name here; external + // callers pass `name` explicitly. Avoid importing the playlist feature barrel — + // that edge closes offline↔playlist import cycles (see 2026-07 detangle task). + return offlineMeta(playlistId, serverId)?.name; } /** Smart playlists refresh from server rules — not eligible for manual offline cache/sync. */ diff --git a/src/features/orbit/utils/guest.ts b/src/features/orbit/utils/guest.ts index f1770c4f..0ce0492c 100644 --- a/src/features/orbit/utils/guest.ts +++ b/src/features/orbit/utils/guest.ts @@ -1,7 +1,8 @@ -import { createPlaylist, deletePlaylist, getPlaylist, getPlaylists, updatePlaylist } from '@/lib/api/subsonicPlaylists'; +import { createPlaylist, deletePlaylist, getPlaylist, getPlaylists, addSongsToPlaylist } from '@/lib/api/subsonicPlaylists'; import { getSong } from '@/lib/api/subsonicLibrary'; import { songToTrack } from '@/lib/media/songToTrack'; import { useAuthStore } from '@/store/authStore'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; import { useOrbitStore } from '@/features/orbit/store/orbitStore'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { @@ -189,15 +190,16 @@ export async function suggestOrbitTrack(trackId: string): Promise { /** * Append a track to an outbox playlist unless it's already there. Subsonic's - * playlist update replaces the song list wholesale, so we carry the existing - * ids along. Shared by the initial suggest and the guest tick's lost-update - * re-send (where a no-op append means the host already cleared + recorded it). + * playlist update replaces the song list wholesale on sweep, so we read the + * current server list before append. A no-op when the track is already present + * means the host already cleared + recorded it (lost-update re-send path). */ export async function ensureTrackInOutbox(outboxPlaylistId: string, trackId: string): Promise { const { songs } = await getPlaylist(outboxPlaylistId); const ids = songs.map(s => s.id); if (ids.includes(trackId)) return; - await updatePlaylist(outboxPlaylistId, [...ids, trackId], ids.length); + await addSongsToPlaylist(outboxPlaylistId, [trackId]); + usePlaylistMembershipStore.getState().setPlaylistSongIds(outboxPlaylistId, [...ids, trackId]); } /** diff --git a/src/features/playlist/index.ts b/src/features/playlist/index.ts index e4924ba6..5c30f89b 100644 --- a/src/features/playlist/index.ts +++ b/src/features/playlist/index.ts @@ -25,6 +25,7 @@ export * from './hooks/usePlaylistSuggestions'; export * from './store/playlistFolderStore'; export * from './store/playlistLayoutStore'; export * from './store/playlistStore'; +export * from './utils/addTracksToPlaylistWithDedup'; export * from './utils/playlistBulkPlayActions'; export * from './utils/playlistDisplayedSongs'; export * from './utils/playlistFolders'; diff --git a/src/features/playlist/pages/PlaylistDetail.tsx b/src/features/playlist/pages/PlaylistDetail.tsx index d08e2ec7..e50e5053 100644 --- a/src/features/playlist/pages/PlaylistDetail.tsx +++ b/src/features/playlist/pages/PlaylistDetail.tsx @@ -6,6 +6,7 @@ import { useTracklistColumns, type ColDef } from '@/lib/hooks/useTracklistColumn import { usePlayerStore } from '@/features/playback/store/playerStore'; import { useShallow } from 'zustand/react/shallow'; import { usePlaylistStore } from '@/features/playlist/store/playlistStore'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; import { useOfflineStore } from '@/features/offline'; import { useLocalPlaybackStore } from '@/store/localPlaybackStore'; import { useAlbumOfflineState } from '@/features/album'; @@ -117,8 +118,11 @@ export default function PlaylistDetail() { setSaving(true); try { await updatePlaylist(id, updatedSongs.map(s => s.id), prevCount); - if (id) touchPlaylist(id); - } catch { /* ignore: best-effort */ } + usePlaylistMembershipStore.getState().replacePlaylistSongIds(id, updatedSongs.map(s => s.id)); + touchPlaylist(id); + } catch { + usePlaylistMembershipStore.getState().invalidatePlaylistSongIds(id); + } setSaving(false); }, [id, touchPlaylist]); diff --git a/src/features/playlist/store/playlistStore.ts b/src/features/playlist/store/playlistStore.ts index 4bbc8dd0..3de42a18 100644 --- a/src/features/playlist/store/playlistStore.ts +++ b/src/features/playlist/store/playlistStore.ts @@ -1,11 +1,11 @@ -import { getPlaylists } from '@/lib/api/subsonicPlaylists'; +import { getPlaylists, createPlaylist as apiCreatePlaylist } from '@/lib/api/subsonicPlaylists'; import type { SubsonicPlaylist } from '@/lib/api/subsonicTypes'; import { create } from 'zustand'; import { persist } from 'zustand/middleware'; -import { createPlaylist as apiCreatePlaylist } from '@/lib/api/subsonicPlaylists'; import { useAuthStore } from '@/store/authStore'; -import { isOfflineBrowseActive } from '@/features/offline'; -import { fetchOfflineBrowsablePlaylists } from '@/features/offline'; +import { isOfflineBrowseActive, fetchOfflineBrowsablePlaylists } from '@/features/offline'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; + interface PlaylistStore { recentIds: string[]; playlists: SubsonicPlaylist[]; @@ -30,10 +30,13 @@ export const usePlaylistStore = create()( recentIds: [id, ...s.recentIds.filter((x) => x !== id)].slice(0, 50), lastModified: { ...s.lastModified, [id]: Date.now() }, })), - removeId: (id) => - set((s) => ({ recentIds: s.recentIds.filter((x) => x !== id) })), + removeId: (id) => { + usePlaylistMembershipStore.getState().invalidatePlaylistSongIds(id); + set((s) => ({ recentIds: s.recentIds.filter((x) => x !== id) })); + }, fetchPlaylists: async () => { set({ playlistsLoading: true }); + usePlaylistMembershipStore.getState().clearAllPlaylistSongIds(); try { const serverId = useAuthStore.getState().activeServerId; if (isOfflineBrowseActive() && serverId) { @@ -54,6 +57,7 @@ export const usePlaylistStore = create()( playlists: [...s.playlists, playlist], recentIds: [playlist.id, ...s.recentIds.filter((x) => x !== playlist.id)].slice(0, 50), })); + usePlaylistMembershipStore.getState().setPlaylistSongIds(playlist.id, songIds ?? []); return playlist; } catch { return null; @@ -65,6 +69,13 @@ export const usePlaylistStore = create()( })); }, }), - { name: 'psysonic_playlists_recent' } - ) + { + name: 'psysonic_playlists_recent', + partialize: (state) => ({ + recentIds: state.recentIds, + playlists: state.playlists, + lastModified: state.lastModified, + }), + }, + ), ); diff --git a/src/features/playlist/utils/addTracksToPlaylistWithDedup.test.ts b/src/features/playlist/utils/addTracksToPlaylistWithDedup.test.ts new file mode 100644 index 00000000..4fa8783e --- /dev/null +++ b/src/features/playlist/utils/addTracksToPlaylistWithDedup.test.ts @@ -0,0 +1,65 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { addTracksToPlaylistWithDedup } from '@/features/playlist/utils/addTracksToPlaylistWithDedup'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; + +const addSongsToPlaylistMock = vi.fn(async (_id: string, _ids: string[]) => {}); +const getPlaylistMock = vi.fn(async (_id: string) => ({ playlist: { id: 'pl-1' }, songs: [{ id: 'a' }, { id: 'b' }] })); +const confirmMock = vi.fn(async () => false); + +vi.mock('@/lib/api/subsonicPlaylists', () => ({ + addSongsToPlaylist: (id: string, ids: string[]) => addSongsToPlaylistMock(id, ids), + getPlaylist: (id: string) => getPlaylistMock(id), +})); + +vi.mock('@/store/confirmModalStore', () => ({ + useConfirmModalStore: { + getState: () => ({ request: () => confirmMock() }), + }, +})); + +vi.mock('@/store/authStore', () => ({ + useAuthStore: { + getState: () => ({ activeServerId: 'srv-1' }), + }, +})); + +describe('addTracksToPlaylistWithDedup', () => { + beforeEach(() => { + addSongsToPlaylistMock.mockClear(); + getPlaylistMock.mockClear(); + confirmMock.mockReset(); + confirmMock.mockResolvedValue(false); + usePlaylistMembershipStore.setState({ + songIdsByCacheKey: { 'srv-1:pl-1': ['a', 'b'] }, + }); + }); + + it('dedupes against cached ids without getPlaylist', async () => { + const result = await addTracksToPlaylistWithDedup('pl-1', 'Mix', ['b', 'c'], k => k); + expect(result).toMatchObject({ outcome: 'partial', addedCount: 1, skippedCount: 1 }); + expect(getPlaylistMock).not.toHaveBeenCalled(); + expect(addSongsToPlaylistMock).toHaveBeenCalledWith('pl-1', ['c']); + expect(usePlaylistMembershipStore.getState().getPlaylistSongIds('pl-1')).toEqual(['a', 'b', 'c']); + }); + + it('fetches membership once on cold cache and dedupes', async () => { + usePlaylistMembershipStore.setState({ songIdsByCacheKey: {} }); + getPlaylistMock.mockResolvedValue({ + playlist: { id: 'pl-2' }, + songs: [{ id: 'x' }], + }); + const result = await addTracksToPlaylistWithDedup('pl-2', 'Cold', ['x', 'y'], k => k); + expect(result).toMatchObject({ outcome: 'partial', addedCount: 1, skippedCount: 1 }); + expect(getPlaylistMock).toHaveBeenCalledTimes(1); + expect(addSongsToPlaylistMock).toHaveBeenCalledWith('pl-2', ['y']); + expect(usePlaylistMembershipStore.getState().getPlaylistSongIds('pl-2')).toEqual(['x', 'y']); + }); + + it('invalidates cache when the write fails', async () => { + addSongsToPlaylistMock.mockRejectedValueOnce(new Error('boom')); + await expect( + addTracksToPlaylistWithDedup('pl-1', 'Mix', ['c'], k => k), + ).rejects.toThrow('boom'); + expect(usePlaylistMembershipStore.getState().getPlaylistSongIds('pl-1')).toBeUndefined(); + }); +}); diff --git a/src/features/playlist/utils/addTracksToPlaylistWithDedup.ts b/src/features/playlist/utils/addTracksToPlaylistWithDedup.ts new file mode 100644 index 00000000..a8beb834 --- /dev/null +++ b/src/features/playlist/utils/addTracksToPlaylistWithDedup.ts @@ -0,0 +1,152 @@ +import { addSongsToPlaylist, getPlaylist } from '@/lib/api/subsonicPlaylists'; +import { useConfirmModalStore } from '@/store/confirmModalStore'; +import { showToast } from '@/lib/dom/toast'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; + +export type AddTracksDedupOutcome = 'added' | 'added_duplicates' | 'partial' | 'skipped'; + +export interface AddTracksDedupResult { + outcome: AddTracksDedupOutcome; + addedCount: number; + skippedCount: number; +} + +/** Ask before re-adding songs when *all* selected ids are already present. + * Returns true → append as duplicates, false → keep the silent-skip behavior. */ +export async function confirmAddAllDuplicates( + playlistName: string, + count: number, + t: (key: string, opts?: Record) => string, +): Promise { + return useConfirmModalStore.getState().request({ + title: t('playlists.duplicateConfirmTitle'), + message: t('playlists.duplicateConfirmMessage', { count, playlist: playlistName }), + confirmLabel: t('playlists.duplicateConfirmAction'), + cancelLabel: t('common.cancel'), + }); +} + +/** Add tracks with dedup; membership from cache or one getPlaylist on cache miss (GET response, not long URL). */ +export async function addTracksToPlaylistWithDedup( + playlistId: string, + playlistName: string, + trackIds: readonly string[], + t: (key: string, opts?: Record) => string, +): Promise { + if (trackIds.length === 0) { + return { outcome: 'skipped', addedCount: 0, skippedCount: 0 }; + } + + // Dedup reads the membership snapshot, awaits the write, then appends. Concurrent + // adds to the same playlist could interleave on this read-modify-append; the risk is + // a rare missed dedup, self-healing on the next full load. Acceptable for a UI action. + const store = usePlaylistMembershipStore.getState(); + const existingIds = new Set( + await resolvePlaylistSongIds(playlistId, async () => { + const { songs } = await getPlaylist(playlistId); + return songs.map(s => s.id); + }), + ); + const newIds = trackIds.filter(id => !existingIds.has(id)); + + try { + if (newIds.length > 0) { + await addSongsToPlaylist(playlistId, newIds); + store.appendPlaylistSongIds(playlistId, newIds); + return { + outcome: newIds.length === trackIds.length ? 'added' : 'partial', + addedCount: newIds.length, + skippedCount: trackIds.length - newIds.length, + }; + } + + const accepted = await confirmAddAllDuplicates(playlistName, trackIds.length, t); + if (!accepted) { + return { outcome: 'skipped', addedCount: 0, skippedCount: trackIds.length }; + } + + await addSongsToPlaylist(playlistId, [...trackIds]); + store.appendPlaylistSongIds(playlistId, trackIds); + return { outcome: 'added_duplicates', addedCount: trackIds.length, skippedCount: 0 }; + } catch (err) { + // A batched write may have partially landed — drop the cache so the next read refetches truth. + store.invalidatePlaylistSongIds(playlistId); + throw err; + } +} + +export function showAddTracksDedupToast( + t: (key: string, opts?: Record) => string, + playlistName: string, + result: AddTracksDedupResult, +): void { + switch (result.outcome) { + case 'added': + showToast(t('playlists.addSuccess', { count: result.addedCount, playlist: playlistName })); + break; + case 'partial': + showToast( + t('playlists.addPartial', { + added: result.addedCount, + skipped: result.skippedCount, + playlist: playlistName, + }), + 4000, + 'info', + ); + break; + case 'added_duplicates': + showToast( + t('playlists.addedAsDuplicates', { count: result.addedCount, playlist: playlistName }), + 3000, + 'info', + ); + break; + case 'skipped': + showToast( + t('playlists.addAllSkipped', { count: result.skippedCount, playlist: playlistName }), + 3000, + 'info', + ); + break; + } +} + +/** Resolve song ids for a playlist: in-memory cache first, network fallback (then cached). */ +export async function resolvePlaylistSongIds( + playlistId: string, + fetch: () => Promise, +): Promise { + const cached = usePlaylistMembershipStore.getState().getPlaylistSongIds(playlistId); + if (cached !== undefined) return cached; + const ids = await fetch(); + usePlaylistMembershipStore.getState().setPlaylistSongIds(playlistId, ids); + return ids; +} + +/** Collect song ids to merge into target, using cached membership when available. */ +export async function collectMergeSongIds( + targetPlaylistId: string, + sourcePlaylistIds: readonly string[], +): Promise { + const targetIds = new Set( + await resolvePlaylistSongIds(targetPlaylistId, async () => { + const { songs } = await getPlaylist(targetPlaylistId); + return songs.map(s => s.id); + }), + ); + const idsToAdd: string[] = []; + for (const sourceId of sourcePlaylistIds) { + const sourceIds = await resolvePlaylistSongIds(sourceId, async () => { + const { songs } = await getPlaylist(sourceId); + return songs.map(s => s.id); + }); + for (const songId of sourceIds) { + if (!targetIds.has(songId)) { + targetIds.add(songId); + idsToAdd.push(songId); + } + } + } + return idsToAdd; +} diff --git a/src/features/playlist/utils/runPlaylistLoad.test.ts b/src/features/playlist/utils/runPlaylistLoad.test.ts new file mode 100644 index 00000000..dc2182ed --- /dev/null +++ b/src/features/playlist/utils/runPlaylistLoad.test.ts @@ -0,0 +1,64 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { runPlaylistLoad } from '@/features/playlist/utils/runPlaylistLoad'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; + +const getPlaylistMock = vi.fn(); +const filterMock = vi.fn(); + +vi.mock('@/lib/api/subsonicPlaylists', () => ({ + getPlaylist: (id: string) => getPlaylistMock(id), +})); + +vi.mock('@/lib/api/subsonicLibrary', () => ({ + filterSongsToActiveLibrary: (songs: unknown) => filterMock(songs), +})); + +vi.mock('@/features/offline', () => ({ + isOfflineBrowseActive: () => false, + resolvePlaylist: vi.fn(), +})); + +vi.mock('@/features/playlist/store/playlistStore', () => ({ + usePlaylistStore: { getState: () => ({ playlists: [] }) }, +})); + +vi.mock('@/store/authStore', () => ({ + useAuthStore: { getState: () => ({ activeServerId: 'srv-1' }) }, +})); + +function makeDeps(id: string) { + return { + id, + setLoading: vi.fn(), + setPlaylist: vi.fn(), + setSongs: vi.fn(), + setCustomCoverId: vi.fn(), + setRatings: vi.fn(), + setStarredSongs: vi.fn(), + }; +} + +describe('runPlaylistLoad membership seeding', () => { + beforeEach(() => { + getPlaylistMock.mockReset(); + filterMock.mockReset(); + usePlaylistMembershipStore.setState({ songIdsByCacheKey: {} }); + }); + + it('seeds the membership cache from the full list, not the library-scoped view', async () => { + getPlaylistMock.mockResolvedValue({ + playlist: { id: 'pl-1' }, + songs: [{ id: 'a' }, { id: 'b' }, { id: 'c' }], + }); + // Active library scope hides b and c from the displayed list. + filterMock.mockResolvedValue([{ id: 'a' }]); + + const deps = makeDeps('pl-1'); + await runPlaylistLoad(deps); + + // Cache must hold the full server membership so dedup won't re-add b/c. + expect(usePlaylistMembershipStore.getState().getPlaylistSongIds('pl-1')).toEqual(['a', 'b', 'c']); + // The visible list is still the filtered subset. + expect(deps.setSongs).toHaveBeenCalledWith([{ id: 'a' }]); + }); +}); diff --git a/src/features/playlist/utils/runPlaylistLoad.ts b/src/features/playlist/utils/runPlaylistLoad.ts index abf73749..b385c2de 100644 --- a/src/features/playlist/utils/runPlaylistLoad.ts +++ b/src/features/playlist/utils/runPlaylistLoad.ts @@ -4,6 +4,7 @@ import { filterSongsToActiveLibrary } from '@/lib/api/subsonicLibrary'; import type { SubsonicPlaylist, SubsonicSong } from '@/lib/api/subsonicTypes'; import { useAuthStore } from '@/store/authStore'; import { usePlaylistStore } from '@/features/playlist/store/playlistStore'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; import { isOfflineBrowseActive } from '@/features/offline'; import { resolvePlaylist } from '@/features/offline'; @@ -21,6 +22,11 @@ function applyLoadedPlaylist( deps: RunPlaylistLoadDeps, playlist: SubsonicPlaylist, songs: SubsonicSong[], + // The membership cache must hold the *full* server-side track list, not the + // library-scope-filtered view — otherwise dedup would treat out-of-scope + // members as new and re-add them as duplicates. Defaults to the shown songs + // (offline path, where the resolved list already is the full membership). + membershipIds: string[] = songs.map(s => s.id), ): void { const { setPlaylist, setSongs, setCustomCoverId, setRatings, setStarredSongs } = deps; setPlaylist(playlist); @@ -34,6 +40,7 @@ function applyLoadedPlaylist( }); setRatings(init); setStarredSongs(starred); + usePlaylistMembershipStore.getState().setPlaylistSongIds(deps.id, membershipIds); } export async function runPlaylistLoad(deps: RunPlaylistLoadDeps): Promise { @@ -51,7 +58,7 @@ export async function runPlaylistLoad(deps: RunPlaylistLoadDeps): Promise const { playlist, songs } = await getPlaylist(id); const filteredSongs = await filterSongsToActiveLibrary(songs); - applyLoadedPlaylist(deps, playlist, filteredSongs); + applyLoadedPlaylist(deps, playlist, filteredSongs, songs.map(s => s.id)); } catch { const stub = usePlaylistStore.getState().playlists.find(p => p.id === id); if (stub) { diff --git a/src/features/playlist/utils/runPlaylistsActions.ts b/src/features/playlist/utils/runPlaylistsActions.ts index ed8203f4..0a078c0a 100644 --- a/src/features/playlist/utils/runPlaylistsActions.ts +++ b/src/features/playlist/utils/runPlaylistsActions.ts @@ -1,8 +1,10 @@ import type React from 'react'; import type { TFunction } from 'i18next'; -import { deletePlaylist, getPlaylist, updatePlaylist } from '@/lib/api/subsonicPlaylists'; +import { deletePlaylist, addSongsToPlaylist } from '@/lib/api/subsonicPlaylists'; import type { SubsonicPlaylist } from '@/lib/api/subsonicTypes'; import { usePlaylistStore } from '@/features/playlist/store/playlistStore'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; +import { collectMergeSongIds } from '@/features/playlist/utils/addTracksToPlaylistWithDedup'; import { showToast } from '@/lib/dom/toast'; export interface RunPlaylistDeleteDeps { @@ -82,29 +84,22 @@ export async function runPlaylistMergeSelected(deps: RunPlaylistMergeSelectedDep const { targetPlaylist, selectedPlaylists, touchPlaylist, clearSelection, t } = deps; if (selectedPlaylists.length === 0) return; try { - const { songs: targetSongs } = await getPlaylist(targetPlaylist.id); - const targetIds = new Set(targetSongs.map(s => s.id)); - let totalAdded = 0; + const sourceIds = selectedPlaylists + .filter(pl => pl.id !== targetPlaylist.id) + .map(pl => pl.id); + const idsToAdd = await collectMergeSongIds(targetPlaylist.id, sourceIds); - for (const pl of selectedPlaylists) { - if (pl.id === targetPlaylist.id) continue; - const { songs } = await getPlaylist(pl.id); - const newSongs = songs.filter(s => !targetIds.has(s.id)); - if (newSongs.length > 0) { - newSongs.forEach(s => targetIds.add(s.id)); - totalAdded += newSongs.length; - } - } - - if (totalAdded > 0) { - await updatePlaylist(targetPlaylist.id, Array.from(targetIds)); + if (idsToAdd.length > 0) { + await addSongsToPlaylist(targetPlaylist.id, idsToAdd); + usePlaylistMembershipStore.getState().appendPlaylistSongIds(targetPlaylist.id, idsToAdd); touchPlaylist(targetPlaylist.id); - showToast(t('playlists.mergeSuccess', { count: totalAdded, playlist: targetPlaylist.name }), 3000, 'info'); + showToast(t('playlists.mergeSuccess', { count: idsToAdd.length, playlist: targetPlaylist.name }), 3000, 'info'); } else { showToast(t('playlists.mergeNoNewSongs'), 3000, 'info'); } clearSelection(); } catch { + usePlaylistMembershipStore.getState().invalidatePlaylistSongIds(targetPlaylist.id); showToast(t('playlists.mergeError'), 4000, 'error'); } } diff --git a/src/lib/api/subsonicPlaylists.test.ts b/src/lib/api/subsonicPlaylists.test.ts new file mode 100644 index 00000000..eac8ec3e --- /dev/null +++ b/src/lib/api/subsonicPlaylists.test.ts @@ -0,0 +1,103 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { + PLAYLIST_SONG_ID_GET_BATCH, + addSongsToPlaylist, + chunkIndicesForSubsonicGet, + chunkRemovalIndicesForSubsonicGet, + chunkSongIdsForSubsonicGet, + removePlaylistSongsAtIndices, + updatePlaylist, +} from '@/lib/api/subsonicPlaylists'; + +const { apiMock } = vi.hoisted(() => { + const fn = vi.fn(); + return { apiMock: fn }; +}); + +vi.mock('@/lib/api/subsonicClient', () => ({ + api: apiMock, + apiForServer: vi.fn(), +})); + +vi.mock('@/features/offline', () => ({ + schedulePinnedPlaylistSync: vi.fn(), +})); + +describe('subsonicPlaylists batching', () => { + beforeEach(() => { + apiMock.mockReset(); + apiMock.mockImplementation(async (endpoint: string) => { + if (endpoint === 'getPlaylist.view') { + return { + playlist: { + id: 'pl1', + entry: Array.from({ length: 400 }, (_, i) => ({ id: `existing-${i}` })), + }, + }; + } + return {}; + }); + }); + + it('chunks song ids for GET batching', () => { + const ids = Array.from({ length: 320 }, (_, i) => `track-${i}`); + const batches = chunkSongIdsForSubsonicGet(ids, 150); + expect(batches).toHaveLength(3); + expect(batches[0]).toHaveLength(150); + expect(batches[2]).toHaveLength(20); + }); + + it('chunks clear indices from the end', () => { + const batches = chunkIndicesForSubsonicGet(340, 150); + expect(batches).toHaveLength(3); + expect(batches[0][0]).toBe(190); + expect(batches[0][batches[0].length - 1]).toBe(339); + expect(batches[2]).toEqual(Array.from({ length: 40 }, (_, i) => i)); + }); + + it('addSongsToPlaylist uses updatePlaylist.view with songIdToAdd only', async () => { + const ids = Array.from({ length: PLAYLIST_SONG_ID_GET_BATCH + 5 }, (_, i) => `s${i}`); + await addSongsToPlaylist('pl1', ids); + expect(apiMock).toHaveBeenCalledTimes(2); + const calls = apiMock.mock.calls as Array<[string, Record?]>; + expect(calls[0]?.[0]).toBe('updatePlaylist.view'); + expect(calls[0]?.[1]).toEqual({ + playlistId: 'pl1', + songIdToAdd: ids.slice(0, PLAYLIST_SONG_ID_GET_BATCH), + }); + expect(calls[1]?.[1]).toEqual({ + playlistId: 'pl1', + songIdToAdd: ids.slice(PLAYLIST_SONG_ID_GET_BATCH), + }); + }); + + it('chunks removal indices high-to-low', () => { + const indices = Array.from({ length: 200 }, (_, i) => i); + const batches = chunkRemovalIndicesForSubsonicGet(indices, 150); + expect(batches).toHaveLength(2); + expect(batches[0][0]).toBe(199); + expect(batches[0][batches[0].length - 1]).toBe(50); + expect(batches[1][0]).toBe(49); + expect(batches[1][batches[1].length - 1]).toBe(0); + }); + + it('removePlaylistSongsAtIndices removes high indices first', async () => { + const indices = Array.from({ length: 200 }, (_, i) => i); + await removePlaylistSongsAtIndices('pl1', indices); + expect(apiMock).toHaveBeenCalledTimes(2); + const calls = apiMock.mock.calls as Array<[string, Record?]>; + const firstBatch = calls[0]?.[1]?.songIndexToRemove as number[]; + expect(firstBatch[0]).toBe(199); + expect(firstBatch[firstBatch.length - 1]).toBe(50); + }); + + it('updatePlaylist clears then appends when replacing a large list', async () => { + const ids = Array.from({ length: 200 }, (_, i) => `s${i}`); + await updatePlaylist('pl1', ids, 400); + const calls = apiMock.mock.calls as Array<[string, Record?]>; + const endpoints = calls.map(call => call[0]); + expect(endpoints.filter(e => e === 'updatePlaylist.view').length).toBeGreaterThan(0); + expect(endpoints.filter(e => e === 'createPlaylist.view')).toHaveLength(0); + expect(calls.some(call => call[1]?.songIdToAdd)).toBe(true); + }); +}); diff --git a/src/lib/api/subsonicPlaylists.ts b/src/lib/api/subsonicPlaylists.ts index 97fef9d9..5c9dbc09 100644 --- a/src/lib/api/subsonicPlaylists.ts +++ b/src/lib/api/subsonicPlaylists.ts @@ -4,6 +4,57 @@ import { shouldAttemptSubsonicForServer } from '@/lib/network/subsonicNetworkGua import { api, apiForServer } from '@/lib/api/subsonicClient'; import type { SubsonicPlaylist, SubsonicSong } from '@/lib/api/subsonicTypes'; +/** Max song-id params per Subsonic GET call (auth + ~8 KiB URL ceiling). */ +export const PLAYLIST_SONG_ID_GET_BATCH = 150; + +export function chunkIndicesForSubsonicGet(count: number, batchSize = PLAYLIST_SONG_ID_GET_BATCH): number[][] { + if (count <= 0) return []; + const batches: number[][] = []; + let remaining = count; + while (remaining > 0) { + const size = Math.min(batchSize, remaining); + const start = remaining - size; + batches.push(Array.from({ length: size }, (_, i) => start + i)); + remaining -= size; + } + return batches; +} + +export function chunkSongIdsForSubsonicGet(ids: string[], batchSize = PLAYLIST_SONG_ID_GET_BATCH): string[][] { + if (ids.length === 0) return []; + const batches: string[][] = []; + for (let i = 0; i < ids.length; i += batchSize) { + batches.push(ids.slice(i, i + batchSize)); + } + return batches; +} + +/** Batch arbitrary removal indices high-to-low so earlier positions stay valid between calls. */ +export function chunkRemovalIndicesForSubsonicGet( + indices: number[], + batchSize = PLAYLIST_SONG_ID_GET_BATCH, +): number[][] { + if (indices.length === 0) return []; + const sorted = [...indices].sort((a, b) => b - a); + const batches: number[][] = []; + for (let i = 0; i < sorted.length; i += batchSize) { + batches.push(sorted.slice(i, i + batchSize)); + } + return batches; +} + +function schedulePinnedPlaylistSync(playlistId: string): void { + void import('@/features/offline') + .then(m => m.schedulePinnedPlaylistSync(playlistId)) + .catch(() => {}); +} + +async function clearPlaylistSongs(id: string, prevCount: number): Promise { + for (const indices of chunkIndicesForSubsonicGet(prevCount)) { + await api('updatePlaylist.view', { playlistId: id, songIndexToRemove: indices }); + } +} + export async function getPlaylists(includeOrbit = false): Promise { const data = await api<{ playlists: { playlist: SubsonicPlaylist[] } }>('getPlaylists.view', { _t: Date.now() }); const all = data.playlists?.playlist ?? []; @@ -45,21 +96,49 @@ export async function createPlaylist(name: string, songIds?: string[]): Promise< return data.playlist; } +/** Append tracks without re-sending the full playlist (avoids GET URL length limits). */ +export async function addSongsToPlaylist(id: string, songIdsToAdd: string[]): Promise { + if (songIdsToAdd.length === 0) return; + for (const batch of chunkSongIdsForSubsonicGet(songIdsToAdd)) { + await api('updatePlaylist.view', { playlistId: id, songIdToAdd: batch }); + } + schedulePinnedPlaylistSync(id); +} + +/** Remove tracks by 0-based playlist indices (batched for large playlists). */ +export async function removePlaylistSongsAtIndices(id: string, indices: number[]): Promise { + if (indices.length === 0) return; + for (const batch of chunkRemovalIndicesForSubsonicGet(indices)) { + await api('updatePlaylist.view', { playlistId: id, songIndexToRemove: batch }); + } + schedulePinnedPlaylistSync(id); +} + export async function updatePlaylist(id: string, songIds: string[], prevCount = 0): Promise { if (songIds.length > 0) { - // createPlaylist with playlistId replaces the existing playlist's songs (Subsonic API 1.14+) - await api('createPlaylist.view', { playlistId: id, songId: songIds }); + if (songIds.length <= PLAYLIST_SONG_ID_GET_BATCH) { + // createPlaylist with playlistId replaces the existing playlist's songs (Subsonic API 1.14+) + await api('createPlaylist.view', { playlistId: id, songId: songIds }); + } else { + // Lists over the GET batch cap can't replace atomically (URL length limit), + // so we clear then re-append. A failure between the two steps leaves the + // server playlist truncated; the caller invalidates the membership cache so + // the client re-reads truth on next load. This is the unavoidable trade-off + // for supporting playlists larger than one request can carry. + let priorCount = prevCount; + if (priorCount <= 0) { + const { songs } = await getPlaylist(id); + priorCount = songs.length; + } + if (priorCount > 0) { + await clearPlaylistSongs(id, priorCount); + } + await addSongsToPlaylist(id, songIds); + } } else if (prevCount > 0) { - // Axios serialises empty arrays as no params — createPlaylist.view would leave songs unchanged. - // Use updatePlaylist.view with explicit index removal to clear the list instead. - await api('updatePlaylist.view', { - playlistId: id, - songIndexToRemove: Array.from({ length: prevCount }, (_, i) => i), - }); + await clearPlaylistSongs(id, prevCount); } - void import('@/features/offline') - .then(m => m.schedulePinnedPlaylistSync(id)) - .catch(() => {}); + schedulePinnedPlaylistSync(id); } export async function updatePlaylistMeta( diff --git a/src/store/playlistMembershipStore.test.ts b/src/store/playlistMembershipStore.test.ts new file mode 100644 index 00000000..d42ac15e --- /dev/null +++ b/src/store/playlistMembershipStore.test.ts @@ -0,0 +1,38 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { usePlaylistMembershipStore } from '@/store/playlistMembershipStore'; + +vi.mock('@/store/authStore', () => ({ + useAuthStore: { + getState: () => ({ activeServerId: 'srv-1' }), + }, +})); + +describe('playlistMembershipStore', () => { + beforeEach(() => { + usePlaylistMembershipStore.setState({ songIdsByCacheKey: {} }); + }); + + it('stores and reads ids scoped to active server', () => { + usePlaylistMembershipStore.getState().setPlaylistSongIds('pl-1', ['a', 'b']); + expect(usePlaylistMembershipStore.getState().getPlaylistSongIds('pl-1')).toEqual(['a', 'b']); + }); + + it('appends and removes by index', () => { + const store = usePlaylistMembershipStore.getState(); + store.setPlaylistSongIds('pl-1', ['a', 'b', 'c']); + store.appendPlaylistSongIds('pl-1', ['d']); + store.removePlaylistSongIdsAtIndices('pl-1', [1]); + expect(usePlaylistMembershipStore.getState().getPlaylistSongIds('pl-1')).toEqual(['a', 'c', 'd']); + }); + + it('invalidate drops a single playlist; clearAll drops everything', () => { + const store = usePlaylistMembershipStore.getState(); + store.setPlaylistSongIds('pl-1', ['a']); + store.setPlaylistSongIds('pl-2', ['b']); + store.invalidatePlaylistSongIds('pl-1'); + expect(usePlaylistMembershipStore.getState().getPlaylistSongIds('pl-1')).toBeUndefined(); + expect(usePlaylistMembershipStore.getState().getPlaylistSongIds('pl-2')).toEqual(['b']); + store.clearAllPlaylistSongIds(); + expect(usePlaylistMembershipStore.getState().getPlaylistSongIds('pl-2')).toBeUndefined(); + }); +}); diff --git a/src/store/playlistMembershipStore.ts b/src/store/playlistMembershipStore.ts new file mode 100644 index 00000000..84e8c24b --- /dev/null +++ b/src/store/playlistMembershipStore.ts @@ -0,0 +1,69 @@ +import { create } from 'zustand'; +import { useAuthStore } from '@/store/authStore'; + +/** + * In-memory playlist song-id membership cache, keyed by `serverId:playlistId`. + * + * Lives in the core store layer (not the playlist feature) so `offline`, `orbit`, + * `contextMenu` and `playlist` can all read/write it directly without a cross-feature + * barrel dependency — the membership cache is the one piece those features genuinely + * share, and routing it through `@/features/playlist` created import cycles. + * + * Not persisted: playlist membership must reflect the live server, so it is rebuilt + * from `getPlaylist`/`runPlaylistLoad` on demand and dropped on `fetchPlaylists`. + */ +interface PlaylistMembershipStore { + /** Song-id lists keyed by `serverId:playlistId`. */ + songIdsByCacheKey: Record; + getPlaylistSongIds: (playlistId: string) => readonly string[] | undefined; + setPlaylistSongIds: (playlistId: string, songIds: readonly string[]) => void; + appendPlaylistSongIds: (playlistId: string, songIds: readonly string[]) => void; + replacePlaylistSongIds: (playlistId: string, songIds: readonly string[]) => void; + removePlaylistSongIdsAtIndices: (playlistId: string, indices: readonly number[]) => void; + invalidatePlaylistSongIds: (playlistId: string) => void; + clearAllPlaylistSongIds: () => void; +} + +/** Scope membership to the active server — playlist ids are not globally unique. */ +function cacheKey(playlistId: string): string { + const serverId = useAuthStore.getState().activeServerId ?? ''; + return `${serverId}:${playlistId}`; +} + +export const usePlaylistMembershipStore = create()((set, get) => ({ + songIdsByCacheKey: {}, + getPlaylistSongIds: (playlistId) => get().songIdsByCacheKey[cacheKey(playlistId)], + setPlaylistSongIds: (playlistId, songIds) => + set((s) => ({ + songIdsByCacheKey: { ...s.songIdsByCacheKey, [cacheKey(playlistId)]: [...songIds] }, + })), + appendPlaylistSongIds: (playlistId, songIds) => { + if (songIds.length === 0) return; + set((s) => { + const key = cacheKey(playlistId); + const prev = s.songIdsByCacheKey[key] ?? []; + return { songIdsByCacheKey: { ...s.songIdsByCacheKey, [key]: [...prev, ...songIds] } }; + }); + }, + replacePlaylistSongIds: (playlistId, songIds) => get().setPlaylistSongIds(playlistId, songIds), + removePlaylistSongIdsAtIndices: (playlistId, indices) => { + if (indices.length === 0) return; + set((s) => { + const key = cacheKey(playlistId); + const prev = s.songIdsByCacheKey[key]; + if (!prev) return s; + const remove = new Set(indices); + return { + songIdsByCacheKey: { ...s.songIdsByCacheKey, [key]: prev.filter((_, i) => !remove.has(i)) }, + }; + }); + }, + invalidatePlaylistSongIds: (playlistId) => + set((s) => { + const key = cacheKey(playlistId); + if (!(key in s.songIdsByCacheKey)) return s; + const { [key]: _removed, ...rest } = s.songIdsByCacheKey; + return { songIdsByCacheKey: rest }; + }), + clearAllPlaylistSongIds: () => set({ songIdsByCacheKey: {} }), +}));