Files
Psychotoxical-psysonic/src/hooks/useServerCapabilitiesProbe.ts
T
Frank Stellmacher b591a1cb5f refactor(app-shell): I.1 — split AppShell.tsx 691 → 248 LOC across 12 files (#671)
* refactor(app-shell): extract appShellHelpers.ts

Move SIDEBAR_COLLAPSED_STORAGE_KEY + read/persist helpers and the
shouldSuppressQueueResizerMouseDown geometry helper out of AppShell.tsx
into utils/appShellHelpers.ts.

AppShell.tsx: 691 → 639 LOC.

* refactor(app-shell): extract usePlatformShellSetup hook

Bundle the one-shot platform/window-shell effects (tiling-WM detection,
no-compositing class, data-platform attr, custom titlebar sync, kinetic
scroll toggle, logging mode push) into hooks/usePlatformShellSetup.ts.
Returns isTilingWm so AppShell can still gate the custom titlebar.

AppShell.tsx: 639 → 604 LOC.

* refactor(app-shell): extract 5 lifecycle hooks

Pull these effect islands into hooks/:
- useOrbitBodyAttrs       — orbit role/phase → <html data-orbit-*> attrs
- useWindowFullscreenState — Tauri isFullscreen() tracker
- useNowPlayingTrayTitle  — title + tray tooltip sync
- useTrayMenuI18n         — tray menu labels via i18n
- useServerCapabilitiesProbe — music folders + rating support + orbit
                              orphan sweep on login

AppShell.tsx: 604 → 497 LOC.

* refactor(app-shell): extract useQueueResizer hook

Bundle queueWidth state, drag listeners, sidebar-aligned handle position,
and the click-vs-drag mousedown handler into hooks/useQueueResizer.ts.
AppShell drops shouldSuppressQueueResizerMouseDown wiring and 4 local
state pieces.

AppShell.tsx: 497 → 403 LOC.

* refactor(app-shell): extract 4 misc lifecycle hooks

- useGlobalDndAndSelectionBlockers — document-level DnD/select-all/
  selectstart blockers (Linux/WebKitGTK + Wayland workarounds).
- useAppActivityTracking — <html data-app-hidden> + <html data-app-blurred>
  so CSS can pause cosmetic animation when the app isn't being looked at.
- useMainScrollingIndicator — scroll-idle tracker for main + np viewports.
- useOfflineAutoNav — connStatus transitions push to /offline or back.

AppShell.tsx: 403 → 282 LOC.

* refactor(app-shell): extract AppShellQueueResizerSeam subcomponent

The 6px resizer strip and the round resize/toggle handle (~50 LOC of JSX
with embedded scrollbar-collision suppression + self-heal logic) move
into components/AppShellQueueResizerSeam.tsx. Desktop-only.

AppShell.tsx: 282 → 248 LOC.
2026-05-13 23:48:03 +02:00

53 lines
2.0 KiB
TypeScript

import { useEffect } from 'react';
import { getMusicFolders } from '../api/subsonicLibrary';
import { probeEntityRatingSupport } from '../api/subsonicStarRating';
import { useAuthStore } from '../store/authStore';
import { cleanupOrphanedOrbitPlaylists } from '../utils/orbit';
/**
* Per-server one-shot probe run after login:
* - Fetches the server's music folders (falls back to []).
* - Probes which entity types support star ratings (falls back to
* `track_only` for old/non-Navidrome servers).
* - Sweeps leftover Orbit session / outbox playlists from crashed or
* force-closed sessions so they don't pollute the playlist view.
*
* Each step is server-scoped — if the user switches servers mid-probe the
* stale result is dropped.
*/
export function useServerCapabilitiesProbe(): void {
const isLoggedIn = useAuthStore(s => s.isLoggedIn);
const activeServerId = useAuthStore(s => s.activeServerId);
const setMusicFolders = useAuthStore(s => s.setMusicFolders);
const setEntityRatingSupport = useAuthStore(s => s.setEntityRatingSupport);
useEffect(() => {
if (!isLoggedIn || !activeServerId) return;
const serverAtStart = activeServerId;
let cancelled = false;
(async () => {
const stillThisServer = () => !cancelled && useAuthStore.getState().activeServerId === serverAtStart;
try {
const folders = await getMusicFolders();
if (stillThisServer()) setMusicFolders(folders);
} catch {
if (stillThisServer()) setMusicFolders([]);
}
try {
const level = await probeEntityRatingSupport();
if (stillThisServer()) setEntityRatingSupport(serverAtStart, level);
} catch {
if (stillThisServer()) setEntityRatingSupport(serverAtStart, 'track_only');
}
})();
return () => {
cancelled = true;
};
}, [isLoggedIn, activeServerId, setMusicFolders, setEntityRatingSupport]);
useEffect(() => {
if (!isLoggedIn || !activeServerId) return;
void cleanupOrphanedOrbitPlaylists();
}, [isLoggedIn, activeServerId]);
}