mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
refactor(hooks): move cross-cutting hooks into lib/hooks
The five residual src/hooks/ hooks (useConnectionStatus, useCardGridMetrics, useTracklistColumns, useNavidromeAdminRole, useAnalysisPerfListener) are all domain-agnostic — none imports @/features — so they join the other shared hooks in src/lib/hooks/ (with their two colocated tests). Consumers repointed; relative-up imports in the moved files become the @/ alias. src/hooks/ is removed. Pure move + import updates, no behavior change. The layering baseline gains five lib->store entries (the three hooks that read authStore/devOfflineBrowseStore are only now caught under lib/) — same documented debt class as the api move.
This commit is contained in:
@@ -533,6 +533,91 @@
|
|||||||
"name": "lib-is-the-floor"
|
"name": "lib-is-the-floor"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "dependency",
|
||||||
|
"from": "src/lib/hooks/useCardGridMetrics.ts",
|
||||||
|
"to": "src/store/authStore.ts",
|
||||||
|
"unresolvedTo": "@/store/authStore",
|
||||||
|
"dependencyTypes": [
|
||||||
|
"aliased",
|
||||||
|
"aliased-tsconfig",
|
||||||
|
"aliased-tsconfig-paths",
|
||||||
|
"local",
|
||||||
|
"import"
|
||||||
|
],
|
||||||
|
"rule": {
|
||||||
|
"severity": "error",
|
||||||
|
"name": "lib-is-the-floor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dependency",
|
||||||
|
"from": "src/lib/hooks/useCardGridMetrics.ts",
|
||||||
|
"to": "src/store/authStoreHelpers.ts",
|
||||||
|
"unresolvedTo": "@/store/authStoreHelpers",
|
||||||
|
"dependencyTypes": [
|
||||||
|
"aliased",
|
||||||
|
"aliased-tsconfig",
|
||||||
|
"aliased-tsconfig-paths",
|
||||||
|
"local",
|
||||||
|
"import"
|
||||||
|
],
|
||||||
|
"rule": {
|
||||||
|
"severity": "error",
|
||||||
|
"name": "lib-is-the-floor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dependency",
|
||||||
|
"from": "src/lib/hooks/useConnectionStatus.ts",
|
||||||
|
"to": "src/store/authStore.ts",
|
||||||
|
"unresolvedTo": "@/store/authStore",
|
||||||
|
"dependencyTypes": [
|
||||||
|
"aliased",
|
||||||
|
"aliased-tsconfig",
|
||||||
|
"aliased-tsconfig-paths",
|
||||||
|
"local",
|
||||||
|
"import"
|
||||||
|
],
|
||||||
|
"rule": {
|
||||||
|
"severity": "error",
|
||||||
|
"name": "lib-is-the-floor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dependency",
|
||||||
|
"from": "src/lib/hooks/useConnectionStatus.ts",
|
||||||
|
"to": "src/store/devOfflineBrowseStore.ts",
|
||||||
|
"unresolvedTo": "@/store/devOfflineBrowseStore",
|
||||||
|
"dependencyTypes": [
|
||||||
|
"aliased",
|
||||||
|
"aliased-tsconfig",
|
||||||
|
"aliased-tsconfig-paths",
|
||||||
|
"local",
|
||||||
|
"import"
|
||||||
|
],
|
||||||
|
"rule": {
|
||||||
|
"severity": "error",
|
||||||
|
"name": "lib-is-the-floor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dependency",
|
||||||
|
"from": "src/lib/hooks/useNavidromeAdminRole.ts",
|
||||||
|
"to": "src/store/authStore.ts",
|
||||||
|
"unresolvedTo": "@/store/authStore",
|
||||||
|
"dependencyTypes": [
|
||||||
|
"aliased",
|
||||||
|
"aliased-tsconfig",
|
||||||
|
"aliased-tsconfig-paths",
|
||||||
|
"local",
|
||||||
|
"import"
|
||||||
|
],
|
||||||
|
"rule": {
|
||||||
|
"severity": "error",
|
||||||
|
"name": "lib-is-the-floor"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "dependency",
|
"type": "dependency",
|
||||||
"from": "src/lib/library/hooks/useLibraryAnalysisBackfill.ts",
|
"from": "src/lib/library/hooks/useLibraryAnalysisBackfill.ts",
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ import { useOfflineAutoNav } from '@/features/offline';
|
|||||||
import { useOfflineLibraryFilterSuspend } from '@/features/offline';
|
import { useOfflineLibraryFilterSuspend } from '@/features/offline';
|
||||||
import { AppShellQueueResizerSeam } from '@/app/AppShellQueueResizerSeam';
|
import { AppShellQueueResizerSeam } from '@/app/AppShellQueueResizerSeam';
|
||||||
import { IS_LINUX, IS_MACOS } from '@/lib/util/platform';
|
import { IS_LINUX, IS_MACOS } from '@/lib/util/platform';
|
||||||
import { useConnectionStatus } from '../hooks/useConnectionStatus';
|
import { useConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import { useIdlePlayQueuePull } from '@/app/hooks/useIdlePlayQueuePull';
|
import { useIdlePlayQueuePull } from '@/app/hooks/useIdlePlayQueuePull';
|
||||||
import { useAuthStore } from '../store/authStore';
|
import { useAuthStore } from '../store/authStore';
|
||||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { createPortal } from 'react-dom';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Check, ChevronDown, RefreshCw } from 'lucide-react';
|
import { Check, ChevronDown, RefreshCw } from 'lucide-react';
|
||||||
import type { ConnectionStatus } from '@/hooks/useConnectionStatus';
|
import type { ConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import { usePlayQueueSyncLedState } from '@/app/hooks/usePlayQueueSyncLedState';
|
import { usePlayQueueSyncLedState } from '@/app/hooks/usePlayQueueSyncLedState';
|
||||||
import type { ServerProfile } from '@/store/authStoreTypes';
|
import type { ServerProfile } from '@/store/authStoreTypes';
|
||||||
import { useAuthStore } from '@/store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import {
|
|||||||
resolveOverlayVisibility,
|
resolveOverlayVisibility,
|
||||||
usePerfOverlayMode,
|
usePerfOverlayMode,
|
||||||
} from '@/lib/perf/perfOverlayMode';
|
} from '@/lib/perf/perfOverlayMode';
|
||||||
import { useAnalysisPerfListener } from '@/hooks/useAnalysisPerfListener';
|
import { useAnalysisPerfListener } from '@/lib/hooks/useAnalysisPerfListener';
|
||||||
import { useCoverPerfListener } from '@/cover/useCoverPerfListener';
|
import { useCoverPerfListener } from '@/cover/useCoverPerfListener';
|
||||||
import { getCoverCachedPerMinute, getCoverUiPerMinute } from '@/lib/perf/coverPerfStore';
|
import { getCoverCachedPerMinute, getCoverUiPerMinute } from '@/lib/perf/coverPerfStore';
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
markPlaybackIdle,
|
markPlaybackIdle,
|
||||||
} from '@/features/playback/store/queuePlaybackIdle';
|
} from '@/features/playback/store/queuePlaybackIdle';
|
||||||
import { hasPendingQueueSync } from '@/features/playback/store/queueSync';
|
import { hasPendingQueueSync } from '@/features/playback/store/queueSync';
|
||||||
import type { ConnectionStatus } from '@/hooks/useConnectionStatus';
|
import type { ConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import { canAutoIdlePlayQueuePull } from '@/app/hooks/usePlayQueueSyncLedState';
|
import { canAutoIdlePlayQueuePull } from '@/app/hooks/usePlayQueueSyncLedState';
|
||||||
|
|
||||||
const IDLE_THRESHOLD_MS = 30_000;
|
const IDLE_THRESHOLD_MS = 30_000;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react';
|
import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { ConnectionStatus } from '@/hooks/useConnectionStatus';
|
import type { ConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import { pullPlayQueueFromActiveServer } from '@/features/playback/store/applyServerPlayQueue';
|
import { pullPlayQueueFromActiveServer } from '@/features/playback/store/applyServerPlayQueue';
|
||||||
import { useAuthStore } from '@/store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import { useOrbitStore } from '@/features/orbit';
|
import { useOrbitStore } from '@/features/orbit';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||||
import type { Track } from '@/lib/media/trackTypes';
|
import type { Track } from '@/lib/media/trackTypes';
|
||||||
import React, { useMemo, useState, useEffect } from 'react';
|
import React, { useMemo, useState, useEffect } from 'react';
|
||||||
import { useTracklistColumns } from '@/hooks/useTracklistColumns';
|
import { useTracklistColumns } from '@/lib/hooks/useTracklistColumns';
|
||||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useIsMobile } from '@/lib/hooks/useIsMobile';
|
import { useIsMobile } from '@/lib/hooks/useIsMobile';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import { AudioLines, ChevronRight, Heart, Play, Square } from 'lucide-react';
|
import { AudioLines, ChevronRight, Heart, Play, Square } from 'lucide-react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import type { ColDef } from '@/hooks/useTracklistColumns';
|
import type { ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||||
import type { Track } from '@/lib/media/trackTypes';
|
import type { Track } from '@/lib/media/trackTypes';
|
||||||
import { songToTrack } from '@/lib/media/songToTrack';
|
import { songToTrack } from '@/lib/media/songToTrack';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import type { ColDef } from '@/hooks/useTracklistColumns';
|
import type { ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
import { CENTERED_COLS, isSortable, type ColKey, type SortKey } from '@/features/album/utils/albumTrackListHelpers';
|
import { CENTERED_COLS, isSortable, type ColKey, type SortKey } from '@/features/album/utils/albumTrackListHelpers';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ColDef } from '@/hooks/useTracklistColumns';
|
import type { ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
|
|
||||||
export function codecLabel(song: { suffix?: string; bitRate?: number }, showBitrate: boolean): string {
|
export function codecLabel(song: { suffix?: string; bitRate?: number }, showBitrate: boolean): string {
|
||||||
const parts: string[] = [];
|
const parts: string[] = [];
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type {
|
|||||||
SubsonicAlbum, SubsonicArtist, SubsonicArtistInfo, SubsonicSong,
|
SubsonicAlbum, SubsonicArtist, SubsonicArtistInfo, SubsonicSong,
|
||||||
} from '@/lib/api/subsonicTypes';
|
} from '@/lib/api/subsonicTypes';
|
||||||
import { useAuthStore } from '@/store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import { useConnectionStatus } from '@/hooks/useConnectionStatus';
|
import { useConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import { loadArtistFromLibraryIndex } from '@/features/offline';
|
import { loadArtistFromLibraryIndex } from '@/features/offline';
|
||||||
import { useOfflineBrowseContext } from '@/features/offline';
|
import { useOfflineBrowseContext } from '@/features/offline';
|
||||||
import { loadArtistFromLocalPlayback, offlineLocalBrowseEnabled } from '@/features/offline';
|
import { loadArtistFromLocalPlayback, offlineLocalBrowseEnabled } from '@/features/offline';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { AudioLines, ChevronRight, Play, Square, X } from 'lucide-react';
|
import { AudioLines, ChevronRight, Play, Square, X } from 'lucide-react';
|
||||||
import type { ColDef } from '@/hooks/useTracklistColumns';
|
import type { ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||||
import { codecLabel } from '@/lib/format/playlistDetailHelpers';
|
import { codecLabel } from '@/lib/format/playlistDetailHelpers';
|
||||||
import { formatLastSeen } from '@/lib/format/userMgmtHelpers';
|
import { formatLastSeen } from '@/lib/format/userMgmtHelpers';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import FavoriteSongRow, { type FavoriteSongRowCallbacks } from '@/features/favor
|
|||||||
import { TracklistColumnPicker } from '@/ui/TracklistColumnPicker';
|
import { TracklistColumnPicker } from '@/ui/TracklistColumnPicker';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import type { ColDef } from '@/hooks/useTracklistColumns';
|
import type { ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||||
import { previewInputFromSong, usePreviewStore } from '@/features/playback/store/previewStore';
|
import { previewInputFromSong, usePreviewStore } from '@/features/playback/store/previewStore';
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type {
|
|||||||
import { useAuthStore } from '@/store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||||
import type { TopFavoriteArtist } from '@/features/favorites/components/TopFavoriteArtists';
|
import type { TopFavoriteArtist } from '@/features/favorites/components/TopFavoriteArtists';
|
||||||
import { useConnectionStatus } from '@/hooks/useConnectionStatus';
|
import { useConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import { isActiveServerReachable } from '@/lib/network/activeServerReachability';
|
import { isActiveServerReachable } from '@/lib/network/activeServerReachability';
|
||||||
import { useOfflineBrowseContext } from '@/features/offline';
|
import { useOfflineBrowseContext } from '@/features/offline';
|
||||||
import { useOfflineBrowseReloadToken } from '@/features/offline';
|
import { useOfflineBrowseReloadToken } from '@/features/offline';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { queueSongStar, queueSongRating } from '@/features/playback/store/pendingStarSync';
|
import { queueSongStar, queueSongRating } from '@/features/playback/store/pendingStarSync';
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { useTracklistColumns, type ColDef } from '@/hooks/useTracklistColumns';
|
import { useTracklistColumns, type ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
import { TopFavoriteArtistsRow } from '@/features/favorites/components/TopFavoriteArtists';
|
import { TopFavoriteArtistsRow } from '@/features/favorites/components/TopFavoriteArtists';
|
||||||
import { RadioStationRow } from '@/features/favorites/components/RadioFavorites';
|
import { RadioStationRow } from '@/features/favorites/components/RadioFavorites';
|
||||||
import FavoritesSongsSectionHeader from '@/features/favorites/components/FavoritesSongsSectionHeader';
|
import FavoritesSongsSectionHeader from '@/features/favorites/components/FavoritesSongsSectionHeader';
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
writeHomeFeedCache,
|
writeHomeFeedCache,
|
||||||
type HomeFeedSnapshot,
|
type HomeFeedSnapshot,
|
||||||
} from '@/features/home/store/homeFeedCache';
|
} from '@/features/home/store/homeFeedCache';
|
||||||
import { useConnectionStatus } from '@/hooks/useConnectionStatus';
|
import { useConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import { useOfflineBrowseContext } from '@/features/offline';
|
import { useOfflineBrowseContext } from '@/features/offline';
|
||||||
import { useOfflineBrowseReloadToken } from '@/features/offline';
|
import { useOfflineBrowseReloadToken } from '@/features/offline';
|
||||||
import { useDevOfflineBrowseStore } from '@/features/offline';
|
import { useDevOfflineBrowseStore } from '@/features/offline';
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type { ArtistStats, TrackStats } from '@/music-network';
|
|||||||
import { getMusicNetworkRuntimeOrNull } from '@/music-network';
|
import { getMusicNetworkRuntimeOrNull } from '@/music-network';
|
||||||
import { makeCache } from '@/lib/cache/nowPlayingCache';
|
import { makeCache } from '@/lib/cache/nowPlayingCache';
|
||||||
import { shouldAttemptSubsonicForServer } from '@/lib/network/subsonicNetworkGuard';
|
import { shouldAttemptSubsonicForServer } from '@/lib/network/subsonicNetworkGuard';
|
||||||
import { useConnectionStatus } from '@/hooks/useConnectionStatus';
|
import { useConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
|
|
||||||
// Module-level TTL caches (shared across mounts)
|
// Module-level TTL caches (shared across mounts)
|
||||||
const songMetaCache = makeCache<SubsonicSong | null>();
|
const songMetaCache = makeCache<SubsonicSong | null>();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useAuthStore } from '@/store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import { useOfflineStore } from '@/features/offline/store/offlineStore';
|
import { useOfflineStore } from '@/features/offline/store/offlineStore';
|
||||||
import { useConnectionStatus } from '@/hooks/useConnectionStatus';
|
import { useConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import { usePlayerStatsRecordingEnabled } from '@/features/stats';
|
import { usePlayerStatsRecordingEnabled } from '@/features/stats';
|
||||||
import { hasOfflineBrowsingContent } from '@/features/offline/utils/favoritesOfflineBrowse';
|
import { hasOfflineBrowsingContent } from '@/features/offline/utils/favoritesOfflineBrowse';
|
||||||
import { useOfflineBrowseActive } from '@/features/offline/utils/offlineBrowseMode';
|
import { useOfflineBrowseActive } from '@/features/offline/utils/offlineBrowseMode';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ConnectionStatus } from '@/hooks/useConnectionStatus';
|
import type { ConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import type { OfflineAlbumMeta } from '@/features/offline/store/offlineStore';
|
import type { OfflineAlbumMeta } from '@/features/offline/store/offlineStore';
|
||||||
import { favoritesOfflineBrowseEnabled } from '@/features/offline/utils/favoritesOfflineBrowse';
|
import { favoritesOfflineBrowseEnabled } from '@/features/offline/utils/favoritesOfflineBrowse';
|
||||||
import { hasOfflineBrowseCapability } from '@/features/offline/utils/offlineBrowseRouting';
|
import { hasOfflineBrowseCapability } from '@/features/offline/utils/offlineBrowseRouting';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
isDevOfflineBrowseForced,
|
isDevOfflineBrowseForced,
|
||||||
useDevOfflineBrowseStore,
|
useDevOfflineBrowseStore,
|
||||||
} from '@/store/devOfflineBrowseStore';
|
} from '@/store/devOfflineBrowseStore';
|
||||||
import { useConnectionStatus } from '@/hooks/useConnectionStatus';
|
import { useConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import { isActiveServerReachable } from '@/lib/network/activeServerReachability';
|
import { isActiveServerReachable } from '@/lib/network/activeServerReachability';
|
||||||
|
|
||||||
/** True when browse/detail pages should use local-bytes-only data sources. */
|
/** True when browse/detail pages should use local-bytes-only data sources. */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { AudioLines, ChevronRight, Heart, Play, Square, Trash2 } from 'lucide-react';
|
import { AudioLines, ChevronRight, Heart, Play, Square, Trash2 } from 'lucide-react';
|
||||||
import type { ColDef } from '@/hooks/useTracklistColumns';
|
import type { ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||||
import { codecLabel } from '@/lib/format/playlistDetailHelpers';
|
import { codecLabel } from '@/lib/format/playlistDetailHelpers';
|
||||||
import { formatLastSeen } from '@/lib/format/userMgmtHelpers';
|
import { formatLastSeen } from '@/lib/format/userMgmtHelpers';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { ChevronRight, Heart, Play, Plus, RefreshCw, Square } from 'lucide-react';
|
import { ChevronRight, Heart, Play, Plus, RefreshCw, Square } from 'lucide-react';
|
||||||
import type { ColDef } from '@/hooks/useTracklistColumns';
|
import type { ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||||
import { usePreviewStore } from '@/features/playback/store/previewStore';
|
import { usePreviewStore } from '@/features/playback/store/previewStore';
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
import {
|
import {
|
||||||
ListPlus, Search, Trash2, X,
|
ListPlus, Search, Trash2, X,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import type { ColDef } from '@/hooks/useTracklistColumns';
|
import type { ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||||
import type { Track } from '@/lib/media/trackTypes';
|
import type { Track } from '@/lib/media/trackTypes';
|
||||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { updatePlaylist } from '@/lib/api/subsonicPlaylists';
|
|||||||
import type { SubsonicPlaylist, SubsonicSong } from '@/lib/api/subsonicTypes';
|
import type { SubsonicPlaylist, SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||||
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
||||||
import { useParams, useNavigate, useLocation } from 'react-router-dom';
|
import { useParams, useNavigate, useLocation } from 'react-router-dom';
|
||||||
import { useTracklistColumns, type ColDef } from '@/hooks/useTracklistColumns';
|
import { useTracklistColumns, type ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||||
import { useShallow } from 'zustand/react/shallow';
|
import { useShallow } from 'zustand/react/shallow';
|
||||||
import { usePlaylistStore } from '@/features/playlist/store/playlistStore';
|
import { usePlaylistStore } from '@/features/playlist/store/playlistStore';
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import RadioEditModal from '@/features/radio/components/RadioEditModal';
|
|||||||
import RadioDirectoryModal from '@/features/radio/components/RadioDirectoryModal';
|
import RadioDirectoryModal from '@/features/radio/components/RadioDirectoryModal';
|
||||||
import { usePerfProbeFlags } from '@/lib/perf/perfFlags';
|
import { usePerfProbeFlags } from '@/lib/perf/perfFlags';
|
||||||
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
|
import { VirtualCardGrid } from '@/ui/VirtualCardGrid';
|
||||||
import { useNavidromeAdminRole, canManageNavidromeRadio } from '@/hooks/useNavidromeAdminRole';
|
import { useNavidromeAdminRole, canManageNavidromeRadio } from '@/lib/hooks/useNavidromeAdminRole';
|
||||||
|
|
||||||
export default function InternetRadio() {
|
export default function InternetRadio() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useAuthStore } from '@/store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
||||||
import { useConnectionStatus } from '@/hooks/useConnectionStatus';
|
import { useConnectionStatus } from '@/lib/hooks/useConnectionStatus';
|
||||||
import { useNavidromeAdminRole } from '@/hooks/useNavidromeAdminRole';
|
import { useNavidromeAdminRole } from '@/lib/hooks/useNavidromeAdminRole';
|
||||||
import { serverListDisplayLabel } from '@/lib/server/serverDisplayName';
|
import { serverListDisplayLabel } from '@/lib/server/serverDisplayName';
|
||||||
import { findServerByIdOrIndexKey } from '@/lib/server/serverLookup';
|
import { findServerByIdOrIndexKey } from '@/lib/server/serverLookup';
|
||||||
import { PerfProbeMetricSection } from '@/features/sidebar/components/perfProbe/PerfProbeMetricCard';
|
import { PerfProbeMetricSection } from '@/features/sidebar/components/perfProbe/PerfProbeMetricCard';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useAuthStore } from '@/store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import type { NavidromeAdminRole } from '@/hooks/useNavidromeAdminRole';
|
import type { NavidromeAdminRole } from '@/lib/hooks/useNavidromeAdminRole';
|
||||||
import { isNavidromeServer, formatServerSoftware } from '@/lib/server/subsonicServerIdentity';
|
import { isNavidromeServer, formatServerSoftware } from '@/lib/server/subsonicServerIdentity';
|
||||||
import { FEATURE_AUDIOMUSE_SIMILAR_TRACKS, OP_SIMILAR_TRACKS } from '@/serverCapabilities/catalog';
|
import { FEATURE_AUDIOMUSE_SIMILAR_TRACKS, OP_SIMILAR_TRACKS } from '@/serverCapabilities/catalog';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
|
|||||||
import { acquirePerfLivePoll, patchPerfLiveAnalysis } from '@/lib/perf/perfLiveStore';
|
import { acquirePerfLivePoll, patchPerfLiveAnalysis } from '@/lib/perf/perfLiveStore';
|
||||||
import { setPerfProbeTelemetryActive } from '@/lib/perf/perfTelemetry';
|
import { setPerfProbeTelemetryActive } from '@/lib/perf/perfTelemetry';
|
||||||
import { useAnalysisPerfLast } from '@/lib/perf/analysisPerfStore';
|
import { useAnalysisPerfLast } from '@/lib/perf/analysisPerfStore';
|
||||||
import { useAnalysisPerfListener } from '@/hooks/useAnalysisPerfListener';
|
import { useAnalysisPerfListener } from '@/lib/hooks/useAnalysisPerfListener';
|
||||||
import { useCoverPerfListener, useCoverUiThroughputPoll } from '@/cover/useCoverPerfListener';
|
import { useCoverPerfListener, useCoverUiThroughputPoll } from '@/cover/useCoverPerfListener';
|
||||||
import {
|
import {
|
||||||
getPerfProbeFlags,
|
getPerfProbeFlags,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useLayoutEffect, useState, type RefObject } from 'react';
|
import { useLayoutEffect, useState, type RefObject } from 'react';
|
||||||
import { useAuthStore } from '../store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import { clampLibraryGridMaxColumns } from '../store/authStoreHelpers';
|
import { clampLibraryGridMaxColumns } from '@/store/authStoreHelpers';
|
||||||
import {
|
import {
|
||||||
type CardGridRowHeightVariant,
|
type CardGridRowHeightVariant,
|
||||||
computeCardGridColumnCount,
|
computeCardGridColumnCount,
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useState, useEffect, useCallback, useRef, useMemo, useSyncExternalStore } from 'react';
|
import { useState, useEffect, useCallback, useRef, useMemo, useSyncExternalStore } from 'react';
|
||||||
import { useAuthStore } from '../store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import { scheduleInstantMixProbeForServer } from '@/lib/api/subsonic';
|
import { scheduleInstantMixProbeForServer } from '@/lib/api/subsonic';
|
||||||
import { serverListDisplayLabel } from '@/lib/server/serverDisplayName';
|
import { serverListDisplayLabel } from '@/lib/server/serverDisplayName';
|
||||||
import {
|
import {
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { ndLogin } from '@/lib/api/navidromeAdmin';
|
import { ndLogin } from '@/lib/api/navidromeAdmin';
|
||||||
import { useAuthStore } from '../store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import { isNavidromeServer } from '@/lib/server/subsonicServerIdentity';
|
import { isNavidromeServer } from '@/lib/server/subsonicServerIdentity';
|
||||||
|
|
||||||
export type NavidromeAdminRole = 'idle' | 'checking' | 'admin' | 'user' | 'na' | 'error';
|
export type NavidromeAdminRole = 'idle' | 'checking' | 'admin' | 'user' | 'na' | 'error';
|
||||||
@@ -5,7 +5,7 @@ import userEvent from '@testing-library/user-event';
|
|||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import { renderWithProviders } from '@/test/helpers/renderWithProviders';
|
import { renderWithProviders } from '@/test/helpers/renderWithProviders';
|
||||||
import { TracklistColumnPicker } from '@/ui/TracklistColumnPicker';
|
import { TracklistColumnPicker } from '@/ui/TracklistColumnPicker';
|
||||||
import type { ColDef } from '@/hooks/useTracklistColumns';
|
import type { ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
|
|
||||||
const COLUMNS: readonly ColDef[] = [
|
const COLUMNS: readonly ColDef[] = [
|
||||||
{ key: 'title', i18nKey: 'title', minWidth: 100, defaultWidth: 200, required: true },
|
{ key: 'title', i18nKey: 'title', minWidth: 100, defaultWidth: 200, required: true },
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { Check, ChevronDown, RotateCcw } from 'lucide-react';
|
import { Check, ChevronDown, RotateCcw } from 'lucide-react';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import type { ColDef } from '@/hooks/useTracklistColumns';
|
import type { ColDef } from '@/lib/hooks/useTracklistColumns';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/** Every column (required ones are filtered out of the menu). */
|
/** Every column (required ones are filtered out of the menu). */
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useWarmGridCovers } from '@/cover/useWarmGridCovers';
|
|||||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||||
import { APP_MAIN_SCROLL_VIEWPORT_ID } from '@/constants/appScroll';
|
import { APP_MAIN_SCROLL_VIEWPORT_ID } from '@/constants/appScroll';
|
||||||
import { useElementClientHeightById } from '@/lib/hooks/useResizeClientHeight';
|
import { useElementClientHeightById } from '@/lib/hooks/useResizeClientHeight';
|
||||||
import { useCardGridMetrics } from '@/hooks/useCardGridMetrics';
|
import { useCardGridMetrics } from '@/lib/hooks/useCardGridMetrics';
|
||||||
import { useRemeasureGridVirtualizer } from '@/lib/hooks/useRemeasureGridVirtualizer';
|
import { useRemeasureGridVirtualizer } from '@/lib/hooks/useRemeasureGridVirtualizer';
|
||||||
import { useVirtualizerScrollMargin } from '@/lib/hooks/useVirtualizerScrollMargin';
|
import { useVirtualizerScrollMargin } from '@/lib/hooks/useVirtualizerScrollMargin';
|
||||||
import type { CardGridRowHeightVariant } from '@/lib/util/cardGridLayout';
|
import type { CardGridRowHeightVariant } from '@/lib/util/cardGridLayout';
|
||||||
|
|||||||
Reference in New Issue
Block a user