Files
wehub-resource-sync 2114b14ee0
Sync main into demo / sync (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:26 +08:00

81 lines
2.4 KiB
TypeScript

import React, { useEffect, useRef } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useSpotifyStore } from '../state';
import { useSpotifyStrings } from '../hooks/useSpotifyStrings';
import { useSpotifyGestures } from '../hooks/useSpotifyGestures';
import { QueueSheetPanel } from './QueueSheetPanel';
const TOAST_DURATION = 5000;
export const QueueToastBanner: React.FC = () => {
const s = useSpotifyStrings();
const [, setSearchParams] = useSearchParams();
const queueToast = useSpotifyStore(st => st._temp.queueToast);
const currentTrack = useSpotifyStore(st => st.currentTrack);
const clearQueueToast = useSpotifyStore(st => st.clearQueueToast);
const timerRef = useRef<number | null>(null);
useEffect(() => {
if (!queueToast) return;
if (timerRef.current !== null) window.clearTimeout(timerRef.current);
timerRef.current = window.setTimeout(() => {
timerRef.current = null;
clearQueueToast();
}, TOAST_DURATION);
return () => {
if (timerRef.current !== null) {
window.clearTimeout(timerRef.current);
timerRef.current = null;
}
};
}, [queueToast, clearQueueToast]);
if (!queueToast) return null;
return (
<div
data-hide-on-keyboard
className="fixed left-2 right-2 z-[68]"
style={{
bottom: currentTrack
? 'calc(var(--app-bottom-player-bottom) + 76px)'
: 'calc(var(--app-tab-bar-height) + 12px)',
}}
>
<div className="flex h-11 items-center justify-between rounded-lg bg-white px-4 text-black shadow-2xl">
<span className="truncate text-sm font-semibold">
{s.queue_toast_added}
</span>
<button
onClick={() => {
clearQueueToast();
setSearchParams(p => { p.set('overlay', 'queue'); return p; });
}}
className="flex-shrink-0 text-sm font-bold text-[#1DB954]"
>
{s.queue_toast_open}
</button>
</div>
</div>
);
};
export const QueueSheet: React.FC = () => {
const [searchParams] = useSearchParams();
const { bindBack, back } = useSpotifyGestures();
const isOpen = searchParams.get('overlay') === 'queue';
if (!isOpen) return null;
const backProps = bindBack({ stopPropagation: true });
return (
<div className="absolute inset-0 z-[80]">
<QueueSheetPanel
backdropProps={backProps}
onClose={() => back()}
/>
</div>
);
};