refactor(app): co-locate shell-only lifecycle hooks in app/hooks; hooks/ now holds only cross-cutting hooks

This commit is contained in:
Psychotoxical
2026-06-30 20:09:22 +02:00
parent 79c02a93cf
commit 03ce57feff
18 changed files with 37 additions and 37 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ import { useLyricsStore } from './store/lyricsStore';
import { useThemeStore } from './store/themeStore';
import { useInstalledThemesStore } from './store/installedThemesStore';
import { syncInjectedThemes } from './utils/themes/themeInjection';
import { useThemeScheduler } from './hooks/useThemeScheduler';
import { useThemeScheduler } from '@/app/hooks/useThemeScheduler';
import { useFontStore } from './store/fontStore';
import { getWindowKind } from './app/windowKind';
import MiniPlayerApp from './app/MiniPlayerApp';
+9 -9
View File
@@ -36,18 +36,18 @@ import { OrbitSessionBar, OrbitStartTrigger } from '@/features/orbit';
import { useOrbitHost } from '@/features/orbit';
import { useOrbitGuest } from '@/features/orbit';
import { useOrbitBodyAttrs } from '@/features/orbit';
import { usePlatformShellSetup } from '../hooks/usePlatformShellSetup';
import { usePlatformShellSetup } from '@/app/hooks/usePlatformShellSetup';
import { useOfflineBrowseContext } from '@/features/offline';
import { offlineBrowseNavFlags } from '@/features/offline';
import { useWindowFullscreenState } from '../hooks/useWindowFullscreenState';
import { useNowPlayingTrayTitle } from '../hooks/useNowPlayingTrayTitle';
import { usePrefetchReleaseNotes } from '../hooks/usePrefetchReleaseNotes';
import { useTrayMenuI18n } from '../hooks/useTrayMenuI18n';
import { useServerCapabilitiesProbe } from '../hooks/useServerCapabilitiesProbe';
import { useWindowFullscreenState } from '@/app/hooks/useWindowFullscreenState';
import { useNowPlayingTrayTitle } from '@/app/hooks/useNowPlayingTrayTitle';
import { usePrefetchReleaseNotes } from '@/app/hooks/usePrefetchReleaseNotes';
import { useTrayMenuI18n } from '@/app/hooks/useTrayMenuI18n';
import { useServerCapabilitiesProbe } from '@/app/hooks/useServerCapabilitiesProbe';
import { useQueueResizer } from '@/features/queue';
import { useGlobalDndAndSelectionBlockers } from '@/lib/hooks/useGlobalDndAndSelectionBlockers';
import { useAppActivityTracking } from '../hooks/useAppActivityTracking';
import { useMainScrollingIndicator } from '../hooks/useMainScrollingIndicator';
import { useAppActivityTracking } from '@/app/hooks/useAppActivityTracking';
import { useMainScrollingIndicator } from '@/app/hooks/useMainScrollingIndicator';
import { useCoverNavigationPriority } from '@/cover/useCoverNavigationPriority';
import { useLiveSearchRouteScope } from '@/features/search';
import { useNowPlayingPrewarm } from '@/features/nowPlaying';
@@ -56,7 +56,7 @@ import { useOfflineLibraryFilterSuspend } from '@/features/offline';
import { AppShellQueueResizerSeam } from '@/app/AppShellQueueResizerSeam';
import { IS_LINUX, IS_MACOS } from '@/lib/util/platform';
import { useConnectionStatus } from '../hooks/useConnectionStatus';
import { useIdlePlayQueuePull } from '../hooks/useIdlePlayQueuePull';
import { useIdlePlayQueuePull } from '@/app/hooks/useIdlePlayQueuePull';
import { useAuthStore } from '../store/authStore';
import { usePlayerStore } from '@/features/playback/store/playerStore';
import '@/features/playback/store/previewPlayerVolumeSync';
+1 -1
View File
@@ -1,6 +1,6 @@
import type { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
import { retryBlockingMigration } from '../hooks/useMigrationOrchestrator';
import { retryBlockingMigration } from '@/app/hooks/useMigrationOrchestrator';
import { useMigrationStore } from '../store/migrationStore';
function MigrationModal() {
+1 -1
View File
@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { Check, ChevronDown, RefreshCw } from 'lucide-react';
import type { ConnectionStatus } from '@/hooks/useConnectionStatus';
import { usePlayQueueSyncLedState } from '@/hooks/usePlayQueueSyncLedState';
import { usePlayQueueSyncLedState } from '@/app/hooks/usePlayQueueSyncLedState';
import type { ServerProfile } from '@/store/authStoreTypes';
import { useAuthStore } from '@/store/authStore';
import { switchActiveServer } from '@/utils/server/switchActiveServer';
+1 -1
View File
@@ -29,7 +29,7 @@ import { useCoverArtPrefetch } from '../cover/useCoverArtPrefetch';
import { useLibraryCoverBackfill } from '@/cover/useLibraryCoverBackfill';
import { useCoverRevalidateScheduler } from '../cover/useCoverRevalidateScheduler';
import { runCoverIdbUpgradeMigration } from '../utils/migrations/coverIdbUpgradeMigration';
import { useMigrationOrchestrator } from '../hooks/useMigrationOrchestrator';
import { useMigrationOrchestrator } from '@/app/hooks/useMigrationOrchestrator';
import { IS_WINDOWS } from '@/lib/util/platform';
import TauriEventBridge from './TauriEventBridge';
import AppShell from './AppShell';
@@ -1,6 +1,6 @@
import { useEffect, useRef } from 'react';
import { applyServerPlayQueue } from '@/features/playback/store/applyServerPlayQueue';
import { useAuthStore } from '../store/authStore';
import { useAuthStore } from '@/store/authStore';
import { useOrbitStore } from '@/features/orbit';
import { usePlayerStore } from '@/features/playback/store/playerStore';
import {
@@ -11,8 +11,8 @@ import {
markPlaybackIdle,
} from '@/features/playback/store/queuePlaybackIdle';
import { hasPendingQueueSync } from '@/features/playback/store/queueSync';
import type { ConnectionStatus } from './useConnectionStatus';
import { canAutoIdlePlayQueuePull } from './usePlayQueueSyncLedState';
import type { ConnectionStatus } from '@/hooks/useConnectionStatus';
import { canAutoIdlePlayQueuePull } from '@/app/hooks/usePlayQueueSyncLedState';
const IDLE_THRESHOLD_MS = 30_000;
const POLL_INTERVAL_MS = 10_000;
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
import {
APP_MAIN_SCROLL_VIEWPORT_ID,
mainRouteInpageScrollViewportId,
} from '../constants/appScroll';
} from '@/constants/appScroll';
const SCROLL_IDLE_MS = 180;
@@ -1,7 +1,7 @@
import { renderHook, waitFor } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { useAuthStore } from '../store/authStore';
import { useMigrationStore } from '../store/migrationStore';
import { useAuthStore } from '@/store/authStore';
import { useMigrationStore } from '@/store/migrationStore';
const migrationInspectMock = vi.fn();
const migrationRunMock = vi.fn();
@@ -13,7 +13,7 @@ vi.mock('@tauri-apps/api/event', () => ({
listen: vi.fn(async () => () => {}),
}));
vi.mock('../api/migration', () => ({
vi.mock('@/api/migration', () => ({
migrationInspect: (mappings: unknown) => migrationInspectMock(mappings),
migrationRun: (mappings: unknown) => migrationRunMock(mappings),
}));
@@ -23,11 +23,11 @@ vi.mock('@/lib/api/library', () => ({
libraryGenreTagsRun: () => libraryGenreTagsRunMock(),
}));
vi.mock('../utils/server/rewriteFrontendStoreKeys', () => ({
vi.mock('@/utils/server/rewriteFrontendStoreKeys', () => ({
rewriteFrontendStoreKeys: (servers: unknown) => rewriteFrontendStoreKeysMock(servers),
}));
import { useMigrationOrchestrator } from './useMigrationOrchestrator';
import { useMigrationOrchestrator } from '@/app/hooks/useMigrationOrchestrator';
const DONE_FLAG = 'psysonic-server-key-migration-v1';
const REAL_MIGRATION_TEST_OVERRIDE = '__PSYSONIC_REAL_MIGRATION_TEST__';
@@ -1,11 +1,11 @@
import { useEffect } from 'react';
import { listen } from '@tauri-apps/api/event';
import { libraryGenreTagsInspect, libraryGenreTagsRun } from '@/lib/api/library';
import { migrationInspect, migrationRun, type ServerIndexMapping } from '../api/migration';
import { useAuthStore } from '../store/authStore';
import { useMigrationStore } from '../store/migrationStore';
import { serverIndexKeyFromUrl } from '../utils/server/serverIndexKey';
import { rewriteFrontendStoreKeys } from '../utils/server/rewriteFrontendStoreKeys';
import { migrationInspect, migrationRun, type ServerIndexMapping } from '@/api/migration';
import { useAuthStore } from '@/store/authStore';
import { useMigrationStore } from '@/store/migrationStore';
import { serverIndexKeyFromUrl } from '@/utils/server/serverIndexKey';
import { rewriteFrontendStoreKeys } from '@/utils/server/rewriteFrontendStoreKeys';
const MIGRATION_DONE_FLAG = 'psysonic-server-key-migration-v1';
let migrationInFlight: Promise<void> | null = null;
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { invoke } from '@tauri-apps/api/core';
import { useAuthStore } from '../store/authStore';
import type { LinuxWaylandTextRenderProfile } from '../store/authStoreTypes';
import { useAuthStore } from '@/store/authStore';
import type { LinuxWaylandTextRenderProfile } from '@/store/authStoreTypes';
import { IS_LINUX, IS_MACOS, IS_WINDOWS } from '@/lib/util/platform';
/**
@@ -1,8 +1,8 @@
import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react';
import { useTranslation } from 'react-i18next';
import type { ConnectionStatus } from '../hooks/useConnectionStatus';
import type { ConnectionStatus } from '@/hooks/useConnectionStatus';
import { pullPlayQueueFromActiveServer } from '@/features/playback/store/applyServerPlayQueue';
import { useAuthStore } from '../store/authStore';
import { useAuthStore } from '@/store/authStore';
import { useOrbitStore } from '@/features/orbit';
import { usePlayerStore } from '@/features/playback/store/playerStore';
import { getPlaybackServerId, queueIsMultiServer } from '@/features/playback/utils/playback/playbackServer';
@@ -11,7 +11,7 @@ import {
subscribeIdleQueuePullSuspended,
} from '@/features/playback/store/queuePlaybackIdle';
import { clearQueueHandoffPending, isQueueHandoffPending } from '@/features/playback/store/queueSyncUiState';
import { showToast } from '../utils/ui/toast';
import { showToast } from '@/utils/ui/toast';
export function usePlayQueueSyncLedState(status: ConnectionStatus) {
const { t } = useTranslation();
@@ -1,7 +1,7 @@
import { useEffect } from 'react';
import { version as appVersion } from '../../package.json';
import { isWorkspaceReleaseNotesMode } from '../utils/releaseNotes/releaseNotesChannel';
import { resolveReleaseNotes } from '../utils/releaseNotes/releaseNotesResolve';
import { version as appVersion } from '@/../package.json';
import { isWorkspaceReleaseNotesMode } from '@/utils/releaseNotes/releaseNotesChannel';
import { resolveReleaseNotes } from '@/utils/releaseNotes/releaseNotesResolve';
/**
* Warm the release-notes cache after an update (RC/stable only).
@@ -1,7 +1,7 @@
import { useEffect } from 'react';
import { getMusicFolders } from '@/lib/api/subsonicLibrary';
import { probeEntityRatingSupport } from '@/lib/api/subsonicStarRating';
import { useAuthStore } from '../store/authStore';
import { useAuthStore } from '@/store/authStore';
import { cleanupOrphanedOrbitPlaylists } from '@/features/orbit';
/**
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
import { useThemeStore, getScheduledTheme } from '../store/themeStore';
import { useThemeStore, getScheduledTheme } from '@/store/themeStore';
import { useSystemPrefersDark } from '@/lib/hooks/useSystemPrefersDark';
/**