import { useEffect, useRef } from 'react'; import { createPortal } from 'react-dom'; import { Shuffle } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { useOrbitStore } from '../store/orbitStore'; import { updateOrbitSettings, triggerOrbitShuffleNow } from '../utils/orbit'; import { ORBIT_DEFAULT_SETTINGS, ORBIT_SHUFFLE_INTERVAL_PRESETS_MIN, type OrbitShuffleIntervalMin } from '../api/orbit'; import { showToast } from '../utils/toast'; interface Props { anchorRef: React.RefObject; onClose: () => void; } /** * Host-only popover anchored below the settings button in the Orbit bar. * Two toggles; writes are pushed immediately to Navidrome via * `updateOrbitSettings`. */ export default function OrbitSettingsPopover({ anchorRef, onClose }: Props) { const { t } = useTranslation(); const settings = useOrbitStore(s => s.state?.settings) ?? ORBIT_DEFAULT_SETTINGS; const popRef = useRef(null); useEffect(() => { const onDown = (e: MouseEvent) => { const target = e.target as Node | null; if (popRef.current?.contains(target)) return; if (anchorRef.current?.contains(target)) return; onClose(); }; const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; document.addEventListener('mousedown', onDown); document.addEventListener('keydown', onKey); return () => { document.removeEventListener('mousedown', onDown); document.removeEventListener('keydown', onKey); }; }, [anchorRef, onClose]); const anchor = anchorRef.current?.getBoundingClientRect(); const style: React.CSSProperties = anchor ? { position: 'fixed', top: anchor.bottom + 12, right: Math.max(8, window.innerWidth - anchor.right), zIndex: 9999, } : { display: 'none' }; return createPortal(
{t('orbit.settingsTitle')}
{t('orbit.settingShuffleInterval')}
{t('orbit.settingShuffleIntervalHint')}
{ORBIT_SHUFFLE_INTERVAL_PRESETS_MIN.map(min => { const active = (settings.shuffleIntervalMin ?? 15) === min; return ( ); })}
, document.body, ); }