web-player: P9 — tarjetas y grids (MediaCard)
MediaCard pasa a construir su propio arte (src/trackIds vía Artwork size="fill", o un snippet art a medida) y su botón de reproducir (onPlay, con scrim y PlayButton glass en hover) en vez de depender de que cada wrapper le pase un snippet. Sustituye a AlbumCard, PlaylistCard y MixTile, que se borran junto con MediaGrid.svelte (sus grids pasan a los @utility grid-cards/grid-cards-lg/grid-tiles/ grid-wide de P1). format.ts gana albumMeta() y playlistMeta() (antes cálculos ad-hoc dentro de cada tarjeta). El tile de género en Explorar pasa de un style= con el gradiente inline a la receta @utility genre-tile + --tile-hue. De paso, corrige la pluralización "seguidor/es" del perfil de usuario que quedó suelta. Delta documentado: el hover-zoom del arte y el scrim+PlayButton (antes exclusivos de MixTile) pasan a ser comportamiento de MediaCard condicionado a la prop onPlay — se aplicarían a cualquier tarjeta futura que la use, por consistencia. Verificado con npm run check/build; sin QA visual autenticada (Docker no disponible en esta sesión). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
import { player, isQueueCurrent, playAllOrToggle, playShuffled } from '$lib/player/player.svelte';
|
||||
import { pressable } from '$lib/actions/pressable';
|
||||
import { mergeRecentlyPlayed } from '$lib/recentlyPlayed';
|
||||
import { mixItemTarget } from '$lib/mixes';
|
||||
import { fmtTime, fmtDurationLong, fmtPlays, plural } from '$lib/format';
|
||||
import {
|
||||
isTargetCurrent,
|
||||
@@ -20,7 +21,7 @@
|
||||
type TrackTarget
|
||||
} from '$lib/tracks';
|
||||
import Artwork from '$lib/components/ui/Artwork.svelte';
|
||||
import MixTile from '$lib/components/ui/MixTile.svelte';
|
||||
import MediaCard from '$lib/components/ui/MediaCard.svelte';
|
||||
import EqBars from '$lib/components/ui/EqBars.svelte';
|
||||
import ListRow from '$lib/components/ui/ListRow.svelte';
|
||||
import SectionHeading from '$lib/components/ui/SectionHeading.svelte';
|
||||
@@ -107,6 +108,14 @@
|
||||
function openContextMenu(event: MouseEvent, target: TrackTarget) {
|
||||
trackMenu.open(event, target);
|
||||
}
|
||||
|
||||
function playMix(mix: (typeof mixes)[number], event: MouseEvent) {
|
||||
event.preventDefault();
|
||||
player.playQueue(
|
||||
mix.items.map((item) => queueItemForTarget(mixItemTarget(item))),
|
||||
0
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -274,9 +283,16 @@
|
||||
<section>
|
||||
<SectionHeading title="Mixes" subtitle="Generados a partir de lo que más repites" />
|
||||
{#if mixes.length > 0}
|
||||
<div class="grid grid-cols-[repeat(auto-fill,minmax(164px,1fr))] gap-5">
|
||||
<div class="grid-tiles">
|
||||
{#each mixes as mix, i (mix.id)}
|
||||
<MixTile {mix} index={i} />
|
||||
<MediaCard
|
||||
href="/mixes/{mix.id}"
|
||||
title={mix.title}
|
||||
subtitle={mix.subtitle}
|
||||
trackIds={mix.items.map((item) => item.trackId)}
|
||||
onPlay={(event) => playMix(mix, event)}
|
||||
index={i}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
@@ -351,7 +367,7 @@
|
||||
{/snippet}
|
||||
</SectionHeading>
|
||||
{#if playlists.length > 0}
|
||||
<div class="grid grid-cols-[repeat(auto-fill,minmax(258px,1fr))] gap-3.5">
|
||||
<div class="grid-wide">
|
||||
{#each playlists as playlist, i (playlist.id)}
|
||||
<ListRow
|
||||
onclick={() => goto(`/playlists/${playlist.id}`)}
|
||||
|
||||
Reference in New Issue
Block a user