drag drop
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
nowPlayingLabel,
|
||||
prev,
|
||||
removeTrack,
|
||||
reorderTrackById,
|
||||
schedulePersistNow,
|
||||
setUiOpen,
|
||||
setVolume,
|
||||
@@ -274,6 +275,87 @@
|
||||
|
||||
let clearQueueDialogOpen = $state(false);
|
||||
|
||||
// --- Drag & drop reorder (works for both linear and shuffle) ---
|
||||
// We reorder by track.id (annSongId). The player module adjusts traversal state.
|
||||
let dragId = $state<number | null>(null);
|
||||
let dragOverId = $state<number | null>(null);
|
||||
|
||||
function onDragStart(trackId: number, e: DragEvent) {
|
||||
dragId = trackId;
|
||||
dragOverId = null;
|
||||
|
||||
// Best-effort: set payload (useful for some browsers)
|
||||
try {
|
||||
e.dataTransfer?.setData("text/plain", String(trackId));
|
||||
e.dataTransfer!.effectAllowed = "move";
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function onDragOver(trackId: number, e: DragEvent) {
|
||||
// Required to allow dropping
|
||||
e.preventDefault();
|
||||
dragOverId = trackId;
|
||||
|
||||
try {
|
||||
e.dataTransfer!.dropEffect = "move";
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function onDrop(targetTrackId: number, e: DragEvent) {
|
||||
e.preventDefault();
|
||||
|
||||
// Prefer our internal dragId; fall back to transfer data
|
||||
let sourceId = dragId;
|
||||
if (sourceId == null) {
|
||||
const raw = e.dataTransfer?.getData("text/plain");
|
||||
const parsed = raw ? Number(raw) : NaN;
|
||||
if (Number.isFinite(parsed)) sourceId = parsed;
|
||||
}
|
||||
|
||||
if (sourceId == null) {
|
||||
dragId = null;
|
||||
dragOverId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sourceId === targetTrackId) {
|
||||
dragId = null;
|
||||
dragOverId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Reorder by queue indices
|
||||
const fromIndex = snap.queue.findIndex((t) => t.id === sourceId);
|
||||
const toIndex = snap.queue.findIndex((t) => t.id === targetTrackId);
|
||||
|
||||
if (fromIndex === -1 || toIndex === -1) {
|
||||
dragId = null;
|
||||
dragOverId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
reorderTrackById(sourceId, toIndex);
|
||||
|
||||
dragId = null;
|
||||
dragOverId = null;
|
||||
}
|
||||
|
||||
function onDragEnd() {
|
||||
dragId = null;
|
||||
dragOverId = null;
|
||||
}
|
||||
|
||||
function draggableHint(trackId: number) {
|
||||
if (dragId == null) return "";
|
||||
if (dragId === trackId) return "opacity-70";
|
||||
if (dragOverId === trackId) return "ring-2 ring-primary/40";
|
||||
return "";
|
||||
}
|
||||
|
||||
function formatTime(seconds: number) {
|
||||
if (!Number.isFinite(seconds) || seconds < 0) return "0:00";
|
||||
const s = Math.floor(seconds);
|
||||
@@ -699,7 +781,17 @@
|
||||
<ul class="rounded border">
|
||||
{#each queueDisplay as item (item.track.id)}
|
||||
<li
|
||||
class="flex items-center gap-2 border-b px-2 py-2 last:border-b-0"
|
||||
class={[
|
||||
"flex items-center gap-2 border-b px-2 py-2 last:border-b-0",
|
||||
draggableHint(item.track.id),
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(" ")}
|
||||
draggable="true"
|
||||
ondragstart={(e) => onDragStart(item.track.id, e)}
|
||||
ondragover={(e) => onDragOver(item.track.id, e)}
|
||||
ondrop={(e) => onDrop(item.track.id, e)}
|
||||
ondragend={onDragEnd}
|
||||
>
|
||||
<button
|
||||
class="min-w-0 flex-1 truncate text-left text-sm hover:underline"
|
||||
@@ -976,7 +1068,17 @@
|
||||
<ul class="rounded border">
|
||||
{#each queueDisplay as item (item.track.id)}
|
||||
<li
|
||||
class="flex items-center gap-2 border-b px-2 py-2 last:border-b-0"
|
||||
class={[
|
||||
"flex items-center gap-2 border-b px-2 py-2 last:border-b-0",
|
||||
draggableHint(item.track.id),
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(" ")}
|
||||
draggable="true"
|
||||
ondragstart={(e) => onDragStart(item.track.id, e)}
|
||||
ondragover={(e) => onDragOver(item.track.id, e)}
|
||||
ondrop={(e) => onDrop(item.track.id, e)}
|
||||
ondragend={onDragEnd}
|
||||
>
|
||||
<button
|
||||
class="min-w-0 flex-1 truncate text-left text-sm hover:underline"
|
||||
|
||||
Reference in New Issue
Block a user