Add anonymous listening support and redesign web-player UI

Backend:
- Expose GET /config/playback so the frontend can detect whether
  anonymous listening is enabled without requiring auth
- Wire anonymous access through track streaming and YouTube resolve flows

Frontend:
- Allow browsing/listening without a session when the backend enables it
- Redesign Inicio, Sidebar and top bar with a new dark theme, typography,
  and layout (top bar with live quick-search, sticky/blurred on scroll)
- Populate Top música, Popular and Recomendados with real Musify +
  YouTube Music data instead of placeholders
- Various shape, spacing, color and animation refinements across the
  redesigned components
This commit is contained in:
2026-09-11 01:29:37 +02:00
parent 10766bbb47
commit 389b3b9244
40 changed files with 1172 additions and 452 deletions
@@ -36,7 +36,7 @@
const variants = {
primary: 'bg-accent-soft text-on-accent active:scale-[0.97]',
secondary: 'bg-surface-2 text-fg hover:bg-accent/12',
secondary: 'bg-bg text-fg ring-1 ring-line hover:bg-surface',
subtle: 'bg-white/10 text-fg hover:bg-accent/18',
danger: 'bg-danger text-on-accent hover:brightness-110'
};
@@ -13,17 +13,22 @@
let { icon: Icon, title, description, class: klass = '', actions }: Props = $props();
</script>
<div class="flex flex-col items-center px-6 py-14 text-center {klass}">
<div
class="flex flex-col items-center rounded-panel border border-dashed border-line px-6 py-16 text-center {klass}"
>
{#if Icon}
<span class="grid h-14 w-14 place-items-center rounded-full bg-accent-soft text-on-accent">
<Icon class="h-6 w-6" />
<span
class="grid h-16 w-16 place-items-center rounded-full text-on-accent"
style="background:radial-gradient(circle at 30% 30%, color-mix(in oklch, var(--color-accent), white 15%), var(--color-accent))"
>
<Icon class="h-7 w-7" />
</span>
{/if}
{#if title}
<h3 class="mt-5 font-display text-2xl font-semibold tracking-tight text-fg">{title}</h3>
<h3 class="mt-6 font-display text-2xl font-medium tracking-tight text-fg">{title}</h3>
{/if}
{#if description}
<p class="mt-2 text-fg-2">{description}</p>
<p class="mt-2 max-w-sm text-fg-2">{description}</p>
{/if}
{#if actions}
<div class="mt-6 flex items-center gap-3">{@render actions()}</div>
@@ -24,11 +24,13 @@
<a
href="/mixes/{mix.id}"
class="group/tile animate-enter relative block overflow-hidden rounded-art ring-1 ring-line transition duration-300 ease-out [clip-path:inset(0_round_var(--radius-art))] ring-inset focus-visible:ring-2 focus-visible:ring-accent focus-visible:outline-none {klass}"
class="group/tile animate-enter relative block overflow-hidden rounded-art shadow-art ring-1 ring-line transition duration-300 ease-out [clip-path:inset(0_round_var(--radius-art))] ring-inset hover:shadow-art-lg focus-visible:ring-2 focus-visible:ring-accent focus-visible:outline-none {klass}"
style="animation-delay:{Math.min(index, 10) * 45}ms"
>
{#if tiles.length > 0}
<div class="absolute inset-0 flex transition duration-300 ease-out">
<div
class="absolute inset-0 flex scale-105 transition duration-500 ease-out group-hover/tile:scale-110"
>
{#each tiles as item, i (i)}
<Cover
trackId={item.trackId ?? item.videoId ?? ''}
+7 -1
View File
@@ -7,9 +7,15 @@
}
let { class: klass = '', children }: Props = $props();
let track: HTMLDivElement | undefined = $state();
export function scrollByPage(direction: 1 | -1) {
track?.scrollBy({ left: direction * track.clientWidth * 0.85, behavior: 'smooth' });
}
</script>
<div class="no-scrollbar -mx-1 flex gap-4 overflow-x-auto px-1 pb-2 {klass}">
<div bind:this={track} class="no-scrollbar -mx-1 flex gap-4 overflow-x-auto px-1 pb-2 {klass}">
{@render children()}
</div>
@@ -11,14 +11,16 @@
</script>
{#if actions}
<div class="mb-3 flex items-baseline justify-between gap-4 sm:mb-4 {klass}">
<h2 class="font-display font-medium tracking-tight text-fg sm:text-xl">
<div class="mb-4 flex items-end justify-between gap-4 sm:mb-5 {klass}">
<h2 class="font-display text-xl font-medium tracking-tight text-fg sm:text-[1.75rem]">
{title}
</h2>
{@render actions()}
</div>
{:else}
<h2 class="mb-3 font-display font-medium tracking-tight text-fg sm:mb-4 sm:text-xl {klass}">
<h2
class="mb-4 font-display text-xl font-medium tracking-tight text-fg sm:mb-5 sm:text-[1.75rem] {klass}"
>
{title}
</h2>
{/if}