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:
KeelrLeek committed 2026-09-13 23:59:47 -05:00
1 parent 1737c5e1b6
commit aff29aba5c
8 files changed
+272 -2

No files matched your search

+33
View File
@@ -10,6 +10,7 @@
import { player } from "../player.svelte.js";
import { settings, setSetting } from "../prefs.svelte.js";
import { refreshSourcePrefs } from "../../lib/sources.js";
import { devBuild } from "../util.js";
let cfg = $state(null);
let scanning = $state(false);
@@ -130,6 +131,25 @@
}
}
const removeShared = (folder) => saveCfg({ sharedFolders: (cfg?.shared_folders ?? []).filter((f) => f !== folder) });
/* the Soulseek listener: the port other peers dial when they download
from you. Unset means the client's own 50300, read at connect — bind
walks forward a few ports if it is taken. `set_settings` only assigns
a port that is Some, so a number typed here can be changed but never
taken back to unset. */
const DEFAULT_LISTEN_PORT = 50300;
function portPrompt() {
openHalf("prompt", {
title: "Listening port",
value: cfg?.listen_port != null ? String(cfg.listen_port) : "",
placeholder: String(DEFAULT_LISTEN_PORT),
ok: "Save", numeric: true,
onsubmit: (v) => {
const n = Number(v);
if (!Number.isInteger(n) || n < 1024 || n > 65535) { player.error = "A port is a number between 1024 and 65535."; return; }
void saveCfg({ listenPort: n });
},
});
}
async function refetchCovers() {
if (refetching) return;
refetching = true;
@@ -265,6 +285,7 @@
</div>
<div class="sheet-sec">Sharing</div>
<div class="sec-note">What other people can take from you, and how they reach you. Your library folder is always shared; the listening port is what peers dial when they download from you — the app asks the router to forward it over UPnP and falls back to the server relaying the connection when the router will not. On mobile data the carrier's NAT blocks incoming connections whatever the port is, and a change applies on the next connect.</div>
<div class="group">
<div class="kv"><span class="k">Your library folder</span><span class="v dim">always shared · {(cfg?.share_files ?? 0).toLocaleString()} files</span></div>
<div class="row slots">
@@ -272,6 +293,11 @@
<span class="b"><span class="t">Upload slots</span><span class="m">how many peers can download from you at once</span></span>
<span class="stepper"><button class="iconbtn sm" onclick={() => setSlots((cfg?.upload_slots ?? 2) - 1)} aria-label="Fewer slots"><Icon name="minus" size={16} /></button><span class="n">{cfg?.upload_slots ?? 2}</span><button class="iconbtn sm" onclick={() => setSlots((cfg?.upload_slots ?? 2) + 1)} aria-label="More slots"><Icon name="plus" size={16} /></button></span>
</div>
<button class="row" onclick={portPrompt}>
<span class="lead"><Icon name="hash" size={20} /></span>
<span class="b"><span class="t">Listening port</span><span class="m">{cfg?.listen_port ?? DEFAULT_LISTEN_PORT}{cfg?.listen_port == null ? " (the default)" : ""} · what peers dial to download from you</span></span>
<span class="r"><Icon name="chevron-right" size={17} /></span>
</button>
{#each cfg?.shared_folders ?? [] as folder (folder)}
<div class="row">
<span class="lead"><Icon name="folder" size={20} /></span>
@@ -328,6 +354,13 @@
<div class="group">
<div class="kv"><span class="k">SoulStream</span><span class="v">{lib.version || "—"}</span></div>
<div class="kv"><span class="k">Soulseek</span><span class="v dim">{lib.username || "not signed in"}</span></div>
{#if devBuild}
<button class="row" onclick={() => push("diag", {})}>
<span class="lead"><Icon name="devices" size={20} /></span>
<span class="b"><span class="t">Diagnostics</span><span class="m">the desktop's debug overlay — this process, the network, the stream and what is pre-buffering</span></span>
<span class="r"><Icon name="chevron-right" size={17} /></span>
</button>
{/if}
</div>