mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +00:00
c0f2bc00dd
Final piece of the App.tsx slim-down. The `TauriEventBridge` component — ZIP download progress, track-preview lifecycle, audio device changed/reset, the full `cli:*` listener surface (audio-device-set, instant-mix, library list/set, server list/set, search, player-command), tray-icon visibility sync, in-app keybindings keydown handler, media keys + tray actions, `shortcut:global-action` / `shortcut:run-action`, seek-relative / seek-absolute / set-volume, the window:close-requested + app:force-quit flow (with the shared `performExit` Orbit teardown), and the `psysonic --info` snapshot publisher — moves into `src/app/TauriEventBridge.tsx`. `MainApp` imports it from the new file. `App.tsx` is now 57 LOC: just the `App()` default-export that branches between `MiniPlayerApp` and `MainApp` after wiring the shared theme / font / track-preview document attributes. A.K.A. App.tsx 1453 → 57 LOC over Phase 2 (M0 + B.1 + B.2 + C.1 + C.2 + D). Pure code move at every step — no behaviour change. Pre-PR check: PASS (frontend tests, tsc, coverage gates, prod build, backend tests, clippy, backend coverage gates).
58 lines
2.4 KiB
TypeScript
58 lines
2.4 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { useAuthStore } from './store/authStore';
|
|
import { useThemeStore } from './store/themeStore';
|
|
import { useThemeScheduler } from './hooks/useThemeScheduler';
|
|
import { useFontStore } from './store/fontStore';
|
|
import { getWindowKind } from './app/windowKind';
|
|
import MiniPlayerApp from './app/MiniPlayerApp';
|
|
import MainApp from './app/MainApp';
|
|
|
|
export default function App() {
|
|
// Re-subscribe so themeStore changes trigger a re-render (the value itself
|
|
// is consumed via useThemeScheduler / data-theme attribute below).
|
|
useThemeStore(s => s.theme);
|
|
const effectiveTheme = useThemeScheduler();
|
|
const font = useFontStore(s => s.font);
|
|
|
|
// Document-attribute hooks are shared between both window kinds — each
|
|
// webview has its own `document`, and theme / font / track-preview tokens
|
|
// are read by CSS in both trees.
|
|
useEffect(() => {
|
|
document.documentElement.setAttribute('data-theme', effectiveTheme);
|
|
}, [effectiveTheme]);
|
|
|
|
useEffect(() => {
|
|
document.documentElement.setAttribute('data-font', font);
|
|
}, [font]);
|
|
|
|
// Hide all inline track-preview buttons when the user opts out — single
|
|
// CSS hook (`html[data-track-previews="off"]`) instead of conditional
|
|
// rendering in every tracklist. Per-location toggles use additional
|
|
// attributes `data-track-previews-{location}` consumed by scoped selectors.
|
|
const trackPreviewsEnabled = useAuthStore(s => s.trackPreviewsEnabled);
|
|
const trackPreviewLocations = useAuthStore(s => s.trackPreviewLocations);
|
|
const trackPreviewDurationSec = useAuthStore(s => s.trackPreviewDurationSec);
|
|
useEffect(() => {
|
|
document.documentElement.setAttribute(
|
|
'data-track-previews',
|
|
trackPreviewsEnabled ? 'on' : 'off',
|
|
);
|
|
}, [trackPreviewsEnabled]);
|
|
useEffect(() => {
|
|
const root = document.documentElement;
|
|
(Object.keys(trackPreviewLocations) as Array<keyof typeof trackPreviewLocations>).forEach(loc => {
|
|
root.setAttribute(`data-track-previews-${loc.toLowerCase()}`, trackPreviewLocations[loc] ? 'on' : 'off');
|
|
});
|
|
}, [trackPreviewLocations]);
|
|
// Drive the SVG progress-ring keyframe duration from the same setting that
|
|
// governs the engine's auto-stop timer so both finish in lockstep.
|
|
useEffect(() => {
|
|
document.documentElement.style.setProperty(
|
|
'--preview-duration',
|
|
`${trackPreviewDurationSec}s`,
|
|
);
|
|
}, [trackPreviewDurationSec]);
|
|
|
|
return getWindowKind() === 'mini' ? <MiniPlayerApp /> : <MainApp />;
|
|
}
|