// 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}
{/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');