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.
This commit is contained in:
1 parent
867fd42972
commit
9f0601027c
400 files changed
+26401
-3
No files matched your search
@@ -0,0 +1,57 @@
|
||||
/* ── 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;
|
||||
}
|
||||
Reference in new issue
Block a user