From b7ad8e459cae11ca74d976f6bd2e02559912716a Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Fri, 6 Feb 2026 23:03:07 +0800 Subject: desktop: add loading window and restructure rust (#12176) --- packages/desktop/src/bindings.ts | 32 +++++++++++++++-- packages/desktop/src/entry.tsx | 5 +++ packages/desktop/src/index.tsx | 6 ++-- packages/desktop/src/loading.tsx | 77 ++++++++++++++++++++++++++++++++++++++++ packages/desktop/src/styles.css | 10 ++++++ 5 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 packages/desktop/src/entry.tsx create mode 100644 packages/desktop/src/loading.tsx (limited to 'packages/desktop/src') diff --git a/packages/desktop/src/bindings.ts b/packages/desktop/src/bindings.ts index 64d0c113d..46dcb7f44 100644 --- a/packages/desktop/src/bindings.ts +++ b/packages/desktop/src/bindings.ts @@ -1,20 +1,48 @@ // This file has been generated by Tauri Specta. Do not edit this file manually. -import { invoke as __TAURI_INVOKE } from "@tauri-apps/api/core" +import { invoke as __TAURI_INVOKE, Channel } from '@tauri-apps/api/core'; +import * as __TAURI_EVENT from "@tauri-apps/api/event"; /** Commands */ export const commands = { killSidecar: () => __TAURI_INVOKE("kill_sidecar"), installCli: () => __TAURI_INVOKE("install_cli"), - ensureServerReady: () => __TAURI_INVOKE("ensure_server_ready"), + awaitInitialization: (events: Channel) => __TAURI_INVOKE("await_initialization", { events }), + getDefaultServerUrl: () => __TAURI_INVOKE("get_default_server_url"), setDefaultServerUrl: (url: string | null) => __TAURI_INVOKE("set_default_server_url", { url }), parseMarkdownCommand: (markdown: string) => __TAURI_INVOKE("parse_markdown_command", { markdown }), }; +/** Events */ +export const events = { + loadingWindowComplete: makeEvent("loading-window-complete"), +}; + /* Types */ +export type InitStep = { phase: "server_waiting" } | { phase: "sqlite_waiting" } | { phase: "done" }; + +export type LoadingWindowComplete = null; + export type ServerReadyData = { url: string, password: string | null, }; +/* Tauri Specta runtime */ +function makeEvent(name: string) { + const base = { + listen: (cb: __TAURI_EVENT.EventCallback) => __TAURI_EVENT.listen(name, cb), + once: (cb: __TAURI_EVENT.EventCallback) => __TAURI_EVENT.once(name, cb), + emit: (payload: T) => __TAURI_EVENT.emit(name, payload) as unknown as (T extends null ? () => Promise : (payload: T) => Promise) + }; + + const fn = (target: import("@tauri-apps/api/webview").Webview | import("@tauri-apps/api/window").Window) => ({ + listen: (cb: __TAURI_EVENT.EventCallback) => target.listen(name, cb), + once: (cb: __TAURI_EVENT.EventCallback) => target.once(name, cb), + emit: (payload: T) => target.emit(name, payload) as unknown as (T extends null ? () => Promise : (payload: T) => Promise) + }); + + return Object.assign(fn, base); +} + diff --git a/packages/desktop/src/entry.tsx b/packages/desktop/src/entry.tsx new file mode 100644 index 000000000..b1c9f13f9 --- /dev/null +++ b/packages/desktop/src/entry.tsx @@ -0,0 +1,5 @@ +if (location.pathname === "/loading") { + import("./loading") +} else { + import("./") +} diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx index 66e86bf52..2b74bbabd 100644 --- a/packages/desktop/src/index.tsx +++ b/packages/desktop/src/index.tsx @@ -21,7 +21,8 @@ import { UPDATER_ENABLED } from "./updater" import { initI18n, t } from "./i18n" import pkg from "../package.json" import "./styles.css" -import { commands } from "./bindings" +import { commands, InitStep } from "./bindings" +import { Channel } from "@tauri-apps/api/core" import { createMenu } from "./menu" const root = document.getElementById("root") @@ -307,7 +308,6 @@ const createPlatform = (password: Accessor): Platform => ({ .catch(() => undefined) }, - // @ts-expect-error fetch: (input, init) => { const pw = password() @@ -400,7 +400,7 @@ 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.ensureServerReady()) + const [serverData] = createResource(() => commands.awaitInitialization(new Channel() as any)) const errorMessage = () => { const error = serverData.error diff --git a/packages/desktop/src/loading.tsx b/packages/desktop/src/loading.tsx new file mode 100644 index 000000000..752cde893 --- /dev/null +++ b/packages/desktop/src/loading.tsx @@ -0,0 +1,77 @@ +import { render } from "solid-js/web" +import { MetaProvider } from "@solidjs/meta" +import "@opencode-ai/app/index.css" +import { Font } from "@opencode-ai/ui/font" +import { Splash } from "@opencode-ai/ui/logo" +import "./styles.css" +import { createSignal, Match, onMount } from "solid-js" +import { commands, events, InitStep } from "./bindings" +import { Channel } from "@tauri-apps/api/core" +import { Switch } from "solid-js" + +const root = document.getElementById("root")! + +render(() => { + let splash!: SVGSVGElement + const [state, setState] = createSignal(null) + + 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" + }) + }) + }) + + 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) + + onMount(async () => { + await new Promise((res) => setTimeout(res, 3000)) + setTextIndex(1) + await new Promise((res) => setTimeout(res, 6000)) + setTextIndex(2) + }) + + return <>{textItems[textIndex()]} + }} + + + +
+
+
+ ) +}, root) diff --git a/packages/desktop/src/styles.css b/packages/desktop/src/styles.css index 143a21312..941fb95d7 100644 --- a/packages/desktop/src/styles.css +++ b/packages/desktop/src/styles.css @@ -5,3 +5,13 @@ 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