setup: the installer is our own window — the alpha key is the gate, the release comes down with it and is verified before the silent install, and the in-app tour asks for the key too
This commit is contained in:
1 parent
8093835482
commit
f8508da081
17 files changed
+1960
-13
No files matched your search
@@ -27,6 +27,7 @@
|
||||
|
||||
const STEPS = [
|
||||
{ id: "welcome", label: "Welcome", icon: "sparkle" },
|
||||
{ id: "alpha", label: "Alpha key", icon: "key" },
|
||||
{ id: "library", label: "Your library", icon: "library" },
|
||||
{ id: "soulseek", label: "Soulseek", icon: "users" },
|
||||
{ id: "community", label: "Community", icon: "globe" },
|
||||
@@ -53,6 +54,10 @@
|
||||
let displayName = $state("");
|
||||
let glass = $state(false);
|
||||
let loudness = $state(true);
|
||||
// The closed alpha's read-only release key (updater.rs): typed here,
|
||||
// kept by the backend in the Credential Manager, never read back.
|
||||
let alphaKey = $state("");
|
||||
let hasToken = $state(false);
|
||||
let busy = $state(false);
|
||||
let error = $state("");
|
||||
let closing = $state(false);
|
||||
@@ -90,6 +95,11 @@
|
||||
} catch {
|
||||
freenetOn = false;
|
||||
}
|
||||
try {
|
||||
hasToken = !!(await api.updaterStatus()).has_token;
|
||||
} catch {
|
||||
hasToken = false;
|
||||
}
|
||||
await tick();
|
||||
panelEl?.querySelector(".primary")?.focus();
|
||||
}
|
||||
@@ -132,7 +142,25 @@
|
||||
|
||||
async function next() {
|
||||
if (busy || closing) return;
|
||||
if (cur.id === "library") {
|
||||
if (cur.id === "alpha") {
|
||||
const k = alphaKey.trim();
|
||||
if (k) {
|
||||
busy = true;
|
||||
error = "";
|
||||
try {
|
||||
await api.updaterSet({ token: k });
|
||||
hasToken = true;
|
||||
alphaKey = "";
|
||||
// The first check can start now; the toast reports it.
|
||||
void api.updaterCheck().catch(() => {});
|
||||
} catch (e) {
|
||||
error = String(e);
|
||||
} finally {
|
||||
busy = false;
|
||||
}
|
||||
if (error) return;
|
||||
}
|
||||
} else if (cur.id === "library") {
|
||||
const patch = {};
|
||||
if (libraryDir && libraryDir !== settings?.download_dir) patch.downloadDir = libraryDir;
|
||||
const lay = layout.trim();
|
||||
@@ -274,11 +302,28 @@
|
||||
that runs on a peer you own. Four short questions and the app is yours.
|
||||
</p>
|
||||
<ul class="pills" in:fly={{ y: 10, duration: dur(520), delay: dur(460), easing: quintOut }}>
|
||||
{#each STEPS.slice(1, 5) as s (s.id)}
|
||||
{#each STEPS.slice(1, 6) as s (s.id)}
|
||||
<li><Icon name={s.icon} size={13} /> {s.label}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
{:else if cur.id === "alpha"}
|
||||
<h1 id="fr-title">Your alpha key</h1>
|
||||
<p class="lede">
|
||||
SoulStream is in a closed alpha. New builds come from a private repository, and
|
||||
this key — one per tester, able only to read them — is how your copy finds
|
||||
updates. It goes to the Windows Credential Manager, not a plain file. Without it
|
||||
the app runs, but cannot update itself.
|
||||
</p>
|
||||
<div class="card">
|
||||
<div class="row">
|
||||
<div class="label">
|
||||
<div class="name">Alpha key {#if hasToken}<span class="tag ok">set</span>{/if}</div>
|
||||
<div class="hint">{hasToken ? "A key is saved on this computer. Paste another to replace it, or press Next to keep it." : "Paste the key you were given. It starts with github_pat_."}</div>
|
||||
</div>
|
||||
<div class="ctl"><input type="password" class="mono" bind:value={alphaKey} placeholder={hasToken ? "••••••••••••" : "github_pat_…"} spellcheck="false" autocomplete="off" aria-label="Alpha key" /></div>
|
||||
</div>
|
||||
</div>
|
||||
{:else if cur.id === "library"}
|
||||
<h1 id="fr-title">Where does your music live?</h1>
|
||||
<p class="lede">
|
||||
@@ -400,6 +445,7 @@
|
||||
<p class="lede">Here is what you chose. Every line of it lives in Settings.</p>
|
||||
<ul class="summary">
|
||||
{#each [
|
||||
["key", "Alpha key", hasToken ? "set" : "not set — updates need it"],
|
||||
["folder-open", "Library", libraryDir || "not chosen"],
|
||||
["users", "Soulseek", online ? `signed in as ${app.username}` : "not signed in yet"],
|
||||
["globe", "Community peer", freenetOn ? (displayName.trim() ? `on · ${displayName.trim()}` : "on") : "off"],
|
||||
@@ -430,7 +476,7 @@
|
||||
{:else if cur.id === "ready"}
|
||||
<button class="ax-fill primary big" onclick={finish} disabled={closing}>Open SoulStream</button>
|
||||
{:else}
|
||||
{#if cur.id === "soulseek" && !online}
|
||||
{#if (cur.id === "soulseek" && !online) || (cur.id === "alpha" && !hasToken && !alphaKey.trim())}
|
||||
<button class="lnk" onclick={next} disabled={busy}>Later</button>
|
||||
{/if}
|
||||
<button class="ax-fill primary" onclick={next} disabled={busy || closing}>{busy ? "Saving…" : "Next"} <Icon name="chevron-right" size={14} /></button>
|
||||
|
||||
Reference in new issue
Block a user