From 3d43214075b1f4ba0a3c71d5fea799532bbb7bd9 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:44:25 -0600 Subject: wip: desktop work --- packages/desktop/src/pages/index.tsx | 663 +++++++++++++++++------------------ 1 file changed, 323 insertions(+), 340 deletions(-) (limited to 'packages/desktop/src/pages') diff --git a/packages/desktop/src/pages/index.tsx b/packages/desktop/src/pages/index.tsx index dc3436720..7bba17cba 100644 --- a/packages/desktop/src/pages/index.tsx +++ b/packages/desktop/src/pages/index.tsx @@ -10,10 +10,10 @@ import { Diff, Collapsible, DiffChanges, - ProgressCircle, Message, Typewriter, Card, + Code, } from "@opencode-ai/ui" import { FileIcon } from "@/ui" import FileTree from "@/components/file-tree" @@ -35,7 +35,6 @@ import { } from "@thisbeyond/solid-dnd" import type { DragEvent, Transformer } from "@thisbeyond/solid-dnd" import type { JSX } from "solid-js" -import { Code } from "@/components/code" import { useSync } from "@/context/sync" import { useSDK } from "@/context/sdk" import { type AssistantMessage as AssistantMessageType } from "@opencode-ai/sdk" @@ -54,14 +53,6 @@ export default function Page() { let messageScrollElement!: HTMLDivElement const [activeItem, setActiveItem] = createSignal(undefined) - createEffect(() => { - // Set first message as active if none selected - const userMessages = local.session.userMessages() - if (userMessages.length > 0 && !local.session.activeMessage()) { - local.session.setActiveMessage(userMessages[0].id) - } - }) - const MOD = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform) ? "Meta" : "Control" onMount(() => { @@ -91,26 +82,26 @@ export default function Page() { return } - if (local.file.active()) { - const active = local.file.active()! - if (event.key === "Enter" && active.selection) { - local.context.add({ - type: "file", - path: active.path, - selection: { ...active.selection }, - }) - return - } - - if (event.getModifierState(MOD)) { - if (event.key.toLowerCase() === "a") { - return - } - if (event.key.toLowerCase() === "c") { - return - } - } - } + // if (local.file.active()) { + // const active = local.file.active()! + // if (event.key === "Enter" && active.selection) { + // local.context.add({ + // type: "file", + // path: active.path, + // selection: { ...active.selection }, + // }) + // return + // } + // + // if (event.getModifierState(MOD)) { + // if (event.key.toLowerCase() === "a") { + // return + // } + // if (event.key.toLowerCase() === "c") { + // return + // } + // } + // } if (event.key.length === 1 && event.key !== "Unidentified" && !(event.ctrlKey || event.metaKey)) { inputRef?.focus() @@ -140,21 +131,22 @@ export default function Page() { } } - const navigateChange = (dir: 1 | -1) => { - const active = local.file.active() - if (!active) return - const current = local.file.changeIndex(active.path) - const next = current === undefined ? (dir === 1 ? 0 : -1) : current + dir - local.file.setChangeIndex(active.path, next) - } + // const navigateChange = (dir: 1 | -1) => { + // const active = local.file.active() + // if (!active) return + // const current = local.file.changeIndex(active.path) + // const next = current === undefined ? (dir === 1 ? 0 : -1) : current + dir + // local.file.setChangeIndex(active.path, next) + // } const handleTabChange = (path: string) => { - if (path === "chat" || path === "review") return - local.file.open(path) + local.session.setActiveTab(path) + if (path === "chat") return + local.session.open(path) } const handleTabClose = (file: LocalFile) => { - local.file.close(file.path) + local.session.close(file.path) } const handleDragStart = (event: unknown) => { @@ -166,11 +158,11 @@ export default function Page() { const handleDragOver = (event: DragEvent) => { const { draggable, droppable } = event if (draggable && droppable) { - const currentFiles = local.file.opened().map((file) => file.path) - const fromIndex = currentFiles.indexOf(draggable.id.toString()) - const toIndex = currentFiles.indexOf(droppable.id.toString()) - if (fromIndex !== toIndex) { - local.file.move(draggable.id.toString(), toIndex) + const currentFiles = local.session.tabs()?.opened.map((file) => file) + const fromIndex = currentFiles?.indexOf(draggable.id.toString()) + const toIndex = currentFiles?.indexOf(droppable.id.toString()) + if (fromIndex !== toIndex && toIndex !== undefined) { + local.session.move(draggable.id.toString(), toIndex) } } } @@ -179,20 +171,20 @@ export default function Page() { setActiveItem(undefined) } - const scrollDiffItem = (element: HTMLElement) => { - element.scrollIntoView({ block: "start", behavior: "instant" }) - } + // const scrollDiffItem = (element: HTMLElement) => { + // element.scrollIntoView({ block: "start", behavior: "instant" }) + // } const handleDiffTriggerClick = (event: MouseEvent) => { // disabling scroll to diff for now return - const target = event.currentTarget as HTMLElement - queueMicrotask(() => { - if (target.getAttribute("aria-expanded") !== "true") return - const item = target.closest('[data-slot="accordion-item"]') as HTMLElement | null - if (!item) return - scrollDiffItem(item) - }) + // const target = event.currentTarget as HTMLElement + // queueMicrotask(() => { + // if (target.getAttribute("aria-expanded") !== "true") return + // const item = target.closest('[data-slot="accordion-item"]') as HTMLElement | null + // if (!item) return + // scrollDiffItem(item) + // }) } const handlePromptSubmit = async (parts: ContentPart[]) => { @@ -205,6 +197,10 @@ export default function Page() { if (!session) return local.session.setActive(session.id) + if (!existingSession) { + local.session.copyTabs("", session.id) + } + local.session.setActiveTab(undefined) const toAbsolutePath = (path: string) => (path.startsWith("/") ? path : sync.absolute(path)) const text = parts.map((part) => part.content).join("") @@ -427,20 +423,26 @@ export default function Page() { > - +
Chat
- - -
{local.session.context() ?? 0}%
-
+ {/* */} + {/* */} + {/*
{local.session.context() ?? 0}%
*/} + {/*
*/}
{/* Review */} - file.path)}> - - {(file) => } + + + {(file) => ( + + )}
@@ -452,64 +454,6 @@ export default function Page() { />
-
@@ -537,250 +481,289 @@ export default function Page() {
} > - {(activeSession) => ( -
-
- 1}> - - -
- - {(message) => { - const isActive = createMemo(() => local.session.activeMessage()?.id === message.id) - const [titled, setTitled] = createSignal(!!message.summary?.title) - const assistantMessages = createMemo(() => { - return sync.data.message[activeSession().id]?.filter( - (m) => m.role === "assistant" && m.parentID == message.id, - ) as AssistantMessageType[] - }) - const error = createMemo(() => assistantMessages().find((m) => m?.error)?.error) - const [completed, setCompleted] = createSignal(!!message.summary?.body || !!error()) - const [expanded, setExpanded] = createSignal(false) - const parts = createMemo(() => sync.data.part[message.id]) - const title = createMemo(() => message.summary?.title) - const summary = createMemo(() => message.summary?.body) - const diffs = createMemo(() => message.summary?.diffs ?? []) - const hasToolPart = createMemo(() => - assistantMessages() - ?.flatMap((m) => sync.data.part[m.id]) - .some((p) => p?.type === "tool"), - ) - const working = createMemo(() => !summary() && !error()) - - // allowing time for the animations to finish - createEffect(() => { - title() - setTimeout(() => setTitled(!!title()), 10_000) - }) - createEffect(() => { - const complete = !!summary() || !!error() - setTimeout(() => setCompleted(complete), 1200) - }) - - return ( - -
- {/* Title */} -
-
- - } - > -

{title()}

-
-
-
-
- -
- {/* Summary */} - -
-
-

- - Summary - Response - -

- - {(summary) => ( - *]:fade-up-text": !diffs().length }} - text={summary()} + {/* Title */} +
+
+ - )} + } + > +

+ {title()} +

- - - {(diff) => ( - - - -
-
- -
- - - {getDirectory(diff.file)}‎ +
+
+ +
+ {/* Summary */} + +
+
+

+ + Summary + Response + +

+ + {(summary) => ( + *]:fade-up-text": !diffs().length }} + text={summary()} + /> + )} + +
+ + + {(diff) => ( + + + +
+
+ +
+ + + {getDirectory(diff.file)}‎ + + + + {getFilename(diff.file)} - - - {getFilename(diff.file)} - +
+
+
+ +
-
- - -
-
- - - - + + + + + + )} + + +
+ + + + {error()?.data?.message as string} + + + {/* Response */} +
+ + + + + + + +
+
+ + Hide details + Show details + +
+ +
+
+ +
+ + {(assistantMessage) => { + const parts = createMemo( + () => sync.data.part[assistantMessage.id], + ) + return }} - /> - - - )} - - -
- - - - {error()?.data?.message as string} - - - {/* Response */} -
- - - - - - - -
-
- - Hide details - Show details - + + + + {error()?.data?.message as string} + +
- -
-
- -
- - {(assistantMessage) => { - const parts = createMemo( - () => sync.data.part[assistantMessage.id], - ) - return - }} - - - - {error()?.data?.message as string} - - -
-
-
-
-
+ + + + +
-
- - ) - }} -
+ + ) + }} + +
-
- )} + ) + }}
{/* */} - + {(file) => ( - + {(() => { - const view = local.file.view(file.path) - const showRaw = view === "raw" || !file.content?.diff - const code = showRaw ? (file.content?.content ?? "") : (file.content?.diff ?? "") - return + { + /* const view = local.file.view(file) */ + } + { + /* const showRaw = view === "raw" || !file.content?.diff */ + } + { + /* const code = showRaw ? (file.content?.content ?? "") : (file.content?.diff ?? "") */ + } + const node = local.file.node(file) + return ( + + ) })()} )} @@ -847,7 +830,7 @@ export default function Page() { items={local.file.search} key={(x) => x} onOpenChange={(open) => setStore("fileSelectOpen", open)} - onSelect={(x) => (x ? local.file.open(x, { pinned: true }) : undefined)} + onSelect={(x) => (x ? local.session.open(x) : undefined)} > {(i) => (