diff options
| author | Adam <[email protected]> | 2025-12-13 15:12:41 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2025-12-13 15:12:41 -0600 |
| commit | 5bcc93851c59829c00c5801c039170cc6e1f3d7a (patch) | |
| tree | 520bf6d4ebe98543275526d5435cc9cc96321763 /packages | |
| parent | d0789632b4cf8d29d67faf652d955868fc447208 (diff) | |
| download | opencode-5bcc93851c59829c00c5801c039170cc6e1f3d7a.tar.gz opencode-5bcc93851c59829c00c5801c039170cc6e1f3d7a.zip | |
chore: cleanup
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/desktop/package.json | 1 | ||||
| -rw-r--r-- | packages/ui/src/components/session-turn.tsx | 73 |
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" |
