From 8cd56a433e9e8be7251512396ed35e5450abc5f6 Mon Sep 17 00:00:00 2001
From: KeelrLeek <156356974+KeelrLeek@users.noreply.github.com>
Date: Mon, 3 Aug 2026 17:18:25 -0500
Subject: [PATCH] player bar: the album line survives library plays, and lands
with the title
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Two halves of one defect family. The meta line preferred the queue item's
artist/album fields as a PAIR whenever either existed — but a library play
(playAlbum) writes only `artist`, with the record's name living inside
`sub` ("artist — album"), so `album: null` was taken at face value and
every library album lost its name from the bar (and the morning comment
claiming local rows carry neither field was simply wrong). Each half now
falls back to the `sub` split on its own, here and in the rail's byline —
which also restores the album for continuation items whose `sub` is a
bare artist.
And the line no longer trickles in: the buffering branch used to render
the artist alone, so the album flashed in a beat after the title when
playback started. The status gate is replaced by a REAL distinction — a
resolver-phase track has no `path` (playQueueIndex always writes one), so
"finding best source…" still shows as a bare label, and the moment a real
queue item owns the transport the full clickable line renders, buffering
or not. Measured: the first frame carrying the new title already carries
artist · album; no artist-only frame exists.
---
src/components/NowPlaying.svelte | 10 +++++++++-
src/components/PlayerBar.svelte | 34 ++++++++++++++++++++------------
2 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/src/components/NowPlaying.svelte b/src/components/NowPlaying.svelte
index 7db3e81..120a7d0 100644
--- a/src/components/NowPlaying.svelte
+++ b/src/components/NowPlaying.svelte
@@ -104,11 +104,19 @@
return sub.includes(" — ") ? sub.split(" — ")[0].trim() : sub;
});
// Artist / album split for the separate, clickable identity lines.
+ // Per field, like the player bar's: the item's own artist/album win when
+ // present (the continuation fill writes them beside a bare-artist `sub`),
+ // and each half falls back to the `sub` split on its own — a library play
+ // carries only `artist`, with the record's name living inside `sub`.
const metaParts = $derived.by(() => {
const sub = player.track?.sub ?? "";
- return sub.includes(" — ")
+ const split = sub.includes(" — ")
? sub.split(" — ").map((s) => s.trim())
: [sub.trim(), ""];
+ return [
+ currentItem?.artist ?? split[0] ?? "",
+ currentItem?.album ?? split[1] ?? "",
+ ];
});
const LOSSLESS = new Set(["FLAC", "WAV", "ALAC", "AIFF", "APE"]);
diff --git a/src/components/PlayerBar.svelte b/src/components/PlayerBar.svelte
index 9609c15..ac47d28 100644
--- a/src/components/PlayerBar.svelte
+++ b/src/components/PlayerBar.svelte
@@ -43,21 +43,23 @@
const canScratch = $derived(!currentItem?.stream);
/** Artist and album for the separate, clickable meta lines.
*
- * The queue item's OWN `artist` / `album` fields come first, and splitting
- * `sub` on the em dash is only the fallback. `sub` is a display convenience
- * that not every path fills the same way: the album-continuation fill
- * (`maybeExtendAlbumQueue`) writes a bare artist into it while carrying the
- * album right alongside, so a record played straight through lost its album
- * name from the second track on — which is exactly what it looked like.
- * Local library rows carry neither field, and those still fall back. */
+ * Per FIELD, not all-or-nothing. The queue paths disagree about what an
+ * item carries: the album-continuation fill writes artist AND album
+ * fields beside a bare-artist `sub`; a library play (`playAlbum`) writes
+ * only `artist`, with the record's name living inside `sub`
+ * ("artist — album"); old restored items may carry neither. Preferring
+ * the item's fields as a PAIR whenever either existed took `album: null`
+ * at face value and erased the record from every library play — each
+ * half now falls back to the `sub` split on its own. */
const metaParts = $derived.by(() => {
- if (currentItem?.artist || currentItem?.album) {
- return [currentItem.artist ?? "", currentItem.album ?? ""];
- }
const sub = player.track?.sub ?? "";
- return sub.includes(" — ")
+ const split = sub.includes(" — ")
? sub.split(" — ").map((s) => s.trim())
: [sub.trim(), ""];
+ return [
+ currentItem?.artist ?? split[0] ?? "",
+ currentItem?.album ?? split[1] ?? "",
+ ];
});
const volumeIcon = $derived(
player.muted || player.volume === 0
@@ -791,8 +793,14 @@
- {#if player.status === "buffering"}
- {metaParts[0] || "buffering…"}
+
+ {#if player.track && !player.track.path}
+ {player.track.sub || "buffering…"}
{:else if player.track && (metaParts[0] || metaParts[1])}
{#if metaParts[0]}