From b207ed2b7b4080c3c6e0b2bc8430abcb4a894cad Mon Sep 17 00:00:00 2001
From: Adam <2363879+adamdotdevin@users.noreply.github.com>
Date: Thu, 25 Sep 2025 07:04:36 -0500
Subject: wip: better desktop file status state and timeline
---
packages/app/src/components/code.tsx | 2 +-
packages/app/src/components/markdown.tsx | 3 +-
packages/app/src/components/session-timeline.tsx | 324 +++++++++++++++--------
3 files changed, 215 insertions(+), 114 deletions(-)
(limited to 'packages/app/src/components')
diff --git a/packages/app/src/components/code.tsx b/packages/app/src/components/code.tsx
index e4121d121..63f527c46 100644
--- a/packages/app/src/components/code.tsx
+++ b/packages/app/src/components/code.tsx
@@ -435,7 +435,7 @@ function transformerUnifiedDiff(): ShikiTransformer {
out.push(s)
}
- return out.join("\n")
+ return out.join("\n").trimEnd()
},
code(node) {
if (isDiff) this.addClassToHast(node, "code-diff")
diff --git a/packages/app/src/components/markdown.tsx b/packages/app/src/components/markdown.tsx
index ab6232ecf..a60fad149 100644
--- a/packages/app/src/components/markdown.tsx
+++ b/packages/app/src/components/markdown.tsx
@@ -6,8 +6,7 @@ function strip(text: string): string {
const match = text.match(wrappedRe)
return match ? match[2] : text
}
-
-export default function Markdown(props: { text: string; class?: string }) {
+export function Markdown(props: { text: string; class?: string }) {
const marked = useMarked()
const [html] = createResource(
() => strip(props.text),
diff --git a/packages/app/src/components/session-timeline.tsx b/packages/app/src/components/session-timeline.tsx
index ac8519a9c..99fa5fac8 100644
--- a/packages/app/src/components/session-timeline.tsx
+++ b/packages/app/src/components/session-timeline.tsx
@@ -1,5 +1,5 @@
import { useLocal, useSync } from "@/context"
-import { Collapsible, Icon, type IconProps } from "@/ui"
+import { Collapsible, Icon } from "@/ui"
import type { Part, ToolPart } from "@opencode-ai/sdk"
import { DateTime } from "luxon"
import {
@@ -13,58 +13,14 @@ import {
type ParentProps,
createEffect,
createMemo,
+ Show,
} from "solid-js"
import { getFilename } from "@/utils"
-import Markdown from "./markdown"
+import { Markdown } from "./markdown"
import { Code } from "./code"
import { createElementSize } from "@solid-primitives/resize-observer"
import { createScrollPosition } from "@solid-primitives/scroll"
-function TimelineIcon(props: { name: IconProps["name"]; class?: string }) {
- return (
-
-
-
- )
-}
-
-function CollapsibleTimelineIcon(props: { name: IconProps["name"]; class?: string }) {
- return (
- <>
-
-
-
- >
- )
-}
-
-function ToolIcon(props: { part: ToolPart }) {
- return (
- }>
-
-
-
-
-
-
-
-
-
-
- )
-}
-
function Part(props: ParentProps & ComponentProps<"div">) {
const [local, others] = splitProps(props, ["class", "classList", "children"])
return (
@@ -97,9 +53,13 @@ function CollapsiblePart(props: { title: ParentProps["children"] } & ParentProps
}
function ReadToolPart(props: { part: ToolPart }) {
+ const sync = useSync()
const local = useLocal()
return (
+
+ Reading file...
+
{(state) => {
const path = state().input["filePath"] as string
@@ -110,13 +70,27 @@ function ReadToolPart(props: { part: ToolPart }) {
)
}}
+
+ {(state) => (
+
+
+ Read {getFilename(state().input["filePath"] as string)}
+
+
{sync.sanitize(state().error)}
+
+ )}
+
)
}
function EditToolPart(props: { part: ToolPart }) {
+ const sync = useSync()
return (
+
+ Preparing edit...
+
{(state) => (
)}
+
+ {(state) => (
+
+ Edit {getFilename(state().input["filePath"] as string)}
+ >
+ }
+ >
+ {sync.sanitize(state().error)}
+
+ )}
+
)
}
function WriteToolPart(props: { part: ToolPart }) {
+ const sync = useSync()
return (
+
+ Preparing write...
+
{(state) => (
)}
+
+ {(state) => (
+
+
+ Write {getFilename(state().input["filePath"] as string)}
+
+
{sync.sanitize(state().error)}
+
+ )}
+
)
}
-function ToolPart(props: { part: ToolPart }) {
+function BashToolPart(props: { part: ToolPart }) {
+ const sync = useSync()
return (
-
- {props.part.type}:{props.part.tool}
-
- }
- >
-
-
-
-
+
+
+ Writing shell command...
-
-
-
-
+
+ {(state) => (
+
+ Run command: {state().input["command"]}
+ >
+ }
+ >
+
+
+ )}
-
-
-
-
+
+ {(state) => (
+
+ Shell {state().input["command"]}
+ >
+ }
+ >
+ {sync.sanitize(state().error)}
+
+ )}
)
}
+function ToolPart(props: { part: ToolPart }) {
+ // read
+ // edit
+ // write
+ // bash
+ // ls
+ // glob
+ // grep
+ // todowrite
+ // todoread
+ // webfetch
+ // websearch
+ // patch
+ // task
+ return (
+
+
+ {props.part.type}:{props.part.tool}
+
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
export default function SessionTimeline(props: { session: string; class?: string }) {
const sync = useSync()
const [scrollElement, setScrollElement] = createSignal(undefined)
@@ -196,6 +247,7 @@ export default function SessionTimeline(props: { session: string; class?: string
const scroll = createScrollPosition(scrollElement)
onMount(() => sync.session.sync(props.session))
+ const session = createMemo(() => sync.session.get(props.session))
const messages = createMemo(() => sync.data.message[props.session] ?? [])
const working = createMemo(() => {
const last = messages()[messages().length - 1]
@@ -285,60 +337,33 @@ export default function SessionTimeline(props: { session: string; class?: string
-
- {(message) => (
-
+
+
+ {(message) => (
{(part) => (
- -
-
-
-
-
- }
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
- {(part) => }
-
+
{part.type}}>
{(part) => (
-
+
{part().text}
-
12:07pm · adam
+
+ {DateTime.fromMillis(message.time.created).toRelative()} ·{" "}
+ {sync.data.config.username ?? "user"}
+
-
+
)}
@@ -347,9 +372,11 @@ export default function SessionTimeline(props: { session: string; class?: string
{(part) => (
- Thought for {duration(part())}s
- >
+ Thinking}>
+
+ Thought for {duration(part())}s
+
+
}
>
@@ -361,9 +388,84 @@ export default function SessionTimeline(props: { session: string; class?: string
)}
-
- )}
-
+ )}
+
+
+
+
+
+
+
+ Raw Session Data
+
+
+
+
+
+ -
+
+
+
+
+ session
+
+
+
+
+
+
+
+
+
+ {(message) => (
+ <>
+ -
+
+
+
+
+ {message.role === "user" ? "user" : "assistant"}
+
+
+
+
+
+
+
+
+
+ {(part) => (
+ -
+
+
+
+
+ {part.type}
+
+
+
+
+
+
+
+
+ )}
+
+ >
+ )}
+
+
+
+
+
)
}
--
cgit v1.2.3