summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorAdam <[email protected]>2025-12-13 15:12:41 -0600
committerAdam <[email protected]>2025-12-13 15:12:41 -0600
commit5bcc93851c59829c00c5801c039170cc6e1f3d7a (patch)
tree520bf6d4ebe98543275526d5435cc9cc96321763 /packages
parentd0789632b4cf8d29d67faf652d955868fc447208 (diff)
downloadopencode-5bcc93851c59829c00c5801c039170cc6e1f3d7a.tar.gz
opencode-5bcc93851c59829c00c5801c039170cc6e1f3d7a.zip
chore: cleanup
Diffstat (limited to 'packages')
-rw-r--r--packages/desktop/package.json1
-rw-r--r--packages/ui/src/components/session-turn.tsx73
2 files changed, 43 insertions, 31 deletions
diff --git a/packages/desktop/package.json b/packages/desktop/package.json
index 91e04af08..6753308c9 100644
--- a/packages/desktop/package.json
+++ b/packages/desktop/package.json
@@ -37,6 +37,7 @@
"@solid-primitives/active-element": "2.1.3",
"@solid-primitives/audio": "1.4.2",
"@solid-primitives/event-bus": "1.1.2",
+ "@solid-primitives/media": "2.3.3",
"@solid-primitives/resize-observer": "2.1.3",
"@solid-primitives/scroll": "2.1.3",
"@solid-primitives/storage": "4.3.3",
diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx
index 07946ed79..692e869fe 100644
--- a/packages/ui/src/components/session-turn.tsx
+++ b/packages/ui/src/components/session-turn.tsx
@@ -3,7 +3,7 @@ import { useData } from "../context"
import { useDiffComponent } from "../context/diff"
import { getDirectory, getFilename } from "@opencode-ai/util/path"
import { checksum } from "@opencode-ai/util/encode"
-import { createEffect, createMemo, createSignal, For, Match, onCleanup, ParentProps, Show, Switch } from "solid-js"
+import { createEffect, createMemo, For, Match, onCleanup, ParentProps, Show, Switch } from "solid-js"
import { createResizeObserver } from "@solid-primitives/resize-observer"
import { DiffChanges } from "./diff-changes"
import { Typewriter } from "./typewriter"
@@ -49,56 +49,67 @@ export function SessionTurn(
const working = createMemo(() => status()?.type !== "idle")
let scrollRef: HTMLDivElement | undefined
- const [contentRef, setContentRef] = createSignal<HTMLDivElement>()
- const [stickyTitleRef, setStickyTitleRef] = createSignal<HTMLDivElement>()
- const [stickyTriggerRef, setStickyTriggerRef] = createSignal<HTMLDivElement>()
- const [userScrolled, setUserScrolled] = createSignal(false)
- const [stickyHeaderHeight, setStickyHeaderHeight] = createSignal(0)
- const [scrollY, setScrollY] = createSignal(0)
+ const [state, setState] = createStore({
+ contentRef: undefined as HTMLDivElement | undefined,
+ stickyTitleRef: undefined as HTMLDivElement | undefined,
+ stickyTriggerRef: undefined as HTMLDivElement | undefined,
+ userScrolled: false,
+ stickyHeaderHeight: 0,
+ scrollY: 0,
+ })
function handleScroll() {
if (!scrollRef) return
- setScrollY(scrollRef.scrollTop)
+ setState("scrollY", scrollRef.scrollTop)
const { scrollTop, scrollHeight, clientHeight } = scrollRef
const atBottom = scrollHeight - scrollTop - clientHeight < 50
if (!atBottom && working()) {
- setUserScrolled(true)
+ setState("userScrolled", true)
}
}
function handleInteraction() {
if (working()) {
- setUserScrolled(true)
+ setState("userScrolled", true)
}
}
createEffect(() => {
if (!working()) {
- setUserScrolled(false)
+ setState("userScrolled", false)
}
})
- createResizeObserver(contentRef, () => {
- if (!scrollRef || userScrolled() || !working()) return
- requestAnimationFrame(() => {
- scrollRef.scrollTop = scrollRef.scrollHeight
- })
- })
+ createResizeObserver(
+ () => state.contentRef,
+ () => {
+ if (!scrollRef || state.userScrolled || !working()) return
+ requestAnimationFrame(() => {
+ scrollRef.scrollTop = scrollRef.scrollHeight
+ })
+ },
+ )
- createResizeObserver(stickyTitleRef, ({ height }) => {
- const triggerHeight = stickyTriggerRef()?.offsetHeight ?? 0
- setStickyHeaderHeight(height + triggerHeight + 8)
- })
+ createResizeObserver(
+ () => state.stickyTitleRef,
+ ({ height }) => {
+ const triggerHeight = state.stickyTriggerRef?.offsetHeight ?? 0
+ setState("stickyHeaderHeight", height + triggerHeight + 8)
+ },
+ )
- createResizeObserver(stickyTriggerRef, ({ height }) => {
- const titleHeight = stickyTitleRef()?.offsetHeight ?? 0
- setStickyHeaderHeight(titleHeight + height + 8)
- })
+ createResizeObserver(
+ () => state.stickyTriggerRef,
+ ({ height }) => {
+ const titleHeight = state.stickyTitleRef?.offsetHeight ?? 0
+ setState("stickyHeaderHeight", titleHeight + height + 8)
+ },
+ )
return (
- <div data-component="session-turn" class={props.classes?.root} style={{ "--scroll-y": `${scrollY()}px` }}>
+ <div data-component="session-turn" class={props.classes?.root} style={{ "--scroll-y": `${state.scrollY}px` }}>
<div ref={scrollRef} onScroll={handleScroll} data-slot="session-turn-content" class={props.classes?.content}>
- <div ref={setContentRef} onClick={handleInteraction}>
+ <div ref={(el) => setState("contentRef", el)} onClick={handleInteraction}>
<Show when={message()}>
{(message) => {
const assistantMessages = createMemo(() => {
@@ -237,7 +248,7 @@ export function SessionTurn(
createEffect((prev) => {
const isWorking = working()
- if (prev && !isWorking && !userScrolled()) {
+ if (prev && !isWorking && !state.userScrolled) {
setStore("stepsExpanded", false)
}
return isWorking
@@ -248,10 +259,10 @@ export function SessionTurn(
data-message={message().id}
data-slot="session-turn-message-container"
class={props.classes?.container}
- style={{ "--sticky-header-height": `${stickyHeaderHeight()}px` }}
+ style={{ "--sticky-header-height": `${state.stickyHeaderHeight}px` }}
>
{/* Title (sticky) */}
- <div ref={setStickyTitleRef} data-slot="session-turn-sticky-title">
+ <div ref={(el) => setState("stickyTitleRef", el)} data-slot="session-turn-sticky-title">
<div data-slot="session-turn-message-header">
<div data-slot="session-turn-message-title">
<Switch>
@@ -270,7 +281,7 @@ export function SessionTurn(
<Message message={message()} parts={parts()} />
</div>
{/* Trigger (sticky) */}
- <div ref={setStickyTriggerRef} data-slot="session-turn-response-trigger">
+ <div ref={(el) => setState("stickyTriggerRef", el)} data-slot="session-turn-response-trigger">
<Button
data-slot="session-turn-collapsible-trigger-content"
variant="ghost"