Files
SoulStream/handoff/rounds/ins-r38-disco.txt
T
KeelrLeek 9f0601027c android: the handoff — the pending rounds, the pipeline, and what is unverified
Everything written this session that has not been through the device: rounds 43
to 48 (each patch adversarially verified, 43's transient-notice expectation
fixed), a partial round 49, the pipeline scripts, the Android Auto design and
the icon comparison mock. Also the two harness changes that were never A/B'd —
adaptive waits, which may only shorten a declared wait and never lengthen it,
and a ship that runs the mock walk and the deploy at the same time. The A/B and
its 255-step baseline are in handoff/tools; main stays at what the phone has
actually walked.
2026-09-14 07:57:41 -05:00

58 lines
2.9 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ── the whole discography, on a page of its own ─────────────────────────
The artist page's tabs are one lane per category; the discography page is
the same filing seen whole. Both read ONE classifier, and it is this one.
The desktop cannot do that: CatalogDiscography.svelte takes the artist
page's already-computed tab list as the same array object, because the
desktop's filing depends on a background description harvest and on
deferred MusicBrainz type hints that a re-run would not read
(CatalogDiscography.svelte:28-46). `discoTabs` here is pure and reads only
what the catalog page carries, so the phone simply calls it twice over the
same cached albums and the two pages can never disagree. */
/** "All" in front of the categories — built by CONCATENATING the per-category
* families, never by re-folding the whole set. A single that shares an
* album's base title (Pond released "Terrestrials" in 2026 as an album AND
* as a single) would fold into it as a phantom edition, and one of the two
* would vanish from its own tab. */
export function allTabs(tabs) {
const ts = tabs || [];
if (!ts.length) return [];
return [{ key: "all", label: "All", items: ts.flatMap((t) => t.items) }, ...ts];
}
/** The four orders the page offers, and what each is called. The sort sheet
* in HalfSheet.svelte writes the same four out inline — it is edited by
* every other round and a new import there is a collision waiting to
* happen — so if a label changes it changes in both places. */
export const ORDER_LABEL = { new: "Newest first", old: "Oldest first", az: "A–Z", za: "Z–A" };
/** The desktop's sort (CatalogDiscography.svelte:71-78): dates on
* `release_date`, names on the title, either direction. */
export function orderFamilies(items, order) {
const list = [...(items || [])];
const byName = order === "az" || order === "za";
list.sort((a, b) => (byName
? (a.title ?? "").localeCompare(b.title ?? "")
: (a.release_date ?? "").localeCompare(b.release_date ?? "")));
return order === "new" || order === "za" ? list.reverse() : list;
}
/** [{ key: "2001", items }] — the year headers, cut out of the list in the
* order it is already in rather than re-sorted, which is why a name order
* must not be grouped: the years would repeat out of sequence. `on` false
* gives the whole list back under one null key, so the caller renders one
* loop either way. */
export function byYear(items, on) {
const list = items || [];
if (!on) return list.length ? [{ key: null, items: list }] : [];
const out = [];
for (const r of list) {
const y = String(r.release_date || "").slice(0, 4) || "—";
const last = out[out.length - 1];
if (last && last.key === y) last.items.push(r);
else out.push({ key: y, items: [r] });
}
return out;
}