mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +00:00
7ad196711e
Continue M4 lib/ de-flattening with domain-agnostic infra: - lib/hooks/: 9 pure generic hooks (useDebouncedValue, useIsMobile, useLongPressAction, useRangeSelection, useResizeClientHeight, useWindowVisibility, useSystemPrefersDark, useVirtualizerScrollMargin, useRemeasureGridVirtualizer) — all PURE (only react/zustand/tanstack deps). - lib/dnd/DragDropContext.tsx: the generic mouse-event DnD engine (WebKitGTK HTML5-DnD workaround, ~24 importers, self-contained) — empties src/contexts/. - lib/shortcuts/: shortcutActions + shortcutTypes (the action-id + binding contract; registry/dispatch/bindings stay app-level and import the contract, app->lib direction). useWindowFullscreenState deliberately NOT moved — kept in hooks/ as app-shell per the handoff iron-rule list (overrides its pure-helper appearance). Pure move via deep @/lib/* specifiers. tsc 0, lint 0/0, full suite 319 files / 2353 tests green.
49 lines
1.9 KiB
TypeScript
49 lines
1.9 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { DragDropProvider } from '@/lib/dnd/DragDropContext';
|
|
import MiniPlayer from '@/features/miniPlayer';
|
|
import GlobalConfirmModal from '../components/GlobalConfirmModal';
|
|
import TooltipPortal from '@/ui/TooltipPortal';
|
|
import FpsOverlay from '../components/FpsOverlay';
|
|
import { useThemeStore } from '../store/themeStore';
|
|
import { useFontStore } from '../store/fontStore';
|
|
import { useKeybindingsStore } from '../store/keybindingsStore';
|
|
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
|
|
import i18n from '@/lib/i18n';
|
|
|
|
/**
|
|
* Mini-player webview tree. Rendered in the secondary Tauri window labelled
|
|
* "mini" — no router, no sidebar, no full audio listeners. The window listens
|
|
* for state pushes from the main webview (via the storage event below) and
|
|
* sends control events back through the mini-player bridge.
|
|
*/
|
|
export default function MiniPlayerApp() {
|
|
const perfFlags = usePerfProbeFlags();
|
|
|
|
// Both webviews share localStorage (same origin), so the `storage` event
|
|
// fires in this window whenever main mutates a persisted key — but Zustand
|
|
// persist only reads localStorage on initial load, hence the explicit
|
|
// rehydrate.
|
|
useEffect(() => {
|
|
const onStorage = (e: StorageEvent) => {
|
|
if (!e.key) return;
|
|
if (e.key === 'psysonic_theme') useThemeStore.persist.rehydrate();
|
|
else if (e.key === 'psysonic_font') useFontStore.persist.rehydrate();
|
|
else if (e.key === 'psysonic_keybindings') useKeybindingsStore.persist.rehydrate();
|
|
else if (e.key === 'psysonic_language' && e.newValue) {
|
|
i18n.changeLanguage(e.newValue);
|
|
}
|
|
};
|
|
window.addEventListener('storage', onStorage);
|
|
return () => window.removeEventListener('storage', onStorage);
|
|
}, []);
|
|
|
|
return (
|
|
<DragDropProvider>
|
|
<MiniPlayer />
|
|
<GlobalConfirmModal />
|
|
{!perfFlags.disableTooltipPortal && <TooltipPortal />}
|
|
<FpsOverlay />
|
|
</DragDropProvider>
|
|
);
|
|
}
|