diff --git a/packages/tui/src/routes/home.tsx b/packages/tui/src/routes/home.tsx index 672e4e954cc..0712eacd2fb 100644 --- a/packages/tui/src/routes/home.tsx +++ b/packages/tui/src/routes/home.tsx @@ -1,5 +1,5 @@ import { Prompt, type PromptRef } from "../component/prompt" -import { createEffect, createMemo, createSignal, Match, onMount, Show, Switch, untrack } from "solid-js" +import { createEffect, createMemo, createSignal, onMount, Show, untrack } from "solid-js" import { Logo } from "../component/logo" import { useArgs } from "../context/args" import { useRouteData } from "../context/route" @@ -11,11 +11,10 @@ import { useLocation } from "../context/location" import { FormPrompt } from "./session/form" import { Slot } from "../plugin/render" import { useTerminalDimensions } from "@opentui/solid" -import { TextAttributes, type RGBA } from "@opentui/core" import { useTheme } from "../context/theme" import { useUpdateNotification } from "../context/update-notification" +import { useExit } from "../context/exit" import { FadeInText } from "../component/fade-in-text" -import { stringWidth } from "../util/string-width" let once = false const placeholder = { @@ -33,6 +32,7 @@ export function Home() { const data = useData() const location = useLocation() const dimensions = useTerminalDimensions() + const [logoWidth, setLogoWidth] = createSignal(0) // Global MCP elicitations can arrive without a session route, so keep them reachable from Home. const currentLocation = () => route.location ?? data.location.default() const forms = createMemo(() => data.session.form.list("global", currentLocation()) ?? []) @@ -87,15 +87,18 @@ export function Home() { > - + - + + 0} /> - - - @@ -118,87 +121,55 @@ export function Home() { ) } -function UpdateNotification() { +function UpdateNotification(props: { width: number }) { const update = useUpdateNotification() + const exit = useExit() const theme = useTheme() - const remoteMessage = "A remote server cannot be updated from here. Updating it is recommended." - const [hovered, setHovered] = createSignal<"primary" | "close">() + const [hovered, setHovered] = createSignal(false) + const backdrop = () => (hovered() ? theme.background.action.primary.hovered : theme.background.default) createEffect(() => { update.notification() - setHovered(undefined) + setHovered(false) }) return ( - {(state) => ( - - - - setHovered("primary")} - onMouseOut={() => setHovered(undefined)} - onMouseUp={() => update.open?.("notification")} - > - - - - - - - setHovered("close")} - onMouseOut={() => setHovered(undefined)} - onMouseUp={update.dismiss} - > - Close - - - - - - )} + {(state) => { + const remote = state.source === "server" && state.remote + return ( + + setHovered(true)} + onMouseOut={() => setHovered(false)} + onMouseUp={() => { + if (remote) return update.dismiss() + if (state.type === "installed") return exit() + update.open?.("notification") + }} + > + + + + {state.type === "installed" ? "/exit" : "/update"} + + + {remote + ? "remote server update available" + : state.type === "installed" + ? ` restart to use v${state.version}` + : ` to install v${state.version}`} + + + + ) + }} ) } - -function UpdateMessage(props: { title: string; description: string; backdrop: RGBA }) { - const theme = useTheme() - const titleWidth = stringWidth(props.title) - const descriptionWidth = stringWidth(props.description) - const width = Math.max(titleWidth, descriptionWidth) - return ( - - - {" ".repeat(Math.floor((width - titleWidth) / 2))} - {props.title} - - {"\n"} - - {" ".repeat(Math.floor((width - descriptionWidth) / 2))} - {props.description} - - - ) -}