android: the catalog's numbers — Popular's own lane, a count per row, the artist's photo
Popular is asked on its own as well as with the page, so the section can paint before the full page is built and an artist whose page came back with none still gets one. A catalog record's rows that the album's own artist anchor found no count for — a feature's guest, a compilation's stranger — get the deferred Last.fm pass by their own artist id. The artist page's ⋯ is its own sheet now: choose a hero photo from this phone, or put the catalog's own back; set_artist_hero is pick_artist_hero's install step split out and shared, so the desktop's dialog keeps its door. You gains the desktop's Refresh artist portraits, and a data: URL is the image itself in the art gate — a chosen hero comes back from Rust as one, and the thumbnail fetch used to throw it away.
This commit is contained in:
1 parent
c737809325
commit
1737c5e1b6
12 files changed
+232
-13
No files matched your search
+31
-2
@@ -370,6 +370,9 @@ export function mockInvoke(cmd, args) {
|
||||
if (cmd === "album_tracks")
|
||||
return new Promise((r) => setTimeout(() => r(tracksFor(args.albumId)), 60));
|
||||
if (cmd === "album_art") {
|
||||
/* not a path: the real one fails to open it, which is why the art
|
||||
gate has to answer a data: URL itself */
|
||||
if (String(args.path || "").startsWith("data:")) return Promise.reject(new Error("album_art: not a path"));
|
||||
const m = /(\d+)$/.exec(args.path || "");
|
||||
const num = m ? +m[1] : 0;
|
||||
return Promise.resolve(svgArt((num * 47) % 360, String.fromCharCode(65 + (num % 26))));
|
||||
@@ -494,6 +497,8 @@ const NEWS = [
|
||||
{ title: "Infinity Repeating gets a video", url: "https://example.com/news/2", source: "NME", date: Math.floor(Date.now() / 1000) - 86400 * 2 },
|
||||
];
|
||||
const RELATED = [["Justice", 411], ["Air", 412], ["Kavinsky", 413], ["Chemical Brothers", 414]].map(([name, id], i) => ({ id, name, picture: i % 2 ? null : svgArt(40 + id, name[0]), album_count: 3, fans: 900000 - id * 100 }));
|
||||
/* the heroes chosen this session — pick_image → set_artist_hero */
|
||||
const heroes = {};
|
||||
let follows = [];
|
||||
function mockCatalog(cmd, args) {
|
||||
if (cmd === "catalog_artist") {
|
||||
@@ -502,7 +507,7 @@ function mockCatalog(cmd, args) {
|
||||
if (!a) return Promise.reject(new Error("catalog_artist: unknown artist"));
|
||||
const own = a === CAT_ARTIST;
|
||||
return new Promise((r) => setTimeout(() => r({
|
||||
artist: a, banner: null, banners: [], banner_custom: false, logos: [],
|
||||
artist: a, banner: heroes[a.id] ?? null, banners: heroes[a.id] ? [heroes[a.id]] : [], banner_custom: !!heroes[a.id], logos: [],
|
||||
popular_tracks: own ? CAT_TRACKS.slice(0, 7).map((t, i) => ({ ...t, listeners: 2_400_000 - i * 310_000 })) : [],
|
||||
albums: own ? CAT_DISCO : [{ id: 900 + id, title: a.name + " Live", artist: a.name, cover: null, release_date: "2015-01-01", record_type: "album", track_count: 9, edition_group: null, is_soundtrack: false }],
|
||||
top_genre: "Electronic", socials: [],
|
||||
@@ -518,6 +523,27 @@ function mockCatalog(cmd, args) {
|
||||
if (cmd === "catalog_artist_profile") return Promise.resolve({ listeners: 3_100_000, plays: 210_000_000, tags: ["electronic", "house", "french house", "dance"] });
|
||||
if (cmd === "catalog_artist_bio") return Promise.resolve("Daft Punk were a French electronic music duo formed in Paris in 1993 by Guy-Manuel de Homem-Christo and Thomas Bangalter. They achieved popularity in the late 1990s as part of the French house movement.");
|
||||
if (cmd === "catalog_related") return Promise.resolve(RELATED);
|
||||
/* Popular's own lane: ranked, with counts — and for the artists whose
|
||||
page gives none (the related ones), the only Popular there is */
|
||||
if (cmd === "catalog_artist_popular") {
|
||||
const id = Number(args?.artistId);
|
||||
const a = id === CAT_ARTIST.id ? CAT_ARTIST : RELATED.find((r) => r.id === id);
|
||||
if (!a) return Promise.resolve([]);
|
||||
const rows = id === CAT_ARTIST.id
|
||||
? CAT_TRACKS.slice(0, 7)
|
||||
: TITLES.slice(0, 4).map((t, i) => ({
|
||||
id: 4200000 + id * 10 + i, title: t, artist: a.name, artist_id: id, rank: 700000 - i * 1000,
|
||||
album: a.name + " Live", album_id: 900 + id, cover: null, duration_secs: 210 + i * 13, preview: null, track_no: i + 1,
|
||||
}));
|
||||
return new Promise((r) => setTimeout(() => r(rows.map((t, i) => ({ ...t, listeners: 1_900_000 - i * 240_000 }))), 260));
|
||||
}
|
||||
/* the deferred pass: a count per row, by that row's own artist id */
|
||||
if (cmd === "catalog_track_listeners") {
|
||||
const rows = args?.tracks || [];
|
||||
return new Promise((r) => setTimeout(() => r(rows.map((t, i) => (t.artistId ? 640_000 - i * 20_000 : null))), 260));
|
||||
}
|
||||
if (cmd === "set_artist_hero") { const id = Number(args?.artistId); heroes[id] = svgArt(180, "H"); return Promise.resolve({ data_url: heroes[id], width: 3840, height: 2160 }); }
|
||||
if (cmd === "clear_artist_hero") { const id = Number(args?.artistId); const had = id in heroes; delete heroes[id]; return Promise.resolve(had); }
|
||||
if (cmd === "artist_play_stats") return Promise.resolve({ seconds: 7380, last_played_at: Math.floor(Date.now() / 1000) - 86400, top_title: "Track 1", top_count: 12 });
|
||||
if (cmd === "followed_artists") return Promise.resolve(follows.slice());
|
||||
if (cmd === "follow_artist") { follows.push({ artist_id: args?.artistId, name: args?.name, portrait: args?.portrait ?? null, followed_at: Date.now() / 1000 }); later(30, () => mockEmit("soulseek:follows-changed", {})); return Promise.resolve(); }
|
||||
@@ -532,7 +558,9 @@ function mockCatalog(cmd, args) {
|
||||
if (cmd === "catalog_album") {
|
||||
const a = CAT_ALBUMS.find((x) => x.id === Number(args?.albumId));
|
||||
if (!a) return Promise.reject(new Error("catalog_album: unknown album"));
|
||||
return Promise.resolve({ album: a, tracks: a.id === 302127 ? CAT_TRACKS.map((t, i) => ({ ...t, listeners: 2_400_000 - i * 150_000 })) : [], album_plays: a.id === 302127 ? 310_000_000 : null, album_listeners: a.id === 302127 ? 4_100_000 : null, totals_summed: false });
|
||||
/* the last two rows are a guest's: the album's own artist anchor
|
||||
has no count for them, which is what the deferred pass is for */
|
||||
return Promise.resolve({ album: a, tracks: a.id === 302127 ? CAT_TRACKS.map((t, i) => (i >= CAT_TRACKS.length - 2 ? { ...t, artist: "Daft Punk feat. Todd Edwards", artist_id: 411 } : { ...t, listeners: 2_400_000 - i * 150_000 })) : [], album_plays: a.id === 302127 ? 310_000_000 : null, album_listeners: a.id === 302127 ? 4_100_000 : null, totals_summed: false });
|
||||
}
|
||||
if (cmd === "catalog_album_info") {
|
||||
const t = String(args?.title || "");
|
||||
@@ -558,6 +586,7 @@ function mockCatalog(cmd, args) {
|
||||
if (cmd === "rescan_library") return Promise.resolve();
|
||||
if (cmd === "library_art_prewarm") return Promise.resolve();
|
||||
if (cmd === "refresh_all_album_art") return new Promise((r) => setTimeout(() => r(140), 300));
|
||||
if (cmd === "refresh_artist_art") return new Promise((r) => setTimeout(() => r(26), 300));
|
||||
if (cmd === "catalog_art") return Promise.resolve(svgArt(200, "D"));
|
||||
if (cmd === "stream_cache_ready") return Promise.resolve(cacheReady.has(args?.path) || (xfer && xfer.path === args?.path && xfer.received >= xfer.total));
|
||||
if (cmd === "preload_stream") {
|
||||
|
||||
Reference in new issue
Block a user