feat(playlists): reorder tracks

This commit is contained in:
2024-12-03 00:21:41 +01:00
parent 70c1d018ee
commit 793359b06e
5 changed files with 179 additions and 5 deletions

View File

@@ -7,9 +7,10 @@
import duration from 'dayjs/plugin/duration';
import { getCoverUrl } from '$lib/covers';
import Play from 'virtual:icons/lucide/play';
import Shuffle from 'virtual:icons/lucide/shuffle';
import { getPlayerState } from '$lib/player.svelte';
import { Button } from '$lib/components/ui/button';
import { deserialize } from '$app/forms';
import type { Track, TrackList } from '$lib/proto/library';
dayjs.extend(duration);
const library = getLibraryState();
@@ -20,6 +21,48 @@
let totalDuration = $derived<number>(
playlist?.tracks.reduce((acc, track) => acc + Number(track.duration), 0) ?? 0
);
function onDragStart(e: DragEvent) {
const element = e.target as HTMLElement;
e.dataTransfer?.setData('text/plain', element.getAttribute('data-playlist-index')!);
}
async function onDrop(e: DragEvent) {
const aIndex = e.dataTransfer?.getData('text/plain')!;
const bIndex = (e.currentTarget as HTMLElement).getAttribute('data-playlist-index')!;
const formData = new FormData();
formData.set('a', aIndex);
formData.set('b', bIndex);
const response = await fetch(`/playlists/${playlist!.id}?/swap-tracks`, {
method: 'POST',
headers: {
'x-sveltekit-action': 'true'
},
body: formData
});
if (!response.ok) {
return;
}
const result = deserialize(await response.text());
if (result.type === 'success' && result.data && 'tracks' in result.data) {
const _playlist = library.playlists.find((p) => p.id === playlist?.id);
if (playlist) {
playlist.tracks = (result.data as unknown as TrackList).tracks;
}
if (_playlist) {
_playlist.tracks = (result.data as unknown as TrackList).tracks;
}
}
}
</script>
{#if playlist}
@@ -40,7 +83,8 @@
</div>
<div class="mx-4">
<div class="mb-2">
<Button class="size-12" onclick={() => player.playPlaylist(playlist.id, fetch)}><Play /></Button
<Button class="size-12" onclick={() => player.playPlaylist(playlist.id, fetch)}
><Play /></Button
>
</div>
<Table.Root>
@@ -54,9 +98,16 @@
</Table.Row>
</Table.Header>
<Table.Body>
<!-- formaction="/tracks/{track.hash}?/play" -->
{#each playlist.tracks as track, i}
<Table.Row class="select-none" ondblclick={() => player.playTrack(track.hash, fetch)}>
<Table.Row
class="select-none"
ondblclick={() => player.playTrack(track.hash, fetch)}
data-playlist-index={i}
ondragstart={onDragStart}
ondrop={onDrop}
ondragover={(e) => e.preventDefault()}
draggable
>
<Table.Cell class="text-center">{i + 1}</Table.Cell>
<Table.Cell class="w-0">
<img class="overflow-hidden rounded-md" src={getCoverUrl(track.hash)} alt="" />