refactor(tui): migrate dialog views to V2 themes (#37516)
This commit is contained in:
parent
bce9c639d1
commit
677526d72e
10 changed files with 86 additions and 81 deletions
|
|
@ -16,7 +16,7 @@ export function DialogPair(props: { credentials?: DialogPairCredentials }) {
|
|||
const client = useClient()
|
||||
const dialog = useDialog()
|
||||
const dimensions = useTerminalDimensions()
|
||||
const { theme } = useTheme()
|
||||
const { themeV2 } = useTheme().contextual("elevated")
|
||||
const [loadError, setLoadError] = createSignal<unknown>()
|
||||
const [showPassword, setShowPassword] = createSignal(false)
|
||||
const [passwordHover, setPasswordHover] = createSignal(false)
|
||||
|
|
@ -47,17 +47,17 @@ export function DialogPair(props: { credentials?: DialogPairCredentials }) {
|
|||
<box flexDirection={horizontal() ? "row" : "column"} alignItems={horizontal() ? "flex-start" : "center"} gap={2}>
|
||||
<box width={horizontal() ? 29 : "100%"} flexShrink={0} gap={1}>
|
||||
<box>
|
||||
<text fg={theme.textMuted}>URLs</text>
|
||||
<For each={value.urls}>{(url) => <text fg={theme.text}>{url}</text>}</For>
|
||||
<text fg={themeV2.text.subdued()}>URLs</text>
|
||||
<For each={value.urls}>{(url) => <text fg={themeV2.text()}>{url}</text>}</For>
|
||||
</box>
|
||||
<box>
|
||||
<text fg={theme.textMuted}>Username</text>
|
||||
<text fg={theme.text}>{value.username}</text>
|
||||
<text fg={themeV2.text.subdued()}>Username</text>
|
||||
<text fg={themeV2.text()}>{value.username}</text>
|
||||
</box>
|
||||
<box>
|
||||
<text fg={theme.textMuted}>Password</text>
|
||||
<text fg={themeV2.text.subdued()}>Password</text>
|
||||
<text
|
||||
fg={passwordHover() ? theme.text : theme.textMuted}
|
||||
fg={passwordHover() ? themeV2.text() : themeV2.text.subdued()}
|
||||
wrapMode="word"
|
||||
onMouseOver={() => setPasswordHover(true)}
|
||||
onMouseOut={() => setPasswordHover(false)}
|
||||
|
|
@ -67,7 +67,7 @@ export function DialogPair(props: { credentials?: DialogPairCredentials }) {
|
|||
</text>
|
||||
</box>
|
||||
<Show when={value.urls.some((url) => ["localhost", "127.0.0.1", "[::1]"].includes(new URL(url).hostname))}>
|
||||
<text fg={theme.textMuted} wrapMode="word">
|
||||
<text fg={themeV2.text.subdued()} wrapMode="word">
|
||||
Run `opencode service set hostname 0.0.0.0` to access the service remotely.
|
||||
</text>
|
||||
</Show>
|
||||
|
|
@ -78,7 +78,7 @@ export function DialogPair(props: { credentials?: DialogPairCredentials }) {
|
|||
flexShrink={0}
|
||||
alignItems={horizontal() ? "flex-end" : "center"}
|
||||
>
|
||||
<text fg={theme.text}>{renderUnicodeCompact(JSON.stringify(value), { border: 1 })}</text>
|
||||
<text fg={themeV2.text()}>{renderUnicodeCompact(JSON.stringify(value), { border: 1 })}</text>
|
||||
</box>
|
||||
</box>
|
||||
)
|
||||
|
|
@ -87,17 +87,17 @@ export function DialogPair(props: { credentials?: DialogPairCredentials }) {
|
|||
return (
|
||||
<box paddingLeft={2} paddingRight={2} paddingBottom={1} gap={1}>
|
||||
<box flexDirection="row" justifyContent="space-between">
|
||||
<text fg={theme.text} attributes={TextAttributes.BOLD}>
|
||||
<text fg={themeV2.text()} attributes={TextAttributes.BOLD}>
|
||||
Pair
|
||||
</text>
|
||||
<text fg={theme.textMuted} onMouseUp={() => dialog.clear()}>
|
||||
<text fg={themeV2.text.subdued()} onMouseUp={() => dialog.clear()}>
|
||||
esc
|
||||
</text>
|
||||
</box>
|
||||
<Show
|
||||
when={loadError()}
|
||||
fallback={
|
||||
<Show when={info()} fallback={<text fg={theme.textMuted}>Loading server information…</text>}>
|
||||
<Show when={info()} fallback={<text fg={themeV2.text.subdued()}>Loading server information…</text>}>
|
||||
<Show
|
||||
when={dimensions().height >= 36}
|
||||
fallback={
|
||||
|
|
@ -116,11 +116,11 @@ export function DialogPair(props: { credentials?: DialogPairCredentials }) {
|
|||
>
|
||||
{(error) => (
|
||||
<box>
|
||||
<text fg={theme.error} attributes={TextAttributes.BOLD}>
|
||||
<text fg={themeV2.text.feedback.error()} attributes={TextAttributes.BOLD}>
|
||||
Could not load server information
|
||||
</text>
|
||||
<text fg={theme.textMuted}>{errorMessage(error())}</text>
|
||||
<text fg={theme.textMuted}>Close and reopen Pair to try again.</text>
|
||||
<text fg={themeV2.text.subdued()}>{errorMessage(error())}</text>
|
||||
<text fg={themeV2.text.subdued()}>Close and reopen Pair to try again.</text>
|
||||
</box>
|
||||
)}
|
||||
</Show>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { useDialog, type DialogContext } from "../ui/dialog"
|
|||
|
||||
export function DialogProjectCopyName(props: { onConfirm: (name: string) => void }) {
|
||||
const dialog = useDialog()
|
||||
const { theme } = useTheme()
|
||||
const { themeV2 } = useTheme().contextual("elevated")
|
||||
const shortcuts = Keymap.useShortcuts()
|
||||
const [inputTarget, setInputTarget] = createSignal<InputRenderable>()
|
||||
let input: InputRenderable
|
||||
|
|
@ -47,10 +47,10 @@ export function DialogProjectCopyName(props: { onConfirm: (name: string) => void
|
|||
return (
|
||||
<box paddingLeft={2} paddingRight={2} gap={1}>
|
||||
<box flexDirection="row" justifyContent="space-between">
|
||||
<text attributes={TextAttributes.BOLD} fg={theme.text}>
|
||||
<text attributes={TextAttributes.BOLD} fg={themeV2.text()}>
|
||||
Name project copy
|
||||
</text>
|
||||
<text fg={theme.textMuted} onMouseUp={() => dialog.clear()}>
|
||||
<text fg={themeV2.text.subdued()} onMouseUp={() => dialog.clear()}>
|
||||
esc
|
||||
</text>
|
||||
</box>
|
||||
|
|
@ -61,17 +61,18 @@ export function DialogProjectCopyName(props: { onConfirm: (name: string) => void
|
|||
}}
|
||||
onSubmit={confirm}
|
||||
placeholder="Project copy name"
|
||||
placeholderColor={theme.textMuted}
|
||||
textColor={theme.text}
|
||||
focusedTextColor={theme.text}
|
||||
cursorColor={theme.text}
|
||||
placeholderColor={themeV2.text.subdued()}
|
||||
textColor={themeV2.text.formfield()}
|
||||
focusedTextColor={themeV2.text.formfield()}
|
||||
cursorColor={themeV2.text.formfield()}
|
||||
/>
|
||||
<box paddingBottom={1} flexDirection="row" gap={2}>
|
||||
<text fg={theme.text}>
|
||||
enter <span style={{ fg: theme.textMuted }}>submit</span>
|
||||
<text fg={themeV2.text()}>
|
||||
enter <span style={{ fg: themeV2.text.subdued() }}>submit</span>
|
||||
</text>
|
||||
<text fg={theme.text}>
|
||||
{shortcuts.get("dialog.project_copy.generate")} <span style={{ fg: theme.textMuted }}>generate one</span>
|
||||
<text fg={themeV2.text()}>
|
||||
{shortcuts.get("dialog.project_copy.generate")}{" "}
|
||||
<span style={{ fg: themeV2.text.subdued() }}>generate one</span>
|
||||
</text>
|
||||
</box>
|
||||
</box>
|
||||
|
|
|
|||
|
|
@ -8,47 +8,41 @@ export type DialogStatusProps = {}
|
|||
|
||||
export function DialogStatus() {
|
||||
const data = useData()
|
||||
const { theme } = useTheme()
|
||||
const { themeV2 } = useTheme().contextual("elevated")
|
||||
const dialog = useDialog()
|
||||
|
||||
const mcp = createMemo(() => data.location.mcp.server.list() ?? [])
|
||||
const color = (status: string) => {
|
||||
if (status === "connected") return themeV2.text.feedback.success()
|
||||
if (status === "failed") return themeV2.text.feedback.error()
|
||||
if (status === "needs_auth") return themeV2.text.feedback.warning()
|
||||
if (status === "needs_client_registration") return themeV2.text.feedback.error()
|
||||
return themeV2.text.subdued()
|
||||
}
|
||||
return (
|
||||
<box paddingLeft={2} paddingRight={2} gap={1} paddingBottom={1}>
|
||||
<box flexDirection="row" justifyContent="space-between">
|
||||
<text fg={theme.text} attributes={TextAttributes.BOLD}>
|
||||
<text fg={themeV2.text()} attributes={TextAttributes.BOLD}>
|
||||
Status
|
||||
</text>
|
||||
<text fg={theme.textMuted} onMouseUp={() => dialog.clear()}>
|
||||
<text fg={themeV2.text.subdued()} onMouseUp={() => dialog.clear()}>
|
||||
esc
|
||||
</text>
|
||||
</box>
|
||||
<Show when={mcp().length > 0} fallback={<text fg={theme.text}>No MCP servers</text>}>
|
||||
<Show when={mcp().length > 0} fallback={<text fg={themeV2.text()}>No MCP servers</text>}>
|
||||
<box>
|
||||
<text fg={theme.text}>
|
||||
<text fg={themeV2.text()}>
|
||||
{mcp().length} MCP server{mcp().length === 1 ? "" : "s"}
|
||||
</text>
|
||||
<For each={mcp()}>
|
||||
{(item) => (
|
||||
<box flexDirection="row" gap={1}>
|
||||
<text
|
||||
flexShrink={0}
|
||||
style={{
|
||||
fg: (
|
||||
{
|
||||
connected: theme.success,
|
||||
failed: theme.error,
|
||||
disabled: theme.textMuted,
|
||||
needs_auth: theme.warning,
|
||||
needs_client_registration: theme.error,
|
||||
} as Record<string, typeof theme.success>
|
||||
)[item.status.status],
|
||||
}}
|
||||
>
|
||||
<text flexShrink={0} style={{ fg: color(item.status.status) }}>
|
||||
•
|
||||
</text>
|
||||
<text fg={theme.text} wrapMode="word">
|
||||
<text fg={themeV2.text()} wrapMode="word">
|
||||
<b>{item.name}</b>{" "}
|
||||
<span style={{ fg: theme.textMuted }}>
|
||||
<span style={{ fg: themeV2.text.subdued() }}>
|
||||
<Switch fallback={item.status.status}>
|
||||
<Match when={item.status.status === "connected"}>Connected</Match>
|
||||
<Match when={item.status.status === "failed" && item.status}>{(val) => val().error}</Match>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,20 @@
|
|||
import { useTheme } from "../context/theme"
|
||||
|
||||
export function PluginRouteMissing(props: { id: string; name: string; onHome: () => void }) {
|
||||
const { theme } = useTheme()
|
||||
const { themeV2 } = useTheme()
|
||||
|
||||
return (
|
||||
<box width="100%" height="100%" alignItems="center" justifyContent="center" flexDirection="column" gap={1}>
|
||||
<text fg={theme.warning}>
|
||||
<text fg={themeV2.text.feedback.warning()}>
|
||||
Unknown plugin route: {props.id}/{props.name}
|
||||
</text>
|
||||
<box onMouseUp={props.onHome} backgroundColor={theme.backgroundElement} paddingLeft={1} paddingRight={1}>
|
||||
<text fg={theme.text}>go home</text>
|
||||
<box
|
||||
onMouseUp={props.onHome}
|
||||
backgroundColor={themeV2.background.action("hovered")}
|
||||
paddingLeft={1}
|
||||
paddingRight={1}
|
||||
>
|
||||
<text fg={themeV2.text.action("hovered")}>go home</text>
|
||||
</box>
|
||||
</box>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useTheme } from "../context/theme"
|
|||
import { Spinner } from "./spinner"
|
||||
|
||||
export function Reconnecting() {
|
||||
const theme = useTheme().theme
|
||||
const { themeV2 } = useTheme()
|
||||
|
||||
return (
|
||||
<box
|
||||
|
|
@ -12,12 +12,12 @@ export function Reconnecting() {
|
|||
right={0}
|
||||
bottom={0}
|
||||
left={0}
|
||||
backgroundColor={theme.background}
|
||||
backgroundColor={themeV2.background()}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<box width={62} maxWidth="90%" flexDirection="column" alignItems="center" gap={1}>
|
||||
<Spinner color={theme.textMuted}>Waiting for background service...</Spinner>
|
||||
<Spinner color={themeV2.text.subdued()}>Waiting for background service...</Spinner>
|
||||
</box>
|
||||
</box>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useTheme } from "../context/theme"
|
|||
import { Spinner } from "./spinner"
|
||||
|
||||
export function StartupLoading(props: { ready: () => boolean }) {
|
||||
const theme = useTheme().theme
|
||||
const { themeV2 } = useTheme().contextual("elevated")
|
||||
const [show, setShow] = createSignal(false)
|
||||
const text = createMemo(() => (props.ready() ? "Finishing startup..." : "Loading plugins..."))
|
||||
let wait: NodeJS.Timeout | undefined
|
||||
|
|
@ -54,8 +54,8 @@ export function StartupLoading(props: { ready: () => boolean }) {
|
|||
return (
|
||||
<Show when={show()}>
|
||||
<box position="absolute" zIndex={5000} left={0} right={0} bottom={1} justifyContent="center" alignItems="center">
|
||||
<box backgroundColor={theme.backgroundPanel} paddingLeft={1} paddingRight={1}>
|
||||
<Spinner color={theme.textMuted}>{text()}</Spinner>
|
||||
<box backgroundColor={themeV2.background()} paddingLeft={1} paddingRight={1}>
|
||||
<Spinner color={themeV2.text.subdued()}>{text()}</Spinner>
|
||||
</box>
|
||||
</box>
|
||||
</Show>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue