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

119 lines
7.1 KiB
JavaScript

// Round nineteen: downloads on Wi-Fi only — a switch the phone needs and the
// desktop never did. One guard (network.svelte.js) before every download
// the phone can start; streaming is never refused.
const fs = require('fs');
const root = process.env.SS_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); };
fs.copyFileSync('C:/Users/Kyle/AppData/Local/Temp/claude/F--Coding-SoulStream/5488514a-11e8-482a-b0a0-20cb511ee110/scratchpad/network.svelte.js', root + 'src/mobile/network.svelte.js');
load('src/mobile/prefs.svelte.js');
rep(`export const settings = $state({ ambience: true, accent: true, motion: true, glass: false });`,
`export const settings = $state({ ambience: true, accent: true, motion: true, glass: false, wifiOnly: false });`);
save();
// ── the guards ──
load('src/mobile/resolve.svelte.js');
rep(`import { yearOf } from "./catalog.svelte.js";`, `import { yearOf } from "./catalog.svelte.js";
import { downloadsAllowed } from "./network.svelte.js";`);
rep(`export async function saveCatalogAlbum(album) {`, `export async function saveCatalogAlbum(album) {
if (!downloadsAllowed()) return false;`);
rep(`export async function saveSong(artist, title) {
if (resolver.active) return false;`, `export async function saveSong(artist, title) {
if (resolver.active) return false;
if (!downloadsAllowed()) return false;`);
save();
load('src/mobile/playlists.svelte.js');
rep(`import { slsk } from "./slsk.svelte.js";`, `import { slsk } from "./slsk.svelte.js";
import { downloadsAllowed } from "./network.svelte.js";`);
rep(`export async function runBulk(p, items, mode) {
if (bulk.active) return false;`, `export async function runBulk(p, items, mode) {
if (bulk.active) return false;
if (mode === "download" && !downloadsAllowed()) return false;`);
save();
load('src/mobile/HalfSheet.svelte');
rep(` import { art, wantArt } from "./art.svelte.js";`, ` import { art, wantArt } from "./art.svelte.js";
import { downloadsAllowed } from "./network.svelte.js";`);
rep(` async function saveStreams(entries) {`, ` async function saveStreams(entries) {
if (!downloadsAllowed()) return;`);
rep(` async function saveGroup(g) {`, ` async function saveGroup(g) {
if (!downloadsAllowed()) return;`);
rep(`act(() => api.downloadFile(g.username, f.path, f.size).then(() => note(`, `act(() => { if (!downloadsAllowed()) return; api.downloadFile(g.username, f.path, f.size).then(() => note(`);
save();
// the file row's act closes with ")))}" — reshape to a block
load('src/mobile/HalfSheet.svelte');
{
const a = `act(() => { if (!downloadsAllowed()) return; api.downloadFile(g.username, f.path, f.size).then(() => note(\`Saving “\${titleFromName(f.name)}” from \${g.username}\`)).catch(oops)))}`;
once(a);
s = s.replace(a, () => `act(() => { if (!downloadsAllowed()) return; api.downloadFile(g.username, f.path, f.size).then(() => note(\`Saving “\${titleFromName(f.name)}” from \${g.username}\`)).catch(oops); }))}`);
save();
}
load('src/mobile/screens/Browse.svelte');
rep(` import { note } from "../notice.svelte.js";`, ` import { note } from "../notice.svelte.js";
import { downloadsAllowed } from "../network.svelte.js";`);
rep(` async function save(d) {
const list = d.files.filter(audio);
if (!list.length) return;`, ` async function save(d) {
const list = d.files.filter(audio);
if (!list.length || !downloadsAllowed()) return;`);
save();
// ── You: the switch ──
load('src/mobile/screens/You.svelte');
rep(`<div class="sheet-sec">Downloads</div>
<div class="group">`, `<div class="sheet-sec">Downloads</div>
<div class="group">
<button class="row" onclick={() => setSetting("wifiOnly", !settings.wifiOnly)}>
<span class="lead"><Icon name="globe" size={20} /></span>
<span class="b"><span class="t">Downloads on Wi-Fi only</span><span class="m">on mobile data, Save waits; streaming is never held back</span></span>
<span class="sw" class:on={settings.wifiOnly}><span></span></span>
</button>`);
save();
// ── the harness handle ──
load('src/mobile/Mobile.svelte');
rep(` import { bindShare } from "./share.svelte.js";`, ` import { bindShare } from "./share.svelte.js";
import { downloadsAllowed, cellular } from "./network.svelte.js";`);
rep(`sources, api, transfers, pls, notice, importer, next,`, `sources, api, transfers, pls, notice, importer, wifi: { downloadsAllowed, cellular }, next,`);
save();
// ── the walk: the switch on, the connection made cellular, a download refused ──
load('tests/mobile/smoke.mjs');
rep(` navBadges: [].map.call(document.querySelectorAll('.nav .nb'), function (b) { return b.textContent.trim(); }).join('|'),`,
` navBadges: [].map.call(document.querySelectorAll('.nav .nb'), function (b) { return b.textContent.trim(); }).join('|'),
wifiOnly: (function () { var r = [].slice.call(document.querySelectorAll('.screen .row')).find(function (x) { return /Wi-Fi only/.test(x.textContent); }); return r ? (r.querySelector('.sw.on') ? 'on' : 'off') : ''; })(),`);
rep(` { do: \`__click('.screen .row', 'Clear play history')\`, name: "history-confirm", wait: 600 },`,
` /* downloads on Wi-Fi only: the switch on, the connection made cellular, a download refused; then off */
{ do: \`__click('.screen .row', 'Wi-Fi only')\`, name: "wifi-on", wait: 400 },
{ do: \`(function () { try { Object.defineProperty(navigator, 'connection', { value: { type: 'cellular' }, configurable: true }); } catch (e) {} return __ss.wifi.downloadsAllowed(); })()\`, name: "wifi-refused", wait: 400 },
{ do: \`__click('.toast:not(.notice)', null)\`, wait: 300 },
{ do: \`__click('.screen .row', 'Wi-Fi only')\`, name: "wifi-off", wait: 400 },
{ do: \`__click('.screen .row', 'Clear play history')\`, name: "history-confirm", wait: 600 },`);
rep(` "history-confirm": (i) => i.half.includes("up") && /Clear the play history/.test(i.halfText),`,
` "wifi-on": (i) => i.wifiOnly === "on",
"wifi-refused": (i) => /Wi-Fi/.test(i.toast),
"wifi-off": (i) => i.wifiOnly === "off" && !i.toast,
"history-confirm": (i) => i.half.includes("up") && /Clear the play history/.test(i.halfText),`);
save();
// ── the doc ──
load('ANDROID.md');
rep(`The nav wears two badges the desktop's chrome has:`, `One switch the desktop never needed: You → Downloads → "Downloads on
Wi-Fi only" (\`network.svelte.js\`, off by default) holds every Save — a
record, a track, a folder, a file, a playlist's bulk, the now-playing
Save — while the phone is on mobile data (\`navigator.connection.type\`);
streaming is never held back. The nav wears two badges the desktop's chrome has:`);
save();
console.log('round nineteen wired');