web-player: normalize tracks, albums and playlists into single domain types at the server boundary
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
import ListMusic from '@lucide/svelte/icons/list-music';
|
||||
|
||||
function seek(value: number) {
|
||||
if (player.current.duration > 0) player.seekFraction(value / player.current.duration);
|
||||
if (player.duration > 0) player.seekFraction(value / player.duration);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -39,13 +39,13 @@
|
||||
</span>
|
||||
<Slider
|
||||
value={player.progress}
|
||||
max={player.current.duration}
|
||||
max={player.duration}
|
||||
label="Barra de progreso"
|
||||
oninput={seek}
|
||||
variant="seek"
|
||||
/>
|
||||
<span class="min-w-8 text-xs text-fg-2 tabular-nums">
|
||||
{fmtTime(player.current.duration)}
|
||||
{fmtTime(player.duration)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
</IconButton>
|
||||
</div>
|
||||
|
||||
{#if player.current.id}
|
||||
{#if player.current}
|
||||
<p class="mb-3 text-eyebrow text-fg-2">Reproduciendo</p>
|
||||
<div class="mb-6 surface-active rounded-control p-2.5">
|
||||
<MediaIdentity
|
||||
|
||||
@@ -13,27 +13,20 @@
|
||||
|
||||
let { compact = false }: Props = $props();
|
||||
|
||||
const isLiked = $derived(player.current.id !== '' && liked.isLiked(player.current.id));
|
||||
const current = $derived(player.current);
|
||||
const isLiked = $derived(current !== null && liked.isLiked(current.id));
|
||||
|
||||
function toggleLike() {
|
||||
if (!player.current.id) return;
|
||||
liked.toggle({
|
||||
id: player.current.id,
|
||||
title: player.current.title,
|
||||
artist: player.current.artist,
|
||||
explicit: player.current.explicit,
|
||||
ownerUserId: player.current.ownerUserId,
|
||||
duration: player.current.duration
|
||||
});
|
||||
if (current) liked.toggle(current);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex min-w-0 items-center gap-2.5 md:gap-3">
|
||||
{#if player.current.id}
|
||||
{#if current}
|
||||
<Artwork
|
||||
trackIds={[player.current.id]}
|
||||
trackIds={[current.id]}
|
||||
size="sm"
|
||||
alt={player.current.title}
|
||||
alt={current.title}
|
||||
class="shrink-0 md:size-cover-md"
|
||||
/>
|
||||
{:else}
|
||||
@@ -41,14 +34,14 @@
|
||||
{/if}
|
||||
<div class="min-w-0">
|
||||
<div class="flex min-w-0 items-center gap-1.5">
|
||||
{#if player.current.explicit}
|
||||
{#if current?.explicit}
|
||||
<ExplicitBadge />
|
||||
{/if}
|
||||
<span class="truncate text-sm text-fg">{player.current.title}</span>
|
||||
<span class="truncate text-sm text-fg">{current?.title ?? ''}</span>
|
||||
</div>
|
||||
<ArtistLink
|
||||
name={player.current.artist || '—'}
|
||||
ownerUserId={player.current.ownerUserId}
|
||||
name={current?.artist || '—'}
|
||||
ownerUserId={current?.ownerUserId}
|
||||
class="mt-0.5 text-xs text-fg-2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
<script lang="ts" module>
|
||||
import type { Track } from '$lib/types';
|
||||
|
||||
export type TrackListColumn = 'added' | 'uploaded' | 'plays';
|
||||
|
||||
export interface TrackListTrack {
|
||||
id: string | number;
|
||||
title: string;
|
||||
artist?: string | null;
|
||||
ownerUserId?: string | number | null;
|
||||
isExplicit?: boolean;
|
||||
explicit?: boolean;
|
||||
duration?: number | string;
|
||||
listensCount?: number | string;
|
||||
addedAt?: string | number;
|
||||
uploadedAt?: string | number;
|
||||
}
|
||||
export type TrackListTrack = Track & { date?: string | number };
|
||||
|
||||
const COLUMN_PRESET: Record<TrackListColumn, { label: string; width: string }> = {
|
||||
added: { label: 'Añadida', width: '124px' },
|
||||
@@ -108,7 +99,7 @@
|
||||
</div>
|
||||
<div class="mt-1 flex flex-col gap-0.5" role="list">
|
||||
{#each tracks as track, i (track.id)}
|
||||
{@const active = player.current.id === track.id}
|
||||
{@const active = player.currentId === track.id}
|
||||
|
||||
<div
|
||||
role="listitem"
|
||||
@@ -145,7 +136,7 @@
|
||||
title={track.title}
|
||||
artist={track.artist}
|
||||
ownerUserId={track.ownerUserId}
|
||||
explicit={track.isExplicit ?? track.explicit ?? false}
|
||||
explicit={track.explicit}
|
||||
{active}
|
||||
>
|
||||
{#snippet overlay()}
|
||||
@@ -158,16 +149,14 @@
|
||||
{#each columns as column (column)}
|
||||
<span class="hidden truncate text-center text-xs text-fg-2 tabular-nums sm:block">
|
||||
{#if column === 'plays'}
|
||||
{Number(track.listensCount ?? 0)}
|
||||
{:else if column === 'added' && track.addedAt}
|
||||
{fmtDate(track.addedAt)}
|
||||
{:else if column === 'uploaded' && track.uploadedAt}
|
||||
{fmtDate(track.uploadedAt)}
|
||||
{track.listensCount}
|
||||
{:else if track.date}
|
||||
{fmtDate(track.date)}
|
||||
{/if}
|
||||
</span>
|
||||
{/each}
|
||||
<span class="truncate text-center text-xs text-fg-2 tabular-nums">
|
||||
{fmtTime(Number(track.duration))}
|
||||
{fmtTime(track.duration)}
|
||||
</span>
|
||||
{#if rowAction}
|
||||
{#if rowAction.action}
|
||||
|
||||
Reference in New Issue
Block a user