web-player: big pages (Explore, Home) and tracks.ts cleanup

This pass also tackles the task deferred earlier: removing
tracks.ts's TrackTarget wrapper and its 8 accessors
(targetId/targetTitle/targetArtist/targetOwnerUserId/targetExplicit/
targetListensCount/isTargetCurrent/queueItemForTarget/
targetForQueueItem). Explore, Home, Mix, menus.svelte.ts and mixes.ts
now use track objects directly, with
toQueueItem/trackFromQueueItem (new, in player.svelte.ts) as the only
converters. Along the way, TypeScript revealed that isExplicit
doesn't exist in the real /tracks schema: Explore's "explicit" badge
was already a no-op before this refactor (always undefined ??
false); the binding is removed instead of pretending support that
never existed.

Explore: GENRE_INFO/genreTiles are extracted to src/lib/genres.ts;
the search logic
(showGroup/capped/matchPlaylists/searchCounts/searchChips/findTopResult)
is extracted to src/lib/search.ts as pure functions parameterized by
filter/query instead of closing over component state. "Top result"
unifies the duplicated button/link with <svelte:element>. Decision
made without blocking: the 4 group blocks (Tracks/Albums/Users/
Playlists) are not collapsed into a single {#each groups} — each
group has genuinely different snippets, context menu and ListRow
props, and a generic config would have added more indirection than it
removed.

Home: uses Page instead of a hand-rolled page-x; the 3 stats become
an {#each}; the hero/spotlight backgrounds (inline style= with CSS
variables) become the hero-surface/spotlight-surface utilities, and
gap-11.5 is replaced by the --spacing-section token (2.875rem) via
gap-section.

Verified with npm run check (0 errors) and npm run build. /explore
without a session redirects to /login because +layout.server.ts
requires allowAnonymousListening from the backend (unreachable
without Docker this session) — pre-existing behavior, not a
regression. No authenticated visual QA; smoke-tested /login with no
console errors.
This commit is contained in:
2026-09-21 14:51:43 +02:00
parent 5fa901c2e6
commit b60a87adb5
11 changed files with 458 additions and 443 deletions
+5 -6
View File
@@ -1,8 +1,7 @@
import { contextMenuPosition, type MenuPosition } from '$lib/components/ui/ContextMenu.svelte';
import { player } from './player/player.svelte';
import { queueItemForTarget, type TrackTarget } from './tracks';
import { player, toQueueItem, type ApiTrackLike } from './player/player.svelte';
export type TrackMenuState = TrackTarget & MenuPosition;
export type TrackMenuState = { track: ApiTrackLike } & MenuPosition;
export function createTrackMenu() {
let state = $state<TrackMenuState | null>(null);
@@ -11,15 +10,15 @@ export function createTrackMenu() {
get state() {
return state;
},
open(event: MouseEvent, target: TrackTarget) {
state = { ...target, ...contextMenuPosition(event) };
open(event: MouseEvent, track: ApiTrackLike) {
state = { track, ...contextMenuPosition(event) };
},
close() {
state = null;
},
playNext() {
if (!state) return;
player.playNextItem(queueItemForTarget(state));
player.playNextItem(toQueueItem(state.track));
state = null;
}
};