From d7569a5625e4a2287195c27a84330af1d9d2c3df Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 4 Mar 2026 07:03:44 -0600 Subject: fix(app): terminal tab close --- packages/app/src/pages/session/terminal-panel.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'packages/app/src/pages/session') diff --git a/packages/app/src/pages/session/terminal-panel.tsx b/packages/app/src/pages/session/terminal-panel.tsx index 49bed9490..cc4c17ee2 100644 --- a/packages/app/src/pages/session/terminal-panel.tsx +++ b/packages/app/src/pages/session/terminal-panel.tsx @@ -102,7 +102,7 @@ export function TerminalPanel() { const all = createMemo(() => terminal.all()) const ids = createMemo(() => all().map((pty) => pty.id)) - const byId = createMemo(() => new Map(all().map((pty) => [pty.id, pty]))) + const byId = createMemo(() => new Map(all().map((pty) => [pty.id, { ...pty }]))) const handleTerminalDragStart = (event: unknown) => { const id = getDraggableId(event) @@ -189,7 +189,13 @@ export function TerminalPanel() { > - {(pty) => } + + {(id) => ( + + {(pty) => } + + )} +
Date: Wed, 4 Mar 2026 07:18:03 -0600 Subject: fix(app): loading session should be scrolled to the bottom --- .../app/src/pages/session/message-timeline.tsx | 419 +++++++++++---------- 1 file changed, 210 insertions(+), 209 deletions(-) (limited to 'packages/app/src/pages/session') diff --git a/packages/app/src/pages/session/message-timeline.tsx b/packages/app/src/pages/session/message-timeline.tsx index a7f503d5a..433c36e2e 100644 --- a/packages/app/src/pages/session/message-timeline.tsx +++ b/packages/app/src/pages/session/message-timeline.tsx @@ -550,227 +550,228 @@ export function MessageTimeline(props: { "--sticky-accordion-top": showHeader() ? "48px" : "0px", }} > - -
-
-
- - - - - - {titleValue()} - - } - > - { - titleRef = el - }} - value={title.draft} - disabled={title.saving} - class="text-14-medium text-text-strong grow-1 min-w-0 pl-2 rounded-[6px]" - style={{ "--inline-input-shadow": "var(--shadow-xs-border-select)" }} - onInput={(event) => setTitle("draft", event.currentTarget.value)} - onKeyDown={(event) => { - event.stopPropagation() - if (event.key === "Enter") { - event.preventDefault() - void saveTitleEditor() - return - } - if (event.key === "Escape") { - event.preventDefault() - closeTitleEditor() - } - }} - onBlur={closeTitleEditor} +
+ +
+
+
+ + - -
- - {(id) => ( -
- - setTitle("menuOpen", open)} + + + {titleValue()} + + } > - - - { - if (!title.pendingRename) return + { + titleRef = el + }} + value={title.draft} + disabled={title.saving} + class="text-14-medium text-text-strong grow-1 min-w-0 pl-2 rounded-[6px]" + style={{ "--inline-input-shadow": "var(--shadow-xs-border-select)" }} + onInput={(event) => setTitle("draft", event.currentTarget.value)} + onKeyDown={(event) => { + event.stopPropagation() + if (event.key === "Enter") { event.preventDefault() - setTitle("pendingRename", false) - openTitleEditor() - }} - > - { - setTitle("pendingRename", true) - setTitle("menuOpen", false) + void saveTitleEditor() + return + } + if (event.key === "Escape") { + event.preventDefault() + closeTitleEditor() + } + }} + onBlur={closeTitleEditor} + /> + + +
+ + {(id) => ( +
+ + setTitle("menuOpen", open)} + > + + + { + if (!title.pendingRename) return + event.preventDefault() + setTitle("pendingRename", false) + openTitleEditor() }} > - {language.t("common.rename")} - - void archiveSession(id())}> - {language.t("common.archive")} - - - dialog.show(() => )} - > - {language.t("common.delete")} - - - - -
- )} -
-
-
-
- -
- 0 || props.historyMore}> -
- + { + setTitle("pendingRename", true) + setTitle("menuOpen", false) + }} + > + {language.t("common.rename")} + + void archiveSession(id())}> + {language.t("common.archive")} + + + dialog.show(() => )} + > + {language.t("common.delete")} + + + + +
+ )} +
+
- - {(messageID) => { - const active = createMemo(() => activeMessageID() === messageID) - const queued = createMemo(() => { - if (active()) return false - const activeID = activeMessageID() - if (activeID) return messageID > activeID - return false - }) - const comments = createMemo(() => messageComments(sync.data.part[messageID] ?? []), [], { - equals: (a, b) => JSON.stringify(a) === JSON.stringify(b), - }) - const commentCount = createMemo(() => comments().length) - return ( -
{ - props.onRegisterMessage(el, messageID) - onCleanup(() => props.onUnregisterMessage(messageID)) - }} - classList={{ - "min-w-0 w-full max-w-full": true, - "md:max-w-200 2xl:max-w-[1000px]": props.centered, - }} + +
+ 0 || props.historyMore}> +
+ +
+
+ + {(messageID) => { + const active = createMemo(() => activeMessageID() === messageID) + const queued = createMemo(() => { + if (active()) return false + const activeID = activeMessageID() + if (activeID) return messageID > activeID + return false + }) + const comments = createMemo(() => messageComments(sync.data.part[messageID] ?? []), [], { + equals: (a, b) => JSON.stringify(a) === JSON.stringify(b), + }) + const commentCount = createMemo(() => comments().length) + return ( +
{ + props.onRegisterMessage(el, messageID) + onCleanup(() => props.onUnregisterMessage(messageID)) + }} + classList={{ + "min-w-0 w-full max-w-full": true, + "md:max-w-200 2xl:max-w-[1000px]": props.centered, + }} + > + 0}> +
+
+
+ + {(commentAccessor: () => MessageComment) => { + const comment = createMemo(() => commentAccessor()) + return ( +
+
+ + {getFilename(comment().path)} + + {(selection) => ( + + {selection().startLine === selection().endLine + ? `:${selection().startLine}` + : `:${selection().startLine}-${selection().endLine}`} + + )} + +
+
+ {comment().comment} +
-
- ) - }} - + ) + }} + +
-
- - -
- ) - }} -
+
+ +
+ ) + }} + +
-- cgit v1.2.3 From 64b21135f922e20ced02f9233dbff6aa88e8deaa Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 4 Mar 2026 07:39:25 -0600 Subject: fix(app): delay dock animation on session load --- packages/app/src/pages/session.tsx | 1 + .../session/composer/session-composer-region.tsx | 43 +++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'packages/app/src/pages/session') diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 389c0baea..cc81ae7b6 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -1254,6 +1254,7 @@ export default function Page() { { inputRef = el diff --git a/packages/app/src/pages/session/composer/session-composer-region.tsx b/packages/app/src/pages/session/composer/session-composer-region.tsx index a882e25dd..93ea3d465 100644 --- a/packages/app/src/pages/session/composer/session-composer-region.tsx +++ b/packages/app/src/pages/session/composer/session-composer-region.tsx @@ -1,4 +1,5 @@ import { Show, createEffect, createMemo, createSignal, onCleanup } from "solid-js" +import { createStore } from "solid-js/store" import { useParams } from "@solidjs/router" import { useSpring } from "@opencode-ai/ui/motion-spring" import { PromptInput } from "@/components/prompt-input" @@ -12,6 +13,7 @@ import { SessionTodoDock } from "@/pages/session/composer/session-todo-dock" export function SessionComposerRegion(props: { state: SessionComposerState + ready: boolean centered: boolean inputRef: (el: HTMLDivElement) => void newSessionWorktree: string @@ -61,7 +63,44 @@ export function SessionComposerRegion(props: { setSessionHandoff(sessionKey(), { prompt: previewPrompt() }) }) - const open = createMemo(() => props.state.dock() && !props.state.closing()) + const [gate, setGate] = createStore({ + ready: false, + }) + let timer: number | undefined + let frame: number | undefined + + const clear = () => { + if (timer !== undefined) { + window.clearTimeout(timer) + timer = undefined + } + if (frame !== undefined) { + cancelAnimationFrame(frame) + frame = undefined + } + } + + createEffect(() => { + sessionKey() + const ready = props.ready + const delay = 140 + + clear() + setGate("ready", false) + if (!ready) return + + frame = requestAnimationFrame(() => { + frame = undefined + timer = window.setTimeout(() => { + setGate("ready", true) + timer = undefined + }, delay) + }) + }) + + onCleanup(clear) + + const open = createMemo(() => gate.ready && props.state.dock() && !props.state.closing()) const config = createMemo(() => open() ? { @@ -76,7 +115,7 @@ export function SessionComposerRegion(props: { const progress = useSpring(() => (open() ? 1 : 0), config) const value = createMemo(() => Math.max(0, Math.min(1, progress()))) const [height, setHeight] = createSignal(320) - const dock = createMemo(() => props.state.dock() || value() > 0.001) + const dock = createMemo(() => (gate.ready && props.state.dock()) || value() > 0.001) const full = createMemo(() => Math.max(78, height())) const [contentRef, setContentRef] = createSignal() -- cgit v1.2.3 From a69742ccb26ad70d7442a133d86b69725af1ef06 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 4 Mar 2026 07:43:28 -0600 Subject: fix(app): remove blur from todos --- packages/app/src/pages/session/composer/session-todo-dock.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'packages/app/src/pages/session') diff --git a/packages/app/src/pages/session/composer/session-todo-dock.tsx b/packages/app/src/pages/session/composer/session-todo-dock.tsx index ab8755aec..da2b8c8da 100644 --- a/packages/app/src/pages/session/composer/session-todo-dock.tsx +++ b/packages/app/src/pages/session/composer/session-todo-dock.tsx @@ -281,10 +281,8 @@ function TodoList(props: { todos: Todo[]; open: boolean }) { style={{ "--checkbox-align": "flex-start", "--checkbox-offset": "1px", - transition: - "opacity 220ms var(--tool-motion-ease, cubic-bezier(0.22, 1, 0.36, 1)), filter 220ms var(--tool-motion-ease, cubic-bezier(0.22, 1, 0.36, 1))", + transition: "opacity 220ms var(--tool-motion-ease, cubic-bezier(0.22, 1, 0.36, 1))", opacity: todo().status === "pending" ? "0.94" : "1", - filter: todo().status === "pending" ? "blur(0.3px)" : "blur(0px)", }} > -- cgit v1.2.3