pluggable home footer (#20057)

This commit is contained in:
Sebastian
2026-03-30 14:33:01 +02:00
committed by GitHub
parent 8e4bab5181
commit 14f9e21d5c
4 changed files with 99 additions and 58 deletions
@@ -1,15 +1,11 @@
import { Prompt, type PromptRef } from "@tui/component/prompt"
import { createEffect, createMemo, Match, on, onMount, Show, Switch } from "solid-js"
import { useTheme } from "@tui/context/theme"
import { createEffect, on, onMount } from "solid-js"
import { Logo } from "../component/logo"
import { Locale } from "@/util/locale"
import { useSync } from "../context/sync"
import { Toast } from "../ui/toast"
import { useArgs } from "../context/args"
import { useDirectory } from "../context/directory"
import { useRouteData } from "@tui/context/route"
import { usePromptRef } from "../context/prompt"
import { Installation } from "@/installation"
import { useLocal } from "../context/local"
import { TuiPluginRuntime } from "../plugin"
@@ -22,37 +18,8 @@ const placeholder = {
export function Home() {
const sync = useSync()
const { theme } = useTheme()
const route = useRouteData("home")
const promptRef = usePromptRef()
const mcp = createMemo(() => Object.keys(sync.data.mcp).length > 0)
const mcpError = createMemo(() => {
return Object.values(sync.data.mcp).some((x) => x.status === "failed")
})
const connectedMcpCount = createMemo(() => {
return Object.values(sync.data.mcp).filter((x) => x.status === "connected").length
})
const Hint = (
<box flexShrink={0} flexDirection="row" gap={1}>
<Show when={connectedMcpCount() > 0}>
<text fg={theme.text}>
<Switch>
<Match when={mcpError()}>
<span style={{ fg: theme.error }}>•</span> mcp errors{" "}
<span style={{ fg: theme.textMuted }}>ctrl+x s</span>
</Match>
<Match when={true}>
<span style={{ fg: theme.success }}>•</span>{" "}
{Locale.pluralize(connectedMcpCount(), "{} mcp server", "{} mcp servers")}
</Match>
</Switch>
</text>
</Show>
</box>
)
let prompt: PromptRef | undefined
const args = useArgs()
const local = useLocal()
@@ -81,7 +48,6 @@ export function Home() {
},
),
)
const directory = useDirectory()
return (
<>
@@ -101,7 +67,6 @@ export function Home() {
prompt = r
promptRef.set(r)
}}
hint={Hint}
workspaceID={route.workspaceID}
placeholders={placeholder}
/>
@@ -111,28 +76,8 @@ export function Home() {
<box flexGrow={1} minHeight={0} />
<Toast />
</box>
<box paddingTop={1} paddingBottom={1} paddingLeft={2} paddingRight={2} flexDirection="row" flexShrink={0} gap={2}>
<text fg={theme.textMuted}>{directory()}</text>
<box gap={1} flexDirection="row" flexShrink={0}>
<Show when={mcp()}>
<text fg={theme.text}>
<Switch>
<Match when={mcpError()}>
<span style={{ fg: theme.error }}>⊙ </span>
</Match>
<Match when={true}>
<span style={{ fg: connectedMcpCount() > 0 ? theme.success : theme.textMuted }}>⊙ </span>
</Match>
</Switch>
{connectedMcpCount()} MCP
</text>
<text fg={theme.textMuted}>/status</text>
</Show>
</box>
<box flexGrow={1} />
<box flexShrink={0}>
<text fg={theme.textMuted}>{Installation.VERSION}</text>
</box>
<box width="100%" flexShrink={0}>
<TuiPluginRuntime.Slot name="home_footer" mode="single_winner" />
</box>
</>
)