Files
SoulStream/handoff/rounds/patch-round6.cjs
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

71 lines
4.2 KiB
JavaScript

// Round six: the desktop's Save menu on the now-playing track — a streamed
// track (or the whole streamed record in the queue) filed into the library:
// at once when its cache is complete, else through the download pipeline.
const fs = require('fs');
const root = 'F:/Coding/SoulStream/';
let p, s;
const load = (file) => { p = file; s = fs.readFileSync(root + p, 'utf8'); };
const save = () => fs.writeFileSync(root + p, s);
const once = (a) => {
const i = s.indexOf(a);
if (i < 0) throw new Error('missing in ' + p + ': ' + a.slice(0, 90));
if (s.indexOf(a, i + 1) >= 0) throw new Error('ambiguous in ' + p + ': ' + a.slice(0, 90));
return i;
};
const rep = (a, b) => { once(a); s = s.replace(a, () => b); };
const NL = String.fromCharCode(10);
const afterLine = (anchor, text) => { const i = once(anchor); const nl = s.indexOf(NL, i); s = s.slice(0, nl + 1) + text + s.slice(nl + 1); };
load('src/mobile/HalfSheet.svelte');
rep(` /* a peer's sheet (a raw result's folder, or the browse screen's user) */`,
` /* the desktop's Save menu: a streamed track filed into the library —
at once when its cache is byte-complete, else through the download
pipeline — and the whole streamed record the queue holds */
const streamMates = (track, album) => player.queue.filter((e) => e.t?.stream && e.t.path && e.album?.title === album?.title && e.album?.artist === album?.artist);
async function saveStreams(entries) {
const srcs = entries.filter((e) => e.t?.stream && e.t.path).map((e) => ({ username: e.t.stream.username, path: e.t.path, size: e.t.stream.size }));
if (!srcs.length) return;
try {
const [organized, queued] = await api.saveToLibrary(srcs);
note(organized && !queued ? (organized === 1 ? "Saved to the library" : organized + " tracks saved to the library")
: queued ? queued + " downloading into the library" + (organized ? " · " + organized + " saved" : "")
: "Nothing to save");
} catch (e) { oops(e); }
}
/* a peer's sheet (a raw result's folder, or the browse screen's user) */`);
rep(` {@render row("play", "Play next", "", act(() => playNext([{ t: track, album }])))}
{@render row("list-plus", "Add to queue", after ? after + " after this" : "", act(() => enqueue([{ t: track, album }])))}`,
` {#if track.stream}
{@render row("download", "Save to library", "this track, from " + track.stream.username, act(() => saveStreams([{ t: track, album }])))}
{#if streamMates(track, album).length > 1}
{@render row("download", "Save this record", streamMates(track, album).length + " tracks streaming from the same record", act(() => saveStreams(streamMates(track, album))))}
{/if}
<div class="sheet-hair"></div>
{/if}
{@render row("play", "Play next", "", act(() => playNext([{ t: track, album }])))}
{@render row("list-plus", "Add to queue", after ? after + " after this" : "", act(() => enqueue([{ t: track, album }])))}`);
save();
load('tests/mobile/smoke.mjs');
rep(` { name: "net-arrived", wait: 7000 },`,
` { name: "net-arrived", wait: 7000 },
/* the now-playing sheet's ⋯: the streamed track saved into the library
(its cache is complete by now, so it files at once) */
{ do: \`document.querySelectorAll('.sheet .np-head .iconbtn')[1].click()\`, name: "np-more", wait: 700 },
{ do: \`__click('.halfsheet .row', 'Save to library')\`, name: "np-saved", wait: 900 },`);
afterLine('"net-arrived": (i) =>', ` "np-more": (i) => i.half.includes("up") && /Save to library/.test(i.halfText),
"np-saved": (i) => !i.half.includes("up") && /Saved to the library/.test(i.notice),
`);
save();
load('ANDROID.md');
rep(`the artist. Search corrects an obvious misspelling from the names this
phone knows`,
`the artist. The now-playing sheet's ⋯ on a streamed track is the desktop's
Save menu: Save to library (at once when the cache is byte-complete, else
through the download pipeline) and Save this record for the streamed
record the queue holds. Search corrects an obvious misspelling from the
names this phone knows`);
save();
console.log('round six wired');