feat(frontend): add queue option and enlarge first-level context menu text
The right-click menu now has a plain 'Añadir a la cola' item (appends the track to player.tracks via the new player.addToQueue) alongside the existing playlist submenu, and its first-level text is text-base to match the rest of the menu.
This commit is contained in:
@@ -333,6 +333,14 @@ class PlayerState {
|
|||||||
this.#loadCurrent();
|
this.#loadCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addToQueue(item: QueueItem) {
|
||||||
|
if (this.currentId === null) {
|
||||||
|
this.playQueue([item], 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.tracks = [...this.tracks, toTrack(item)];
|
||||||
|
}
|
||||||
|
|
||||||
playTrack(id: string | number) {
|
playTrack(id: string | number) {
|
||||||
if (this.currentId === id) {
|
if (this.currentId === id) {
|
||||||
this.toggle();
|
this.toggle();
|
||||||
|
|||||||
@@ -2,10 +2,17 @@
|
|||||||
import Search from '@lucide/svelte/icons/search';
|
import Search from '@lucide/svelte/icons/search';
|
||||||
import Music from '@lucide/svelte/icons/music';
|
import Music from '@lucide/svelte/icons/music';
|
||||||
import ChevronRight from '@lucide/svelte/icons/chevron-right';
|
import ChevronRight from '@lucide/svelte/icons/chevron-right';
|
||||||
|
import ListPlus from '@lucide/svelte/icons/list-plus';
|
||||||
import LoaderCircle from '@lucide/svelte/icons/loader-circle';
|
import LoaderCircle from '@lucide/svelte/icons/loader-circle';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { enhance } from '$app/forms';
|
import { enhance } from '$app/forms';
|
||||||
import { player, queueIdForTrack, toQueueItems } from '$lib/player/player.svelte';
|
import {
|
||||||
|
player,
|
||||||
|
queueIdForTrack,
|
||||||
|
toQueueItems,
|
||||||
|
type ApiTrackLike,
|
||||||
|
type QueueItem
|
||||||
|
} from '$lib/player/player.svelte';
|
||||||
import Cover from '$lib/components/ui/Cover.svelte';
|
import Cover from '$lib/components/ui/Cover.svelte';
|
||||||
import PlaylistArt from '$lib/components/ui/PlaylistArt.svelte';
|
import PlaylistArt from '$lib/components/ui/PlaylistArt.svelte';
|
||||||
import { HUES } from '$lib/theme/color';
|
import { HUES } from '$lib/theme/color';
|
||||||
@@ -20,14 +27,9 @@
|
|||||||
isExplicit: boolean;
|
isExplicit: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LocalTrackTarget {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type ContextMenuTarget =
|
type ContextMenuTarget =
|
||||||
| { kind: 'youtube'; song: YouTubeSong }
|
| { kind: 'youtube'; song: YouTubeSong }
|
||||||
| { kind: 'local'; track: LocalTrackTarget };
|
| { kind: 'local'; track: ApiTrackLike };
|
||||||
|
|
||||||
let { data, form } = $props();
|
let { data, form } = $props();
|
||||||
|
|
||||||
@@ -128,6 +130,24 @@
|
|||||||
contextMenu = null;
|
contextMenu = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function queueItemFor(target: ContextMenuTarget): QueueItem {
|
||||||
|
return target.kind === 'youtube'
|
||||||
|
? {
|
||||||
|
id: target.song.videoId,
|
||||||
|
title: target.song.title,
|
||||||
|
artist: target.song.artist,
|
||||||
|
source: 'youtube',
|
||||||
|
coverUrl: target.song.thumbnailUrl
|
||||||
|
}
|
||||||
|
: toQueueItems([target.track])[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function addToQueue(target: ContextMenuTarget | null) {
|
||||||
|
if (!target) return;
|
||||||
|
player.addToQueue(queueItemFor(target));
|
||||||
|
closeContextMenu();
|
||||||
|
}
|
||||||
|
|
||||||
async function loadMoreYouTube() {
|
async function loadMoreYouTube() {
|
||||||
if (!ytContinuation || ytLoadingMore) return;
|
if (!ytContinuation || ytLoadingMore) return;
|
||||||
ytLoadingMore = true;
|
ytLoadingMore = true;
|
||||||
@@ -369,12 +389,20 @@
|
|||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
class="fixed z-40 w-52 rounded-2xl border border-white/10 bg-neutral-900 p-1.5 shadow-[0_12px_28px_-10px_rgba(0,0,0,0.8)]"
|
class="fixed z-40 w-56 rounded-2xl border border-white/10 bg-neutral-900 p-1.5 shadow-[0_12px_28px_-10px_rgba(0,0,0,0.8)]"
|
||||||
style="left:{contextMenu.x}px; top:{contextMenu.y}px;"
|
style="left:{contextMenu.x}px; top:{contextMenu.y}px;"
|
||||||
>
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => addToQueue(contextMenu)}
|
||||||
|
class="flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-left text-base text-neutral-200 transition hover:bg-white/5"
|
||||||
|
>
|
||||||
|
<ListPlus class="h-4 w-4 shrink-0 text-neutral-500" />
|
||||||
|
<span>Añadir a la cola</span>
|
||||||
|
</button>
|
||||||
<div class="group/addmenu relative">
|
<div class="group/addmenu relative">
|
||||||
<div
|
<div
|
||||||
class="flex items-center justify-between gap-2 rounded-lg px-3 py-2 text-sm text-neutral-200 transition group-hover/addmenu:bg-white/5"
|
class="flex items-center justify-between gap-2 rounded-lg px-3 py-2 text-base text-neutral-200 transition group-hover/addmenu:bg-white/5"
|
||||||
>
|
>
|
||||||
<span>Añadir a una playlist</span>
|
<span>Añadir a una playlist</span>
|
||||||
<ChevronRight class="h-4 w-4 shrink-0 text-neutral-500" />
|
<ChevronRight class="h-4 w-4 shrink-0 text-neutral-500" />
|
||||||
|
|||||||
Reference in New Issue
Block a user