Changes
This commit is contained in:
@@ -174,5 +174,13 @@
|
||||
menu={albumMenu}
|
||||
playlists={data.playlists}
|
||||
onClose={() => (albumMenu = null)}
|
||||
onPlayNext={() => {
|
||||
player.playNext(queue);
|
||||
albumMenu = null;
|
||||
}}
|
||||
onAddToQueue={() => {
|
||||
player.appendToQueue(queue);
|
||||
albumMenu = null;
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { untrack } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { player } from '$lib/player/player.svelte';
|
||||
import { fetchAlbumQueueItems } from '$lib/albums';
|
||||
import { fmtTime } from '$lib/format';
|
||||
import Page from '$lib/components/ui/Page.svelte';
|
||||
import PageHeader from '$lib/components/ui/PageHeader.svelte';
|
||||
@@ -163,14 +164,24 @@
|
||||
contextMenu = contextMenuStateFor(event, target);
|
||||
}
|
||||
|
||||
function isForeignAlbum(album: LocalAlbum) {
|
||||
return String(album.ownerUserId) !== data.user?.sub;
|
||||
}
|
||||
|
||||
function openAlbumMenu(event: MouseEvent, kind: 'local' | 'youtube', albumId: string) {
|
||||
albumMenu = albumContextMenuStateFor(event, kind, albumId);
|
||||
}
|
||||
|
||||
async function albumPlayNext() {
|
||||
if (!albumMenu) return;
|
||||
const { kind, albumId } = albumMenu;
|
||||
albumMenu = null;
|
||||
player.playNext(await fetchAlbumQueueItems(kind, albumId));
|
||||
}
|
||||
|
||||
async function albumAddToQueue() {
|
||||
if (!albumMenu) return;
|
||||
const { kind, albumId } = albumMenu;
|
||||
albumMenu = null;
|
||||
player.appendToQueue(await fetchAlbumQueueItems(kind, albumId));
|
||||
}
|
||||
|
||||
function addToQueue() {
|
||||
if (!contextMenu) return;
|
||||
player.addToQueue(queueItemForTarget(contextMenu));
|
||||
@@ -255,9 +266,7 @@
|
||||
href="/albums/{entry.album.id}"
|
||||
class="group/card animate-enter block min-w-0 rounded-art focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-bg focus-visible:outline-none"
|
||||
style="animation-delay:{Math.min(i, 10) * 45}ms"
|
||||
oncontextmenu={isForeignAlbum(entry.album)
|
||||
? (e) => openAlbumMenu(e, 'local', entry.album.id)
|
||||
: undefined}
|
||||
oncontextmenu={(e) => openAlbumMenu(e, 'local', entry.album.id)}
|
||||
>
|
||||
<div class="relative">
|
||||
<PlaylistArt
|
||||
@@ -395,5 +404,7 @@
|
||||
menu={albumMenu}
|
||||
playlists={data.playlists}
|
||||
onClose={() => (albumMenu = null)}
|
||||
onPlayNext={albumPlayNext}
|
||||
onAddToQueue={albumAddToQueue}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import type { PageServerLoad, Actions } from './$types';
|
||||
import { createApiClient, requireUser } from '$lib/server/api';
|
||||
import { fetchYoutubeFiller } from '$lib/server/youtube';
|
||||
import { addTrackAction, addYouTubeToPlaylistAction } from '$lib/server/playlistActions';
|
||||
import {
|
||||
addAlbumToPlaylistAction,
|
||||
addTrackAction,
|
||||
addYouTubeToPlaylistAction
|
||||
} from '$lib/server/playlistActions';
|
||||
import {
|
||||
HOME_ALBUMS_LIMIT,
|
||||
HOME_LATEST_PAGE_SIZE,
|
||||
@@ -62,5 +66,6 @@ export const load: PageServerLoad = async ({ locals, url, fetch }) => {
|
||||
|
||||
export const actions: Actions = {
|
||||
addTrack: addTrackAction,
|
||||
addYouTubeToPlaylist: addYouTubeToPlaylistAction
|
||||
addYouTubeToPlaylist: addYouTubeToPlaylistAction,
|
||||
addAlbumToPlaylist: addAlbumToPlaylistAction
|
||||
};
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
contextMenuStateFor,
|
||||
type ContextMenuState
|
||||
} from '$lib/components/TrackContextMenu.svelte';
|
||||
import AlbumContextMenu, {
|
||||
albumContextMenuStateFor,
|
||||
type AlbumMenuState
|
||||
} from '$lib/components/AlbumContextMenu.svelte';
|
||||
import { fetchAlbumQueueItems } from '$lib/albums';
|
||||
import type { YouTubeSong } from '$lib/types';
|
||||
import { appendUnique } from '$lib/collections';
|
||||
import { HOME_LATEST_PAGE_SIZE } from '$lib/config';
|
||||
@@ -33,6 +38,7 @@
|
||||
let { data } = $props();
|
||||
|
||||
let contextMenu = $state<ContextMenuState | null>(null);
|
||||
let albumMenu = $state<AlbumMenuState | null>(null);
|
||||
let youtubeFillerItems = $state<YouTubeSong[]>([]);
|
||||
|
||||
$effect(() => {
|
||||
@@ -109,6 +115,24 @@
|
||||
contextMenu = null;
|
||||
}
|
||||
|
||||
function openAlbumMenu(event: MouseEvent, albumId: string) {
|
||||
albumMenu = albumContextMenuStateFor(event, 'local', albumId);
|
||||
}
|
||||
|
||||
async function albumPlayNext() {
|
||||
if (!albumMenu) return;
|
||||
const { kind, albumId } = albumMenu;
|
||||
albumMenu = null;
|
||||
player.playNext(await fetchAlbumQueueItems(kind, albumId));
|
||||
}
|
||||
|
||||
async function albumAddToQueue() {
|
||||
if (!albumMenu) return;
|
||||
const { kind, albumId } = albumMenu;
|
||||
albumMenu = null;
|
||||
player.appendToQueue(await fetchAlbumQueueItems(kind, albumId));
|
||||
}
|
||||
|
||||
function albumCaption(album: (typeof albums)[number]) {
|
||||
return [
|
||||
album.releaseYear ? String(album.releaseYear) : undefined,
|
||||
@@ -195,6 +219,7 @@
|
||||
: `/albums/${album.id}`}
|
||||
class="group/card animate-enter block w-42 shrink-0 rounded-art focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-bg focus-visible:outline-none"
|
||||
style="animation-delay:{Math.min(i, 10) * 45}ms"
|
||||
oncontextmenu={(e) => openAlbumMenu(e, album.id)}
|
||||
>
|
||||
<div class="relative">
|
||||
{#if album.thumbnailUrl}
|
||||
@@ -266,9 +291,13 @@
|
||||
>
|
||||
{playlist.name}
|
||||
</div>
|
||||
{#if playlist.description}
|
||||
<div class="mt-0.5 truncate text-sm text-muted">{playlist.description}</div>
|
||||
{/if}
|
||||
<div class="mt-0.5 truncate text-sm text-muted">
|
||||
{#if playlist.description}
|
||||
{playlist.description}
|
||||
{:else}
|
||||
|
||||
{/if}
|
||||
</div>
|
||||
</a>
|
||||
{/each}
|
||||
<a
|
||||
@@ -330,7 +359,11 @@
|
||||
</section>
|
||||
{/if}
|
||||
{#if recentlyPlayed.length === 0 && albums.length === 0 && mixes.length === 0 && playlists.length === 0 && newTargets.length === 0}
|
||||
<EmptyState icon={Music} title="Todavía no hay música" description="Sube tu música o explora nuevas canciones, álbumes y listas de reproducción." />
|
||||
<EmptyState
|
||||
icon={Music}
|
||||
title="Todavía no hay música"
|
||||
description="Sube tu música o explora nuevas canciones, álbumes y listas de reproducción."
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -387,3 +420,13 @@
|
||||
onAddToQueue={addToQueue}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if albumMenu}
|
||||
<AlbumContextMenu
|
||||
menu={albumMenu}
|
||||
{playlists}
|
||||
onClose={() => (albumMenu = null)}
|
||||
onPlayNext={albumPlayNext}
|
||||
onAddToQueue={albumAddToQueue}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { RequestHandler } from './$types';
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { createApiClient, unwrapOrError } from '$lib/server/api';
|
||||
import { ALBUM_TRACKS_PAGE_SIZE } from '$lib/config';
|
||||
|
||||
export const GET: RequestHandler = async ({ params, locals, fetch }) => {
|
||||
const api = createApiClient({ fetch, accessToken: locals.accessToken ?? undefined });
|
||||
const result = await api.GET('/albums/{albumId}/tracks', {
|
||||
params: {
|
||||
path: { albumId: params.id },
|
||||
query: { pageNumber: 1, pageSize: ALBUM_TRACKS_PAGE_SIZE }
|
||||
}
|
||||
});
|
||||
|
||||
return json(unwrapOrError(result, 'No se pudo cargar el álbum.'));
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { RequestHandler } from './$types';
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { createApiClient, unwrapOrError } from '$lib/server/api';
|
||||
|
||||
export const GET: RequestHandler = async ({ params, locals, fetch }) => {
|
||||
const api = createApiClient({ fetch, accessToken: locals.accessToken ?? undefined });
|
||||
const result = await api.GET('/youtube/albums/{albumId}', {
|
||||
params: { path: { albumId: params.albumId } }
|
||||
});
|
||||
|
||||
return json(unwrapOrError(result, 'No se pudo cargar el álbum de YouTube.'));
|
||||
};
|
||||
Reference in New Issue
Block a user