Files
Psychotoxical-psysonic/src/hooks/useMiniSync.ts
T
Frank Stellmacher 383bbbd75f refactor(mini-player): H6 — split MiniPlayer.tsx 820 → 218 LOC across 11 files (#669)
* refactor(mini-player): H6 — extract helpers + constants

Pure code-move: window-size constants, localStorage keys + read helpers,
toMini track shape, initialSnapshot, and fmt(seconds) → utils/miniPlayerHelpers.ts.

MiniPlayer.tsx: 820 → 745 LOC.

* refactor(mini-player): H6 — extract MiniTitlebar + MiniMeta + MiniControls

Three small visual subcomponents move into components/miniPlayer/.
MiniPlayer drops the now-unused Pin/PinOff/Maximize2/X/Play/Pause/
SkipBack/SkipForward lucide icons and the CachedImage import.

MiniPlayer.tsx: 745 → 665 LOC.

* refactor(mini-player): H6 — extract MiniToolbar + useMiniVolumePopover

The whole toolbar (volume button + portaled popover, shuffle, gapless/
crossfade/infinite, queue toggle) moves into MiniToolbar.tsx. The volume
popover open-state + ref/style positioning + outside-click/Escape close
move into the useMiniVolumePopover hook.

MiniPlayer.tsx: 665 → 492 LOC.

* refactor(mini-player): H6 — extract MiniQueue + useMiniQueueDrag

The OverlayScrollArea + queue.map block moves into MiniQueue.tsx. The
PsyDnD wiring (drop-inside emits mini:reorder, drop-outside emits
mini:remove, reorder math collapsing same-position + adjusting for shift)
moves into the useMiniQueueDrag hook.

MiniPlayer.tsx: 492 → 346 LOC.

* refactor(mini-player): H6 — extract useMiniSync + useMiniWindowSetup + useMiniKeyboardShortcuts

Three more hooks pull the remaining side-effect islands out of MiniPlayer:
  - useMiniSync owns mini:ready emit on mount + focus, plus the
    mini:sync / audio:progress / audio:ended listeners. The hidden-window
    visibility ref that gates progress now lives inside the hook.
  - useMiniWindowSetup bundles three small window-bound effects:
    Linux WebKitGTK smooth-scroll, the cold-start expanded-size restore
    when queueOpen=true, and always-on-top reapply on mount + focus.
  - useMiniKeyboardShortcuts moves the keyboard-shortcut bridge wiring.

MiniPlayer.tsx: 346 → 218 LOC.
2026-05-13 23:07:45 +02:00

49 lines
1.8 KiB
TypeScript

import { useEffect, useRef } from 'react';
import { emit, listen } from '@tauri-apps/api/event';
import { useWindowVisibility } from './useWindowVisibility';
import type { MiniSyncPayload } from '../utils/miniPlayerBridge';
interface ProgressPayload {
current_time: number;
duration: number;
}
interface Args {
onSync: (s: MiniSyncPayload) => void;
onProgress: (currentTime: number, duration: number) => void;
onEnded: () => void;
}
/** Bridge wiring between the mini webview and the main window / Rust:
* - emits mini:ready on mount + on focus (Windows pre-creates the mini so the
* mount-time emit can race the main bridge; refocus guarantees re-sync)
* - listens for mini:sync, audio:progress (skipped while hidden), audio:ended
* - cleans up on unmount */
export function useMiniSync({ onSync, onProgress, onEnded }: Args) {
const isHidden = useWindowVisibility();
const hiddenRef = useRef(false);
useEffect(() => { hiddenRef.current = isHidden; }, [isHidden]);
useEffect(() => {
emit('mini:ready', {}).catch(() => {});
const onFocus = () => { emit('mini:ready', {}).catch(() => {}); };
window.addEventListener('focus', onFocus);
return () => window.removeEventListener('focus', onFocus);
}, []);
useEffect(() => {
const unSync = listen<MiniSyncPayload>('mini:sync', (e) => onSync(e.payload));
const unProgress = listen<ProgressPayload>('audio:progress', (e) => {
if (hiddenRef.current || window.__psyHidden) return;
onProgress(e.payload.current_time, e.payload.duration);
});
const unEnded = listen('audio:ended', () => onEnded());
return () => {
unSync.then(fn => fn()).catch(() => {});
unProgress.then(fn => fn()).catch(() => {});
unEnded.then(fn => fn()).catch(() => {});
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}