Moves effect logging, observability, runtime utilities, flags, installation version info, and process utilities from opencode to core package. This enables better code sharing across packages and establishes core as the single source of truth for foundational utilities. All internal imports updated to use @opencode-ai/core paths for consistency.
98 lines
3.5 KiB
TypeScript
98 lines
3.5 KiB
TypeScript
import { useProject } from "@tui/context/project"
|
|
import { useSync } from "@tui/context/sync"
|
|
import { createMemo, Show } from "solid-js"
|
|
import { useTheme } from "../../context/theme"
|
|
import { useTuiConfig } from "../../context/tui-config"
|
|
import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version"
|
|
import { TuiPluginRuntime } from "../../plugin"
|
|
|
|
import { getScrollAcceleration } from "../../util/scroll"
|
|
|
|
export function Sidebar(props: { sessionID: string; overlay?: boolean }) {
|
|
const project = useProject()
|
|
const sync = useSync()
|
|
const { theme } = useTheme()
|
|
const tuiConfig = useTuiConfig()
|
|
const session = createMemo(() => sync.session.get(props.sessionID))
|
|
const workspaceStatus = () => {
|
|
const workspaceID = session()?.workspaceID
|
|
if (!workspaceID) return "error"
|
|
return project.workspace.status(workspaceID) ?? "error"
|
|
}
|
|
const workspaceLabel = () => {
|
|
const workspaceID = session()?.workspaceID
|
|
if (!workspaceID) return "unknown"
|
|
const info = project.workspace.get(workspaceID)
|
|
if (!info) return "unknown"
|
|
return `${info.type}: ${info.name}`
|
|
}
|
|
const scrollAcceleration = createMemo(() => getScrollAcceleration(tuiConfig))
|
|
|
|
return (
|
|
<Show when={session()}>
|
|
<box
|
|
backgroundColor={theme.backgroundPanel}
|
|
width={42}
|
|
height="100%"
|
|
paddingTop={1}
|
|
paddingBottom={1}
|
|
paddingLeft={2}
|
|
paddingRight={2}
|
|
position={props.overlay ? "absolute" : "relative"}
|
|
>
|
|
<scrollbox
|
|
flexGrow={1}
|
|
scrollAcceleration={scrollAcceleration()}
|
|
verticalScrollbarOptions={{
|
|
trackOptions: {
|
|
backgroundColor: theme.background,
|
|
foregroundColor: theme.borderActive,
|
|
},
|
|
}}
|
|
>
|
|
<box flexShrink={0} gap={1} paddingRight={1}>
|
|
<TuiPluginRuntime.Slot
|
|
name="sidebar_title"
|
|
mode="single_winner"
|
|
session_id={props.sessionID}
|
|
title={session()!.title}
|
|
share_url={session()!.share?.url}
|
|
>
|
|
<box paddingRight={1}>
|
|
<text fg={theme.text}>
|
|
<b>{session()!.title}</b>
|
|
</text>
|
|
<Show when={InstallationChannel !== "latest"}>
|
|
<text fg={theme.textMuted}>{props.sessionID}</text>
|
|
</Show>
|
|
<Show when={session()!.workspaceID}>
|
|
<text fg={theme.textMuted}>
|
|
<span style={{ fg: workspaceStatus() === "connected" ? theme.success : theme.error }}>●</span>{" "}
|
|
{workspaceLabel()}
|
|
</text>
|
|
</Show>
|
|
<Show when={session()!.share?.url}>
|
|
<text fg={theme.textMuted}>{session()!.share!.url}</text>
|
|
</Show>
|
|
</box>
|
|
</TuiPluginRuntime.Slot>
|
|
<TuiPluginRuntime.Slot name="sidebar_content" session_id={props.sessionID} />
|
|
</box>
|
|
</scrollbox>
|
|
|
|
<box flexShrink={0} gap={1} paddingTop={1}>
|
|
<TuiPluginRuntime.Slot name="sidebar_footer" mode="single_winner" session_id={props.sessionID}>
|
|
<text fg={theme.textMuted}>
|
|
<span style={{ fg: theme.success }}>•</span> <b>Open</b>
|
|
<span style={{ fg: theme.text }}>
|
|
<b>Code</b>
|
|
</span>{" "}
|
|
<span>{InstallationVersion}</span>
|
|
</text>
|
|
</TuiPluginRuntime.Slot>
|
|
</box>
|
|
</box>
|
|
</Show>
|
|
)
|
|
}
|