playlists + player: every service's list through one door with its names matched for real, and shuffle that readies exactly what it promises
This commit is contained in:
1 parent
30eb6fe025
commit
50414dae5c
16 files changed
+4157
-154
No files matched your search
@@ -7,6 +7,7 @@
|
||||
getArt,
|
||||
getCatalogArt,
|
||||
jumpToQueueIndex,
|
||||
peekNextIndex,
|
||||
streamSong,
|
||||
discovery,
|
||||
loadDiscovery,
|
||||
@@ -101,11 +102,6 @@
|
||||
// nothing, then a partial list.
|
||||
const albumMode = $derived(!!player.catalogRef.albumId);
|
||||
|
||||
// Artist name for the Save action: album items carry "artist — album".
|
||||
const artistName = $derived.by(() => {
|
||||
const sub = currentItem?.sub ?? "";
|
||||
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`),
|
||||
@@ -121,6 +117,16 @@
|
||||
currentItem?.album ?? split[1] ?? "",
|
||||
];
|
||||
});
|
||||
// The artist everything else in this panel is ABOUT — discovery, the
|
||||
// chip, "More from", the in-library count, the Save action.
|
||||
//
|
||||
// It used to split `sub` on its own, which is only "artist — album" for
|
||||
// album playback. A playlist item's `sub` is the PLAYLIST's name, so
|
||||
// playing out of one loaded the whole Artist and About panes for an
|
||||
// artist called "Modern Electro Ghetto Tech Mix" while the identity
|
||||
// lines two rows above correctly read Harka. The item's own `artist`
|
||||
// field is the answer, and `metaParts` already applies that rule.
|
||||
const artistName = $derived(metaParts[0]);
|
||||
|
||||
const LOSSLESS = new Set(["FLAC", "WAV", "ALAC", "AIFF", "APE"]);
|
||||
|
||||
@@ -170,7 +176,9 @@
|
||||
// tier, drop the album that's playing now, cap at 6.
|
||||
const typeRank = (t) => (t === "album" ? 0 : t === "ep" ? 1 : 2);
|
||||
const moreAlbums = $derived.by(() => {
|
||||
const here = norm(currentItem?.sub?.split(" — ")[1] ?? "");
|
||||
// The record playing now, by the same per-field rule — `sub` is the
|
||||
// playlist's name, not "artist — album", whenever one is playing.
|
||||
const here = norm(metaParts[1]);
|
||||
return [...discovery.albums]
|
||||
.filter((a) => norm(a.title) !== here)
|
||||
.sort(
|
||||
@@ -906,7 +914,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
const upNext = $derived(player.queue[player.queueIndex + 1] ?? null);
|
||||
// What actually plays next — shuffle included: peekNextIndex reads the
|
||||
// predetermined order, so this card, the preloader and the advance all
|
||||
// name the same track.
|
||||
const upNextIndex = $derived(peekNextIndex());
|
||||
const upNext = $derived(upNextIndex >= 0 ? (player.queue[upNextIndex] ?? null) : null);
|
||||
// The NEXT track's own artwork — the card wore the CURRENT track's cover
|
||||
// for a while, which read as "The Medic" having the Jets to Brazil sleeve.
|
||||
let upNextArt = $state(null);
|
||||
$effect(() => {
|
||||
const item = upNext;
|
||||
upNextArt = null;
|
||||
if (!item) return;
|
||||
let active = true;
|
||||
if (item.art) {
|
||||
getArt(item.art, 96).then((u) => active && (upNextArt = u)).catch(() => {});
|
||||
} else if (item.artUrl) {
|
||||
getCatalogArt(playerArtSource(item)).then((u) => active && (upNextArt = u)).catch(() => {});
|
||||
}
|
||||
return () => (active = false);
|
||||
});
|
||||
|
||||
const fmtListeners = (n) => (n == null ? null : n.toLocaleString());
|
||||
|
||||
@@ -1249,8 +1276,12 @@
|
||||
<div class="pane" style="--dir: {paneDir}px">
|
||||
{#if pane === "queue"}
|
||||
{#if upNext}
|
||||
<button class="upnext" onclick={() => jumpToQueueIndex(player.queueIndex + 1)}>
|
||||
{#if artUrl}<img src={artUrl} alt="" draggable="false" />{/if}
|
||||
<button class="upnext" onclick={() => jumpToQueueIndex(upNextIndex)}>
|
||||
{#if upNextArt}
|
||||
<img src={upNextArt} alt="" draggable="false" />
|
||||
{:else}
|
||||
<span class="un-fallback"><Icon name="music" size={15} /></span>
|
||||
{/if}
|
||||
<span class="un-body">
|
||||
<span class="un-lab">Up next</span>
|
||||
<span class="un-title" title={upNext.title}>{upNext.title}</span>
|
||||
@@ -2242,6 +2273,16 @@
|
||||
border-color: color-mix(in srgb, var(--accent-hover) 45%, var(--border));
|
||||
}
|
||||
.upnext img { width: 34px; height: 34px; border-radius: 4px; flex: none; object-fit: cover; }
|
||||
.un-fallback {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
flex: none;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 6px;
|
||||
background: var(--bg-highlight);
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
.un-body { min-width: 0; flex: 1; display: block; }
|
||||
.un-lab {
|
||||
display: block;
|
||||
|
||||
Reference in new issue
Block a user