diff --git a/app/src/components/updater.tsx b/app/src/components/updater.tsx new file mode 100644 index 00000000..126b8e68 --- /dev/null +++ b/app/src/components/updater.tsx @@ -0,0 +1,142 @@ +import { createSignal, onMount, Show } from "solid-js"; +import * as Tauri from "../tauri/constants"; +import Tooltip from "./tooltip"; + +const module = Tauri.DESKTOP ? await import("../tauri/update") : undefined; + +type Status = + | { + type: "available"; + version: string; + } + | { + type: "downloading"; + version: string; + size?: number; + progress: number; + } + | { + type: "downloaded"; + version: string; + size: number; + } + | { + type: "installing"; + version: string; + } + | { + type: "error"; + error: string; + }; + +export default function UpdaterIcon() { + const [status, setStatus] = createSignal(); + + onMount(async () => { + // Import the update module + const updater = (await module)?.update; + if (!updater) return; + + // Subscribe to status changes + const dispose = updater.status.subscribe((newStatus) => { + setStatus(newStatus); + }); + + return () => dispose(); + }); + + const handleClick = async () => { + const s = status(); + if (!s) return; + + const module = await import("../tauri/update"); + + if (s.type === "available") { + module.update.download(); + } else if (s.type === "downloaded") { + module.update.install(); + } + }; + + const tooltipContent = () => { + const s = status(); + if (!s) return ""; + + if (s.type === "error") return `Error: ${s.error}`; + if (s.type === "available") return `Update ${s.version} available`; + if (s.type === "downloading") return `Downloading ${s.version}...`; + if (s.type === "downloaded") return `Install ${s.version} now`; + if (s.type === "installing") return `Installing ${s.version}...`; + return ""; + }; + + const progressPercent = () => { + const s = status(); + if (!s || s.type !== "downloading" || !s.size) return 0; + return (s.progress / s.size) * 100; + }; + + return ( + + + + + + ); +} diff --git a/app/src/index.tsx b/app/src/index.tsx index 154b2c7d..d26e3f19 100644 --- a/app/src/index.tsx +++ b/app/src/index.tsx @@ -3,8 +3,9 @@ import "@kixelated/hang/support/element"; import * as Tauri from "./tauri"; -if (Tauri.ENABLED && Tauri.DESKTOP) { - import("./tauri/update").then((module) => module.run()); +// Import update module early if on desktop to ensure it runs even if UI breaks +if (Tauri.DESKTOP) { + import("./tauri/update"); } import solid from "@kixelated/signals/solid"; diff --git a/app/src/layout/web.tsx b/app/src/layout/web.tsx index 05485cd0..e323d178 100644 --- a/app/src/layout/web.tsx +++ b/app/src/layout/web.tsx @@ -1,6 +1,7 @@ -import { type JSX, Show } from "solid-js"; +import { type JSX, Match, Switch } from "solid-js"; import Divider from "../components/divider"; import Tooltip from "../components/tooltip"; +import UpdaterIcon from "../components/updater"; import * as Tauri from "../tauri"; import { Logo } from "./logo"; @@ -11,16 +12,21 @@ export default function Web(props: { children: JSX.Element; link?: string }) {