// Round twenty-six: the odds and ends. A cached stream copied out into a // folder picked on the phone (the desktop has the command and no UI for it), // the Soulseek listening port in You → Sharing (the desktop never exposed it // at all), and the desktop's debug overlay as a screen behind a new dev-build // gate. community_pick_file is deliberately not here: it is the avatar / // recovery-artifact dialog, and the backend has no chat file-send at all. const fs = require('fs'); const root = process.env.SS_ROOT || 'F:/Coding/SoulStream/'; const scratch = 'C:/Users/Kyle/AppData/Local/Temp/claude/F--Coding-SoulStream/5488514a-11e8-482a-b0a0-20cb511ee110/scratchpad/'; const ins = (name) => fs.readFileSync(scratch + name, 'utf8').replace(/\s+$/, ''); 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); // ── the dev gate: Vite's own DEV flag, plus the mock walk saying so ── load('src/mobile/util.js'); // an append has no anchor to be ambiguous, so it guards itself: a re-run // after a throw further down must not export devBuild twice if (s.includes('export const devBuild')) throw new Error('src/mobile/util.js already exports devBuild — round 26 has already run against this tree'); s = s.replace(/\s*$/, NL) + ` /** The dev flavour, and nothing else. That build is the one that loads from * the Vite dev server over the cable (ANDROID.md, "Iterating without * cargo"), so Vite's own DEV flag IS the flavour; the embedded build the * phone keeps is compiled and reads false. The mock walk builds for * production too, so it says who it is through the key the harness sets. */ export const devBuild = (() => { if (import.meta.env.DEV) return true; try { return localStorage.getItem("mockLibrary") === "1"; } catch { return false; } })(); `; save(); // ── the sheet: a cached stream copied into a folder on this phone ── load('src/mobile/HalfSheet.svelte'); rep(` /* a peer's sheet (a raw result's folder, or the browse screen's user) */`, ins('ins-r26-halfsheet-copy.txt') + NL + ` /* a peer's sheet (a raw result's folder, or the browse screen's user) */`); rep(` {#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}`, ` {#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} {@render row("copy", "Copy to a folder…", "the streamed file as it is, into a folder on this phone", act(() => copyToFolder([{ t: track, album }])))}`); // a prompt that asks for a number gets the numeric keypad; Svelte drops an // attribute whose value is undefined, so every other prompt is unchanged rep(` { if (e.key === "Enter") submitPrompt(); }} use:focusLater />`, ` { if (e.key === "Enter") submitPrompt(); }} use:focusLater />`); save(); // ── You: the listening port, and the dev flavour's door to Diagnostics ── load('src/mobile/screens/You.svelte'); rep(` import { refreshSourcePrefs } from "../../lib/sources.js";`, ` import { refreshSourcePrefs } from "../../lib/sources.js"; import { devBuild } from "../util.js";`); rep(` async function refetchCovers() {`, ins('ins-r26-you-port.txt') + NL + ` async function refetchCovers() {`); rep(`