mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +00:00
The drag-row-outside-queue-to-remove feature shipped in #420 (by
cucadmuh) had its QueuePanel.tsx wiring wiped when #419 was squash-
merged from a branch that pre-dated #420. The DragDropContext and
MiniPlayer parts of #420 survived; only QueuePanel.tsx was overwritten.
Restored to the state on commit 274ac5b3:
- Import `registerQueueDragHitTest` from DragDropContext
- Subscribe to `removeTrack` from playerStore
- Register the queue rect as a hit-test region on mount
- Document-level psy-drop listener that removes the dragged row when
the drop coordinates fall outside the queue rect
Co-authored-by: cucadmuh <49571317+cucadmuh@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
dcec30166a
commit
364b29ceee
@@ -23,7 +23,7 @@ import { copyTextToClipboard } from '../utils/serverMagicString';
|
|||||||
import { showToast } from '../utils/toast';
|
import { showToast } from '../utils/toast';
|
||||||
import { useThemeStore } from '../store/themeStore';
|
import { useThemeStore } from '../store/themeStore';
|
||||||
import { useLyricsStore } from '../store/lyricsStore';
|
import { useLyricsStore } from '../store/lyricsStore';
|
||||||
import { useDragDrop } from '../contexts/DragDropContext';
|
import { useDragDrop, registerQueueDragHitTest } from '../contexts/DragDropContext';
|
||||||
import LyricsPane from './LyricsPane';
|
import LyricsPane from './LyricsPane';
|
||||||
import NowPlayingInfo from './NowPlayingInfo';
|
import NowPlayingInfo from './NowPlayingInfo';
|
||||||
import { TFunction } from 'i18next';
|
import { TFunction } from 'i18next';
|
||||||
@@ -350,6 +350,7 @@ function QueuePanelHostOrSolo() {
|
|||||||
const clearQueue = usePlayerStore(s => s.clearQueue);
|
const clearQueue = usePlayerStore(s => s.clearQueue);
|
||||||
|
|
||||||
const reorderQueue = usePlayerStore(s => s.reorderQueue);
|
const reorderQueue = usePlayerStore(s => s.reorderQueue);
|
||||||
|
const removeTrack = usePlayerStore(s => s.removeTrack);
|
||||||
const shuffleQueue = usePlayerStore(s => s.shuffleQueue);
|
const shuffleQueue = usePlayerStore(s => s.shuffleQueue);
|
||||||
const enqueue = usePlayerStore(s => s.enqueue);
|
const enqueue = usePlayerStore(s => s.enqueue);
|
||||||
const enqueueAt = usePlayerStore(s => s.enqueueAt);
|
const enqueueAt = usePlayerStore(s => s.enqueueAt);
|
||||||
@@ -492,6 +493,16 @@ function QueuePanelHostOrSolo() {
|
|||||||
|
|
||||||
const asideRef = useRef<HTMLElement>(null);
|
const asideRef = useRef<HTMLElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const hitTest = (cx: number, cy: number) => {
|
||||||
|
const el = asideRef.current;
|
||||||
|
if (!el) return false;
|
||||||
|
const r = el.getBoundingClientRect();
|
||||||
|
return cx >= r.left && cx <= r.right && cy >= r.top && cy <= r.bottom;
|
||||||
|
};
|
||||||
|
return registerQueueDragHitTest(hitTest);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const { isDragging: isPsyDragging, startDrag, payload: psyPayload } = useDragDrop();
|
const { isDragging: isPsyDragging, startDrag, payload: psyPayload } = useDragDrop();
|
||||||
/** Only these drag types may be dropped into the queue. */
|
/** Only these drag types may be dropped into the queue. */
|
||||||
const QUEUE_DROP_TYPES = new Set(['song', 'album', 'queue_reorder']);
|
const QUEUE_DROP_TYPES = new Set(['song', 'album', 'queue_reorder']);
|
||||||
@@ -559,6 +570,37 @@ function QueuePanelHostOrSolo() {
|
|||||||
return () => aside.removeEventListener('psy-drop', onPsyDrop);
|
return () => aside.removeEventListener('psy-drop', onPsyDrop);
|
||||||
}, [enqueueAt]);
|
}, [enqueueAt]);
|
||||||
|
|
||||||
|
// Drag a queue row outside the panel → remove (drop never reaches `aside`).
|
||||||
|
useEffect(() => {
|
||||||
|
const onDocPsyDrop = (e: Event) => {
|
||||||
|
if (!isQueueVisible) return;
|
||||||
|
const d = (e as CustomEvent<{ data?: string; clientX?: number; clientY?: number }>).detail;
|
||||||
|
if (!d?.data) return;
|
||||||
|
const cx = d.clientX;
|
||||||
|
const cy = d.clientY;
|
||||||
|
if (typeof cx !== 'number' || typeof cy !== 'number') return;
|
||||||
|
let parsed: { type?: string; index?: number } | null = null;
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(d.data);
|
||||||
|
} catch {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (parsed?.type !== 'queue_reorder' || typeof parsed.index !== 'number') return;
|
||||||
|
const aside = asideRef.current;
|
||||||
|
if (!aside) return;
|
||||||
|
const r = aside.getBoundingClientRect();
|
||||||
|
const inside =
|
||||||
|
cx >= r.left && cx <= r.right && cy >= r.top && cy <= r.bottom;
|
||||||
|
if (inside) return;
|
||||||
|
psyDragFromIdxRef.current = null;
|
||||||
|
externalDropTargetRef.current = null;
|
||||||
|
setExternalDropTarget(null);
|
||||||
|
removeTrack(parsed.index);
|
||||||
|
};
|
||||||
|
document.addEventListener('psy-drop', onDocPsyDrop);
|
||||||
|
return () => document.removeEventListener('psy-drop', onDocPsyDrop);
|
||||||
|
}, [isQueueVisible, removeTrack]);
|
||||||
|
|
||||||
useEffect(function queueAutoScroll() {
|
useEffect(function queueAutoScroll() {
|
||||||
if (suppressNextAutoScrollRef.current) {
|
if (suppressNextAutoScrollRef.current) {
|
||||||
suppressNextAutoScrollRef.current = false;
|
suppressNextAutoScrollRef.current = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user