first run, updates, installer: a setup tour stands in front of a fresh install, releases arrive through an in-app updater with stable and nightly channels behind a read-only token, and the branded installer builds again

This commit is contained in:
KeelrLeek committed 2026-09-09 16:16:19 -05:00
1 parent 07810f7543
commit cd2391198e
19 files changed
+2010 -15

No files matched your search

+24 -3
View File
@@ -7,6 +7,10 @@
import LyricsSyncEditor from "./components/LyricsSyncEditor.svelte";
import ImportWindow from "./components/ImportWindow.svelte";
import LoginModal from "./components/LoginModal.svelte";
import FirstRun from "./components/FirstRun.svelte";
import { firstRun } from "./lib/firstRun.svelte.js";
import UpdateToast from "./components/UpdateToast.svelte";
import { startUpdaterWatch } from "./lib/updater.svelte.js";
import PreviewOverlay from "./components/PreviewOverlay.svelte";
import DebugOverlay from "./components/DebugOverlay.svelte";
import GlassBar from "./components/GlassBar.svelte";
@@ -128,7 +132,13 @@
// Dark-glass mode is persisted in config; the window boots solid and
// glasses up as soon as the setting arrives (no-op when off).
void getSettings()
.then((s) => s?.glass_mode && applyGlass(true))
.then((s) => {
if (s?.glass_mode) applyGlass(true);
// A fresh install (no setup_done in its config) meets the
// first-run tour before anything else; FirstRun.svelte stamps
// the flag when it is finished or skipped.
if (s && !s.setup_done) firstRun.open = true;
})
.catch(() => {});
// Windows drops the acrylic blur for the length of a live resize and the
// window stays transparent through it, so the desktop punches through
@@ -136,6 +146,9 @@
// armGlassResizeGuard. Armed unconditionally: the CSS gates on .glass, and
// this way the mode can be toggled mid-drag without leaving stale state.
armGlassResizeGuard();
// The updater's status and finds arrive as events; the backend checks
// on its own schedule and never installs without the button.
startUpdaterWatch();
autoConnect();
// Sealed cargo arrives on the inbox check, and that has to keep happening
// wherever the user is — not only while the Community page is mounted.
@@ -157,6 +170,7 @@
class:player-expanded={ui.playerExpanded}
class:np-dragging={ui.nowPlayingDragging}
class:preview-open={previewUi.open}
class:setup-open={firstRun.open}
style="--np-open-width: {ui.nowPlayingWidth}px"
>
<TitleBar />
@@ -175,7 +189,7 @@
would be masked with it; the per-frame page-mask this replaces
never tracked cleanly). The inner div KEEPS the .content class:
every page resolves its scroll pane via closest(".content"). -->
<main class="pane-shell" class:barless={!BAR_VIEWS.has(ui.view)} inert={previewUi.open || undefined}>
<main class="pane-shell" class:barless={!BAR_VIEWS.has(ui.view)} inert={previewUi.open || firstRun.open || undefined}>
<GlassBar hidden={!BAR_VIEWS.has(ui.view)} />
<div class="content" use:floatScroll>
<CurrentView />
@@ -189,6 +203,7 @@
<UploadToast />
<ProposalToast />
<FollowNewsToast />
<UpdateToast />
<WhoHasSheet />
<SetlistScanChip />
<PreviewOverlay />
@@ -196,6 +211,9 @@
<ArtworkViewer />
<ImportWindow />
<LoginModal />
<!-- Above the login modal: the tour has its own sign-in step, and a
failed auto-connect at boot must not raise the modal over it. -->
<FirstRun />
<DebugOverlay />
</div>
@@ -208,7 +226,10 @@
visible (dimmed under the scrim) but cannot command main audio. */
.app.preview-open :global(.sidebar),
.app.preview-open :global(.nowplaying),
.app.preview-open :global(.player) {
.app.preview-open :global(.player),
.app.setup-open :global(.sidebar),
.app.setup-open :global(.nowplaying),
.app.setup-open :global(.player) {
pointer-events: none;
}