From 5f421883a8aa92338bee1399532f359c5e986f41 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 12 Feb 2026 07:16:30 -0600 Subject: chore: style loading screen --- packages/desktop/src/index.tsx | 13 +--- packages/desktop/src/loading.tsx | 136 +++++++++++++++++++++------------------ packages/desktop/src/styles.css | 10 --- 3 files changed, 74 insertions(+), 85 deletions(-) (limited to 'packages/desktop/src') diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx index ca603da5f..620914dd7 100644 --- a/packages/desktop/src/index.tsx +++ b/packages/desktop/src/index.tsx @@ -1,14 +1,7 @@ // @refresh reload import { webviewZoom } from "./webview-zoom" import { render } from "solid-js/web" -import { - AppBaseProviders, - AppInterface, - PlatformProvider, - Platform, - DisplayBackend, - useCommand, -} from "@opencode-ai/app" +import { AppBaseProviders, AppInterface, PlatformProvider, Platform, useCommand } from "@opencode-ai/app" import { open, save } from "@tauri-apps/plugin-dialog" import { getCurrent, onOpenUrl } from "@tauri-apps/plugin-deep-link" import { openPath as openerOpenPath } from "@tauri-apps/plugin-opener" @@ -29,7 +22,7 @@ import { UPDATER_ENABLED } from "./updater" import { initI18n, t } from "./i18n" import pkg from "../package.json" import "./styles.css" -import { commands, InitStep, type WslConfig } from "./bindings" +import { commands, InitStep } from "./bindings" import { Channel } from "@tauri-apps/api/core" import { createMenu } from "./menu" @@ -487,11 +480,9 @@ type ServerReadyData = { url: string; password: string | null } // Gate component that waits for the server to be ready function ServerGate(props: { children: (data: Accessor) => JSX.Element }) { const [serverData] = createResource(() => commands.awaitInitialization(new Channel() as any)) - if (serverData.state === "errored") throw serverData.error return ( - // Not using suspense as not all components are compatible with it (undefined refs) { - let splash!: SVGSVGElement - const [state, setState] = createSignal(null) + const [step, setStep] = createSignal(null) + const [line, setLine] = createSignal(0) + const [percent, setPercent] = createSignal(0) + + const phase = createMemo(() => step()?.phase) + + const value = createMemo(() => { + if (phase() === "done") return 100 + return Math.max(25, Math.min(100, percent())) + }) const channel = new Channel() - channel.onmessage = (e) => setState(e) - commands.awaitInitialization(channel as any).then(() => { - const currentOpacity = getComputedStyle(splash).opacity - - splash.style.animation = "none" - splash.style.animationPlayState = "paused" - splash.style.opacity = currentOpacity - - requestAnimationFrame(() => { - splash.style.transition = "opacity 0.3s ease" - requestAnimationFrame(() => { - splash.style.opacity = "1" + channel.onmessage = (next) => setStep(next) + commands.awaitInitialization(channel as any).catch(() => undefined) + + createEffect(() => { + if (phase() !== "sqlite_waiting") return + + setLine(0) + setPercent(0) + + const timers = delays.map((ms, i) => setTimeout(() => setLine(i + 1), ms)) + + let stop: (() => void) | undefined + let active = true + + void events.sqliteMigrationProgress + .listen((e) => { + if (e.payload.type === "InProgress") setPercent(Math.max(0, Math.min(100, e.payload.value))) + if (e.payload.type === "Done") setPercent(100) }) + .then((unlisten) => { + if (active) { + stop = unlisten + return + } + + unlisten() + }) + .catch(() => undefined) + + onCleanup(() => { + active = false + timers.forEach(clearTimeout) + stop?.() }) }) + createEffect(() => { + if (phase() !== "done") return + + const timer = setTimeout(() => events.loadingWindowComplete.emit(null), 1000) + onCleanup(() => clearTimeout(timer)) + }) + + const status = createMemo(() => { + if (phase() === "done") return "All done" + if (phase() === "sqlite_waiting") return lines[line()] + return "Just a moment..." + }) + return (
-
- - - - - {(_) => { - onMount(() => { - setTimeout(() => events.loadingWindowComplete.emit(null), 1000) - }) - - return "All done" - }} - - - {(_) => { - const textItems = [ - "Just a moment...", - "Migrating your database", - "This could take a couple of minutes", - ] - const [textIndex, setTextIndex] = createSignal(0) - const [progress, setProgress] = createSignal(0) - - onMount(async () => { - const listener = events.sqliteMigrationProgress.listen((e) => { - if (e.payload.type === "InProgress") setProgress(e.payload.value) - }) - onCleanup(() => listener.then((c) => c())) - - await new Promise((res) => setTimeout(res, 3000)) - setTextIndex(1) - await new Promise((res) => setTimeout(res, 6000)) - setTextIndex(2) - }) - - return ( -
- {textItems[textIndex()]} - Progress: {progress()}% -
-
-
-
- ) - }} - - - +
+ +
+ + {status()} + + `${Math.round(value)}%`} + /> +
diff --git a/packages/desktop/src/styles.css b/packages/desktop/src/styles.css index 941fb95d7..143a21312 100644 --- a/packages/desktop/src/styles.css +++ b/packages/desktop/src/styles.css @@ -5,13 +5,3 @@ button#decorum-tb-close, div[data-tauri-decorum-tb] { height: calc(var(--spacing) * 10) !important; } - -@keyframes pulse-splash { - 0%, - 100% { - opacity: 0.1; - } - 50% { - opacity: 0.3; - } -} -- cgit v1.2.3