android: a streamed file copied into a folder, the listening port, the dev build's diagnostics
The now-playing sheet's streamed track can be copied into a folder picked on the phone, as the file it is — the cache written out, nothing downloaded again, no library row (copy_stream_to_folder, which the desktop has had a command for and no UI). You → Sharing carries the listening port, what peers dial when they download from you: unset is the client's own 50300, the app asks the router to forward it over UPnP and falls back to the server relaying, and a change applies on the next connect. The dev flavour gets the desktop's debug overlay as a screen under This phone — CPU, memory, the network, the stream and its loudness, what the pre-buffer is fetching, the size of the play history — behind devBuild in util.js, which is Vite's own DEV flag, so the embedded build the phone keeps has no row to tap.
This commit is contained in:
1 parent
1737c5e1b6
commit
aff29aba5c
8 files changed
+272
-2
No files matched your search
@@ -214,6 +214,24 @@
|
||||
: "Nothing to save");
|
||||
} catch (e) { oops(e); }
|
||||
}
|
||||
/* the desktop's copy_stream_to_folder: the cached stream written into a
|
||||
folder picked on this phone, as the file it is — no re-download, no
|
||||
tagging, no library row. Nothing leaves the phone, so the Wi-Fi guard
|
||||
has no say here. A track that has not finished streaming is counted
|
||||
back as missing, never fetched. */
|
||||
async function copyToFolder(entries) {
|
||||
const files = entries.filter((e) => e.t?.stream && e.t.path).map((e) => ({ username: e.t.stream.username, path: e.t.path }));
|
||||
if (!files.length) return;
|
||||
try {
|
||||
const r = await api.pickLibraryFolder();
|
||||
if (!r?.path) { player.error = "That folder has no path the phone can write to — pick one on this phone's storage."; return; }
|
||||
const [saved, missing] = await api.copyStreamToFolder(files, r.path);
|
||||
note(saved ? saved + " file" + (saved === 1 ? "" : "s") + " copied" + (missing ? " · " + missing + " not cached yet" : "")
|
||||
: "Not cached yet — play it through first");
|
||||
} catch (e) {
|
||||
if (!/cancelled/.test(String(e))) oops(e);
|
||||
}
|
||||
}
|
||||
/* a peer's sheet (a raw result's folder, or the browse screen's user) */
|
||||
function playGroup(g) {
|
||||
const es = groupEntries(g, 0);
|
||||
@@ -346,6 +364,7 @@
|
||||
{#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 }])))}
|
||||
<div class="sheet-hair"></div>
|
||||
{/if}
|
||||
{@render row("play", "Play next", "", act(() => playNext([{ t: track, album }])))}
|
||||
@@ -487,7 +506,7 @@
|
||||
{#if a.multiline}
|
||||
<textarea class="field area" bind:value={promptVal} placeholder={a.placeholder || ""} rows="3" use:focusLater></textarea>
|
||||
{:else}
|
||||
<input class="field" bind:value={promptVal} placeholder={a.placeholder || ""} autocomplete="off" spellcheck="false" enterkeyhint="done" onkeydown={(e) => { if (e.key === "Enter") submitPrompt(); }} use:focusLater />
|
||||
<input class="field" bind:value={promptVal} placeholder={a.placeholder || ""} autocomplete="off" spellcheck="false" inputmode={a.numeric ? "numeric" : undefined} enterkeyhint="done" onkeydown={(e) => { if (e.key === "Enter") submitPrompt(); }} use:focusLater />
|
||||
{/if}
|
||||
<div class="prompt-acts">
|
||||
<button class="btn btn-ghost" onclick={closeHalf}>Cancel</button>
|
||||
|
||||
Reference in new issue
Block a user