{
e.preventDefault();
if (document.body.classList.contains('is-overlay-scrollbar-thumb-drag')) return;
if (shouldSuppressQueueResizerMouseDown(e.clientX, e.clientY, queueWidth)) return;
setIsDraggingQueue(true);
}}
style={{ display: isQueueVisible ? 'block' : 'none' }}
/>
)}
{!isMobile &&
}
{isMobile && !isMobilePlayer &&
}
{!isMobilePlayer &&
}
{isFullscreenOpen && (
)}
);
}
// Media key + tray event handler
function TauriEventBridge() {
const navigate = useNavigate();
const togglePlay = usePlayerStore(s => s.togglePlay);
const next = usePlayerStore(s => s.next);
const previous = usePlayerStore(s => s.previous);
// ZIP download progress events from Rust
useEffect(() => {
let unlisten: (() => void) | undefined;
listen<{ id: string; bytes: number; total: number | null }>('download:zip:progress', e => {
useZipDownloadStore.getState().updateProgress(e.payload.id, e.payload.bytes, e.payload.total);
}).then(u => { unlisten = u; });
return () => { unlisten?.(); };
}, []);
// Audio output device changed (Bluetooth headphones, USB DAC, etc.)
// The Rust device-watcher has already reopened the stream on the new device
// and dropped the old Sink, so we just need to restart playback.
useEffect(() => {
let unlisten: (() => void) | undefined;
listen('audio:device-changed', () => {
const { currentTrack, isPlaying, playTrack, resetAudioPause } = usePlayerStore.getState();
if (!currentTrack) return;
if (isPlaying) {
playTrack(currentTrack);
} else {
// Paused: clear warm-pause flag so the next resume uses the cold path
// (audio_play + seek) which creates a new Sink on the new device.
resetAudioPause();
}
}).then(u => { unlisten = u; });
return () => { unlisten?.(); };
}, []);
// Pinned output device was unplugged — Rust already fell back to system default.
// Clear the stored device so the Settings dropdown resets to "System Default".
useEffect(() => {
let unlisten: (() => void) | undefined;
listen('audio:device-reset', () => {
useAuthStore.getState().setAudioOutputDevice(null);
const { currentTrack, currentTime, isPlaying, playTrack, resetAudioPause } = usePlayerStore.getState();
if (!currentTrack) return;
if (isPlaying) {
playTrack(currentTrack);
} else {
resetAudioPause();
}
}).then(u => { unlisten = u; });
return () => { unlisten?.(); };
}, []);
// CLI: `--player audio-device set …` (forwarded on Linux via single-instance).
useEffect(() => {
let unlisten: (() => void) | undefined;
listen