diff options
| author | Adam <[email protected]> | 2025-12-09 14:49:00 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2025-12-09 15:21:47 -0600 |
| commit | b9fa7d91630fdaddf1744ba73b6dfcc8821e0b28 (patch) | |
| tree | 10eaa287374cb90dd5541f50ab5df72051060aef | |
| parent | f736751ab275f52701d40ca0488b75081ed851ec (diff) | |
| download | opencode-b9fa7d91630fdaddf1744ba73b6dfcc8821e0b28.tar.gz opencode-b9fa7d91630fdaddf1744ba73b6dfcc8821e0b28.zip | |
wip(desktop): progress
| -rw-r--r-- | packages/desktop/src/context/layout.tsx | 33 | ||||
| -rw-r--r-- | packages/desktop/src/pages/layout.tsx | 43 | ||||
| -rw-r--r-- | packages/enterprise/src/core/share.ts | 2 | ||||
| -rw-r--r-- | packages/enterprise/src/routes/share/[shareID].tsx | 2 | ||||
| -rw-r--r-- | packages/ui/src/components/message-nav.tsx | 2 | ||||
| -rw-r--r-- | packages/ui/src/components/message-part.tsx | 2 | ||||
| -rw-r--r-- | packages/ui/src/components/message-progress.tsx | 2 | ||||
| -rw-r--r-- | packages/ui/src/components/session-message-rail.tsx | 2 | ||||
| -rw-r--r-- | packages/ui/src/components/session-review.tsx | 2 | ||||
| -rw-r--r-- | packages/ui/src/components/session-turn.tsx | 2 | ||||
| -rw-r--r-- | packages/ui/src/context/data.tsx | 2 | ||||
| -rw-r--r-- | packages/util/src/sanitize.ts | 2 |
12 files changed, 57 insertions, 39 deletions
diff --git a/packages/desktop/src/context/layout.tsx b/packages/desktop/src/context/layout.tsx index 58d947af4..b7d1fabb5 100644 --- a/packages/desktop/src/context/layout.tsx +++ b/packages/desktop/src/context/layout.tsx @@ -12,7 +12,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( const globalSync = useGlobalSync() const [store, setStore] = makePersisted( createStore({ - projects: [] as { directory: string; expanded: boolean }[], + projects: [] as { worktree: string; expanded: boolean }[], sidebar: { opened: false, width: 280, @@ -26,7 +26,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, }), { - name: "default-layout.v4", + name: "default-layout.v6", }, ) @@ -43,32 +43,43 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( onMount(() => { Promise.all( - store.projects.map(({ directory }) => { - return loadProjectSessions(directory) + store.projects.map(({ worktree }) => { + return loadProjectSessions(worktree) }), ) }) + function enrich(project: { worktree: string; expanded: boolean }) { + const metadata = globalSync.data.projects.find((x) => x.worktree === project.worktree) + if (!metadata) return [] + return [ + { + ...project, + ...metadata, + }, + ] + } + return { projects: { - list: createMemo(() => store.projects), + list: createMemo(() => store.projects.flatMap(enrich)), open(directory: string) { - if (store.projects.find((x) => x.directory === directory)) return + if (store.projects.find((x) => x.worktree === directory)) return loadProjectSessions(directory) - setStore("projects", (x) => [...x, { directory, expanded: true }]) + setStore("projects", (x) => [...x, { worktree: directory, expanded: true }]) }, close(directory: string) { - setStore("projects", (x) => x.filter((x) => x.directory !== directory)) + setStore("projects", (x) => x.filter((x) => x.worktree !== directory)) }, expand(directory: string) { - setStore("projects", (x) => x.map((x) => (x.directory === directory ? { ...x, expanded: true } : x))) + setStore("projects", (x) => x.map((x) => (x.worktree === directory ? { ...x, expanded: true } : x))) }, collapse(directory: string) { - setStore("projects", (x) => x.map((x) => (x.directory === directory ? { ...x, expanded: false } : x))) + setStore("projects", (x) => x.map((x) => (x.worktree === directory ? { ...x, expanded: false } : x))) }, move(directory: string, toIndex: number) { setStore("projects", (projects) => { - const fromIndex = projects.findIndex((x) => x.directory === directory) + const fromIndex = projects.findIndex((x) => x.worktree === directory) if (fromIndex === -1 || fromIndex === toIndex) return projects const result = [...projects] const [item] = result.splice(fromIndex, 1) diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index 4d3f6a268..c2755b9dc 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -16,7 +16,7 @@ import { DiffChanges } from "@opencode-ai/ui/diff-changes" import { getFilename } from "@opencode-ai/util/path" import { Select } from "@opencode-ai/ui/select" import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu" -import { Session } from "@opencode-ai/sdk/v2/client" +import { Session, Project } from "@opencode-ai/sdk/v2/client" import { usePlatform } from "@/context/platform" import { createStore } from "solid-js/store" import { @@ -106,8 +106,8 @@ export default function Layout(props: ParentProps) { const { draggable, droppable } = event if (draggable && droppable) { const projects = layout.projects.list() - const fromIndex = projects.findIndex((p) => p.directory === draggable.id.toString()) - const toIndex = projects.findIndex((p) => p.directory === droppable.id.toString()) + const fromIndex = projects.findIndex((p) => p.worktree === draggable.id.toString()) + const toIndex = projects.findIndex((p) => p.worktree === droppable.id.toString()) if (fromIndex !== toIndex && toIndex !== -1) { layout.projects.move(draggable.id.toString(), toIndex) } @@ -176,11 +176,11 @@ export default function Layout(props: ParentProps) { ) } - const SortableProject = (props: { project: { directory: string; expanded: boolean } }): JSX.Element => { - const sortable = createSortable(props.project.directory) - const [projectStore] = globalSync.child(props.project.directory) - const slug = createMemo(() => base64Encode(props.project.directory)) - const name = createMemo(() => getFilename(props.project.directory)) + const SortableProject = (props: { project: Project & { expanded: boolean } }): JSX.Element => { + const sortable = createSortable(props.project.worktree) + const [projectStore] = globalSync.child(props.project.worktree) + const slug = createMemo(() => base64Encode(props.project.worktree)) + const name = createMemo(() => getFilename(props.project.worktree)) return ( // @ts-ignore <div use:sortable classList={{ "opacity-30": sortable.isActiveDraggable }}> @@ -194,11 +194,18 @@ export default function Layout(props: ParentProps) { > <Collapsible.Trigger class="group/trigger flex items-center gap-3 p-0 text-left min-w-0 grow border-none"> <div class="size-6 shrink-0"> - <Avatar - fallback={name()} - background="var(--surface-info-base)" - class="size-full group-hover/session:hidden" - /> + <Switch> + <Match when={props.project.icon?.url}> + {(url) => <img src={url()} class="size-full group-hover/session:hidden" />} + </Match> + <Match when={true}> + <Avatar + fallback={name()} + background={props.project.icon?.color ?? "var(--surface-info-base)"} + class="size-full group-hover/session:hidden" + /> + </Match> + </Switch> <Icon name="chevron-right" size="large" @@ -212,7 +219,7 @@ export default function Layout(props: ParentProps) { <DropdownMenu.Trigger as={IconButton} icon="dot-grid" variant="ghost" /> <DropdownMenu.Portal> <DropdownMenu.Content> - <DropdownMenu.Item onSelect={() => closeProject(props.project.directory)}> + <DropdownMenu.Item onSelect={() => closeProject(props.project.worktree)}> <DropdownMenu.ItemLabel>Close Project</DropdownMenu.ItemLabel> </DropdownMenu.Item> </DropdownMenu.Content> @@ -274,8 +281,8 @@ export default function Layout(props: ParentProps) { </Collapsible> </Match> <Match when={true}> - <Tooltip placement="right" value={props.project.directory}> - <ProjectVisual directory={props.project.directory} /> + <Tooltip placement="right" value={props.project.worktree}> + <ProjectVisual directory={props.project.worktree} /> </Tooltip> </Match> </Switch> @@ -315,7 +322,7 @@ export default function Layout(props: ParentProps) { <div class="flex items-center gap-3"> <div class="flex items-center gap-2"> <Select - options={layout.projects.list().map((project) => project.directory)} + options={layout.projects.list().map((project) => project.worktree)} current={currentDirectory()} label={(x) => getFilename(x)} onSelect={(x) => (x ? navigateToProject(x) : undefined)} @@ -443,7 +450,7 @@ export default function Layout(props: ParentProps) { <DragDropSensors /> <ConstrainDragXAxis /> <div class="w-full min-w-8 flex flex-col gap-2 min-h-0 overflow-y-auto no-scrollbar"> - <SortableProvider ids={layout.projects.list().map((p) => p.directory)}> + <SortableProvider ids={layout.projects.list().map((p) => p.worktree)}> <For each={layout.projects.list()}>{(project) => <SortableProject project={project} />}</For> </SortableProvider> </div> diff --git a/packages/enterprise/src/core/share.ts b/packages/enterprise/src/core/share.ts index a85994c31..d7f5c8b8d 100644 --- a/packages/enterprise/src/core/share.ts +++ b/packages/enterprise/src/core/share.ts @@ -1,4 +1,4 @@ -import { FileDiff, Message, Model, Part, Session, SessionStatus } from "@opencode-ai/sdk" +import { FileDiff, Message, Model, Part, Session } from "@opencode-ai/sdk/v2" import { fn } from "@opencode-ai/util/fn" import { iife } from "@opencode-ai/util/iife" import { Identifier } from "@opencode-ai/util/identifier" diff --git a/packages/enterprise/src/routes/share/[shareID].tsx b/packages/enterprise/src/routes/share/[shareID].tsx index a8b0ecf69..1c66624b1 100644 --- a/packages/enterprise/src/routes/share/[shareID].tsx +++ b/packages/enterprise/src/routes/share/[shareID].tsx @@ -1,4 +1,4 @@ -import { FileDiff, Message, Model, Part, Session, SessionStatus, UserMessage } from "@opencode-ai/sdk" +import { FileDiff, Message, Model, Part, Session, SessionStatus, UserMessage } from "@opencode-ai/sdk/v2" import { SessionTurn } from "@opencode-ai/ui/session-turn" import { SessionReview } from "@opencode-ai/ui/session-review" import { DataProvider } from "@opencode-ai/ui/context" diff --git a/packages/ui/src/components/message-nav.tsx b/packages/ui/src/components/message-nav.tsx index 1a1d2a1b5..29b465c8c 100644 --- a/packages/ui/src/components/message-nav.tsx +++ b/packages/ui/src/components/message-nav.tsx @@ -1,4 +1,4 @@ -import { UserMessage } from "@opencode-ai/sdk" +import { UserMessage } from "@opencode-ai/sdk/v2" import { ComponentProps, createMemo, For, Match, Show, splitProps, Switch } from "solid-js" import { DiffChanges } from "./diff-changes" import { Spinner } from "./spinner" diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index 2da4387fd..a28e36aa8 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -7,7 +7,7 @@ import { TextPart, ToolPart, UserMessage, -} from "@opencode-ai/sdk" +} from "@opencode-ai/sdk/v2" import { useDiffComponent } from "../context/diff" import { BasicTool } from "./basic-tool" import { GenericTool } from "./basic-tool" diff --git a/packages/ui/src/components/message-progress.tsx b/packages/ui/src/components/message-progress.tsx index bbcdd3096..ef3548ab3 100644 --- a/packages/ui/src/components/message-progress.tsx +++ b/packages/ui/src/components/message-progress.tsx @@ -2,7 +2,7 @@ import { For, JSXElement, Match, Show, Switch, createEffect, createMemo, createS import { Part } from "./message-part" import { Spinner } from "./spinner" import { useData } from "../context/data" -import type { AssistantMessage as AssistantMessageType, ToolPart } from "@opencode-ai/sdk" +import type { AssistantMessage as AssistantMessageType, ToolPart } from "@opencode-ai/sdk/v2" export interface MessageProgressProps { assistantMessages: () => AssistantMessageType[] diff --git a/packages/ui/src/components/session-message-rail.tsx b/packages/ui/src/components/session-message-rail.tsx index 29d9ac81e..132b813d2 100644 --- a/packages/ui/src/components/session-message-rail.tsx +++ b/packages/ui/src/components/session-message-rail.tsx @@ -1,4 +1,4 @@ -import { UserMessage } from "@opencode-ai/sdk" +import { UserMessage } from "@opencode-ai/sdk/v2" import { ComponentProps, Show, splitProps } from "solid-js" import { MessageNav } from "./message-nav" import "./session-message-rail.css" diff --git a/packages/ui/src/components/session-review.tsx b/packages/ui/src/components/session-review.tsx index cc82dcbd4..8009091b7 100644 --- a/packages/ui/src/components/session-review.tsx +++ b/packages/ui/src/components/session-review.tsx @@ -8,7 +8,7 @@ import { useDiffComponent } from "../context/diff" import { getDirectory, getFilename } from "@opencode-ai/util/path" import { For, Match, Show, Switch, type JSX } from "solid-js" import { createStore } from "solid-js/store" -import { type FileDiff } from "@opencode-ai/sdk" +import { type FileDiff } from "@opencode-ai/sdk/v2" import { PreloadMultiFileDiffResult } from "@pierre/precision-diffs/ssr" import { Dynamic } from "solid-js/web" import { checksum } from "@opencode-ai/util/encode" diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx index 5ca50a5cc..14ba77e26 100644 --- a/packages/ui/src/components/session-turn.tsx +++ b/packages/ui/src/components/session-turn.tsx @@ -1,4 +1,4 @@ -import { AssistantMessage } from "@opencode-ai/sdk" +import { AssistantMessage } from "@opencode-ai/sdk/v2" import { useData } from "../context" import { useDiffComponent } from "../context/diff" import { getDirectory, getFilename } from "@opencode-ai/util/path" diff --git a/packages/ui/src/context/data.tsx b/packages/ui/src/context/data.tsx index 728202a09..265178e10 100644 --- a/packages/ui/src/context/data.tsx +++ b/packages/ui/src/context/data.tsx @@ -1,4 +1,4 @@ -import type { Message, Session, Part, FileDiff, SessionStatus } from "@opencode-ai/sdk" +import type { Message, Session, Part, FileDiff, SessionStatus } from "@opencode-ai/sdk/v2" import { createSimpleContext } from "./helper" import { PreloadMultiFileDiffResult } from "@pierre/precision-diffs/ssr" diff --git a/packages/util/src/sanitize.ts b/packages/util/src/sanitize.ts index 38ad2b290..4bb762393 100644 --- a/packages/util/src/sanitize.ts +++ b/packages/util/src/sanitize.ts @@ -1,4 +1,4 @@ -import type { Part } from "@opencode-ai/sdk/client" +import type { Part } from "@opencode-ai/sdk/v2/client" export const sanitize = (text: string | undefined, remove?: RegExp) => (remove ? text?.replace(remove, "") : text) ?? "" |
