forked from Keelrleek/SoulStream
search: the results page, the typeahead, and a session that survives a reload
The page is the signed-off prototype built out: floating rounded hero, inline top-tracks panel, filter chips, two-column Songs|Albums beside Artists, and all seven states — results, searching, no results, one-kind-only, library-empty, provider-unreachable, first visit. MusicBrainz records are merged in silently behind the Deezer rows. The top result is ranked by POPULARITY, not by kind: each kind puts up its most popular exact match and the winner is whichever holds the largest share of its own kind's leader. A raw fans-vs-rank comparison was tried first and handed "panda bear" to an Owl City song. Two provenance traps are paid for here. Deezer's /search/album returns no release_date at all, so sorting newest-first ordered by PROVENANCE rather than by date; dates are backfilled from the artist overview, resolved PER ALBUM ARTIST because Deezer's artist search answers nothing for "weezer blue album". And the typeahead holds its keyboard selection as the row's KEY rather than its index, because the MusicBrainz supplement lands ~600ms later and re-orders the album group under the cursor. The hero's middle third is hidden on the width of the PANE, not the window. The sidebar and the now-playing rail take ~490px between them, so a 1504px window can leave the hero 1012px — a window-width media query cannot see that, and the "latest release" card ended up sheared down to 26px of itself. The budget is written out at the @container rule. Session restore rounds it off: reload or restart returns to the same place with the same track, everything but the transport coming from localStorage. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7547fed56d
commit
b173f60085
6 files changed
+3315
-493
No files matched your search
@@ -11,9 +11,7 @@
|
||||
refreshRecents,
|
||||
toggleSidebar,
|
||||
goToView,
|
||||
openCatalogAlbum,
|
||||
openAlbumByName,
|
||||
openLibraryAlbum,
|
||||
openRecentAlbum,
|
||||
getArt,
|
||||
} from "../lib/state.svelte.js";
|
||||
import * as api from "../lib/api.js";
|
||||
@@ -139,34 +137,6 @@
|
||||
return !!a.art_path && a.art_path === playingArt;
|
||||
}
|
||||
|
||||
async function openRecent(a) {
|
||||
if (a.kind === "catalog" && a.catalog_album_id) {
|
||||
// The catalog page, not the old library album view — streamed
|
||||
// records live in the catalog. The seed paints title/artist/cover
|
||||
// immediately instead of flashing a skeleton.
|
||||
openCatalogAlbum(a.catalog_album_id, {
|
||||
seed: {
|
||||
id: a.catalog_album_id,
|
||||
title: a.title,
|
||||
artist: a.artist,
|
||||
cover: a.art_url ?? null,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
// A library row has no catalog id to open with — local albums carry no
|
||||
// catalog identity at all (`albums.mbid` is null and never surfaced) —
|
||||
// so the record is resolved by artist + title, where BOTH must match
|
||||
// normalized or nothing opens. That namesake guard lives in
|
||||
// openAlbumByName and is the reason this can't just take a first hit.
|
||||
//
|
||||
// Either way it is the SAME album page: a record no catalog has (Panda
|
||||
// Bear's "A ? of WHEN", verified live) opens from the library's own
|
||||
// data instead. There is no second album view to fall back to.
|
||||
if (await openAlbumByName(a.artist, a.title)) return;
|
||||
void openLibraryAlbum(a.album_id);
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if (!recentsStore.loaded) refreshRecents();
|
||||
});
|
||||
@@ -261,7 +231,7 @@
|
||||
class="rec"
|
||||
class:on={isPlaying(row.album)}
|
||||
title="{row.album.title} — {row.album.artist}"
|
||||
onclick={() => openRecent(row.album)}
|
||||
onclick={() => openRecentAlbum(row.album)}
|
||||
>
|
||||
{#if coverOf(row.album)}
|
||||
<img src={coverOf(row.album)} alt="" draggable="false" />
|
||||
|
||||
Reference in new issue
Block a user