fix(app): preserve todo dock across sessions (#33778)

This commit is contained in:
Brendan Allan 2026-06-25 13:34:37 +08:00 committed by GitHub
commit d13779b1d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 765 additions and 219 deletions

View file

@ -1,11 +1,27 @@
// @ts-nocheck
import { createStore } from "solid-js/store"
import type { Todo } from "@opencode-ai/sdk/v2"
import { createPromptState } from "@/context/prompt"
import { SessionComposerRegion } from "@/pages/session/composer"
import { createPromptInputHistory, PromptInput } from "./prompt-input"
function PromptInputExample() {
function createPromptInputStoryRuntime() {
const state = createPromptState()
const history = createPromptInputHistory()
return {
state,
history: createPromptInputHistory(),
submission: {
abort() {},
handleSubmit(event: Event) {
event.preventDefault()
state.reset()
},
},
}
}
function PromptInputExample() {
const input = createPromptInputStoryRuntime()
const [controls, setControls] = createStore({
agent: "build",
variant: undefined as string | undefined,
@ -22,13 +38,6 @@ function PromptInputExample() {
set: (variant?: string) => setControls("variant", variant),
},
}
const submission = {
abort() {},
handleSubmit(event: Event) {
event.preventDefault()
state.reset()
},
}
const inputControls = {
agents: {
available: [{ name: "review", hidden: false, mode: "subagent" }],
@ -69,7 +78,7 @@ function PromptInputExample() {
const addReviewComment = () => {
const comment = controls.comments + 1
setControls("comments", comment)
state.context.add({
input.state.context.add({
type: "file",
path: "src/components/prompt-input.tsx",
selection: {
@ -87,7 +96,7 @@ function PromptInputExample() {
return (
<div class="flex flex-col gap-3">
<PromptInput controls={inputControls} state={state} history={history} submission={submission} />
<PromptInput controls={inputControls} {...input} />
<div>
<button
type="button"
@ -101,6 +110,82 @@ function PromptInputExample() {
)
}
const todos: Todo[] = [
{ id: "todo-1", content: "Inspect the session composer animation", status: "completed" },
{ id: "todo-2", content: "Keep the dock settled on initial render", status: "in_progress" },
{ id: "todo-3", content: "Verify session navigation behavior", status: "pending" },
]
function PromptInputWithOpenDock() {
const input = createPromptInputStoryRuntime()
const [controls, setControls] = createStore({
agent: "build",
activeTab: undefined as string | undefined,
todoCollapsed: false,
})
const inputControls = {
agents: {
available: [],
options: ["build"],
get current() {
return controls.agent
},
loading: false,
visible: true,
select: (agent?: string) => setControls("agent", agent ?? "build"),
},
model: {
selection: {
current: () => ({ id: "claude-3-7-sonnet", name: "Claude 3.7 Sonnet", provider: { id: "anthropic" } }),
variant: { list: () => [], current: () => undefined, set: () => {} },
},
paid: true,
loading: false,
},
projects: { available: [], directory: "/tmp/story", select: () => {}, add: () => {} },
session: {
id: "story-session",
tabs: {
active: () => controls.activeTab,
all: () => [],
open: () => {},
setActive: (tab: string) => setControls("activeTab", tab),
},
reviewPanel: { opened: () => false, open: () => {} },
},
newLayoutDesigns: true,
}
const state = {
blocked: () => false,
questionRequest: () => undefined,
permissionRequest: () => undefined,
permissionResponding: () => false,
decide: () => {},
todos: () => todos,
dock: () => true,
closing: () => false,
opening: () => false,
}
return (
<SessionComposerRegion
state={state}
sessionKey="story-session"
sessionID="story-session"
controls={inputControls}
promptInput={{ ...input, ref: () => {}, newSessionWorktree: "", onNewSessionWorktreeReset: () => {} }}
todo={{
collapsed: controls.todoCollapsed,
onToggle: () => setControls("todoCollapsed", (collapsed) => !collapsed),
}}
ready
centered={false}
onResponseSubmit={() => {}}
setPromptDockRef={() => {}}
/>
)
}
export default {
title: "App/PromptInput",
id: "app-prompt-input",
@ -115,3 +200,12 @@ export const Basic = {
</div>
),
}
export const DockAlreadyOpen = {
render: () => (
<div class="pt-10">
<h1 class="mb-4">Prompt Input with open Todo dock</h1>
<PromptInputWithOpenDock />
</div>
),
}