android: the first run — a folder to keep music in, and an account to reach the network
Nobody had seen this app on a phone that has just installed it. On Android the library root is never missing — config.rs falls back to the app's own sandbox, a real folder nothing else can see — so "no folder yet" cannot be a null check, and setup_done has never been written by the phone, so every phone in existence reads as unstamped, Kyle's included. The tour therefore opens on three clauses, not one: no flag, no saved account, and no records, read only after the library and the credentials have both answered. Two cards, skippable, and no password anywhere in it — the Soulseek step goes to the card on Community and stops. Every screen that is empty because of those two things now says so with the row that fixes it: Home (whose copy predated the folder picker), Library → Albums, Library → Artists, which had no empty state at all, and Search, where a flat sentence about signing in became the row that does it. A row goes away because the config moved, so the two doors onto the same folder tell each other — You re-reads when the tour moves it, the tour's store is told when You's own picker does — and the all-files row re-reads the grant when the system screen hands the app back, the way You already did. You → This phone opens the tour again as a preview that reads the config and writes nothing, which is the door the phone walk drives on Kyle's own device. The mock can answer as a fresh install now — an empty database, no account, no permission, the sandbox root — so the whole thing is walked end to end, and two commands that had no mock at all (player_control, open_external) got one on the way past. It is the mock walk's first reload, which turned up two things a reload does not clear by itself: the player writes the session back on pagehide, so the fresh block clears it from a pagehide listener of its own, and the viewport emulation lives on the DevTools session, so the harness hands it back after the re-attach.
This commit is contained in:
1 parent
46cf6a98fe
commit
95c2bfeeba
13 files changed
+633
-14
No files matched your search
@@ -21,6 +21,7 @@
|
||||
import { art, wantArt } from "./art.svelte.js";
|
||||
import { metaOf, display, realName, setMeta, clearMeta } from "./contacts.svelte.js";
|
||||
import { downloadsAllowed } from "./network.svelte.js";
|
||||
import { setup, needsFolder, needsAccount, chooseFolder, requestAccess, finishSetup } from "./setup.svelte.js";
|
||||
import { note } from "./notice.svelte.js";
|
||||
import { fmtOf, albumFmt, fmtBytes, basename, dirname, longDur, mmss, titleFromName } from "./util.js";
|
||||
|
||||
@@ -778,6 +779,39 @@
|
||||
{/each}
|
||||
</div>
|
||||
<div style="padding: 6px var(--pad) 16px"><button class="btn btn-ghost wide" onclick={act(() => { leaveRoom(shown.arg.name).catch(() => {}); back(); })}>Leave #{shown.arg.name}</button></div>
|
||||
{:else if kind === "setup"}
|
||||
<!-- the first run: one sheet, two cards, and a foot that closes
|
||||
it. Every row here is a row that exists somewhere else —
|
||||
the folder picker is You's, the sign-in is Community's —
|
||||
because the tour's job is to say WHICH two things matter,
|
||||
not to become a third place they can be changed. -->
|
||||
<div class="setup">
|
||||
<div class="sheet-title">{setup.reason === "preview" ? "Set up this phone" : "Welcome to SoulStream"}</div>
|
||||
<div class="sec-note">Your library, the catalog and the network, in one place. Two things make the rest of it work — neither is required now, and both live on a screen you can come back to.</div>
|
||||
|
||||
<div class="sheet-sec">Where your music lives</div>
|
||||
<div class="sec-note">One folder is the library: everything saved or downloaded lands in it, and everything in it is in the library. Until you pick one it is a folder inside the app that nothing else on this phone can see.</div>
|
||||
<div class="setup-path">{setup.folder || "—"}</div>
|
||||
<div class="sheet-rows">
|
||||
{@render row("folder", setup.picking ? "Picking…" : needsFolder() ? "Choose a folder" : "Choose a different folder", needsFolder() ? "somewhere on this phone's own storage" : "this one is yours", () => void chooseFolder())}
|
||||
{#if !needsFolder() && setup.access === false}
|
||||
{@render row("alert", "Allow all files access", "a folder on the phone's storage needs it — the system screen opens, come back after", () => void requestAccess())}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="sheet-sec">Soulseek</div>
|
||||
<div class="sec-note">Anything the library does not hold comes off the network: what Search finds, a song played from someone's copy, Save. The card asks for a username and a password and keeps them on this phone — nothing here does.</div>
|
||||
{#if needsAccount()}
|
||||
<div class="sheet-rows">
|
||||
{@render row("users", "Sign in on Community", "the card is on the Community tab", act(() => go("community")))}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="sheet-info"><div class="kv"><span class="k">Signed in</span><span class="v">{slsk.username || slsk.savedUser}</span></div></div>
|
||||
{/if}
|
||||
|
||||
<div class="setup-foot"><button class="btn btn-fill wide" onclick={() => void finishSetup()}>Start listening</button></div>
|
||||
<div class="sec-note" style="padding-bottom:16px">Nothing above is required. You → Set up this phone again opens it back up.</div>
|
||||
</div>
|
||||
{:else if kind === "sleep"}
|
||||
<div class="sheet-title">Sleep timer</div>
|
||||
<div class="sheet-sec">Pause after</div>
|
||||
|
||||
Reference in new issue
Block a user