Kaynağa Gözat

fix(app): delay dock animation on session load

Adam 5 ay önce
ebeveyn
işleme
64b21135f9

+ 1 - 0
packages/app/src/pages/session.tsx

@@ -1254,6 +1254,7 @@ export default function Page() {
 
 
           <SessionComposerRegion
           <SessionComposerRegion
             state={composer}
             state={composer}
+            ready={!store.deferRender && messagesReady()}
             centered={centered()}
             centered={centered()}
             inputRef={(el) => {
             inputRef={(el) => {
               inputRef = el
               inputRef = el

+ 41 - 2
packages/app/src/pages/session/composer/session-composer-region.tsx

@@ -1,4 +1,5 @@
 import { Show, createEffect, createMemo, createSignal, onCleanup } from "solid-js"
 import { Show, createEffect, createMemo, createSignal, onCleanup } from "solid-js"
+import { createStore } from "solid-js/store"
 import { useParams } from "@solidjs/router"
 import { useParams } from "@solidjs/router"
 import { useSpring } from "@opencode-ai/ui/motion-spring"
 import { useSpring } from "@opencode-ai/ui/motion-spring"
 import { PromptInput } from "@/components/prompt-input"
 import { PromptInput } from "@/components/prompt-input"
@@ -12,6 +13,7 @@ import { SessionTodoDock } from "@/pages/session/composer/session-todo-dock"
 
 
 export function SessionComposerRegion(props: {
 export function SessionComposerRegion(props: {
   state: SessionComposerState
   state: SessionComposerState
+  ready: boolean
   centered: boolean
   centered: boolean
   inputRef: (el: HTMLDivElement) => void
   inputRef: (el: HTMLDivElement) => void
   newSessionWorktree: string
   newSessionWorktree: string
@@ -61,7 +63,44 @@ export function SessionComposerRegion(props: {
     setSessionHandoff(sessionKey(), { prompt: previewPrompt() })
     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(() =>
   const config = createMemo(() =>
     open()
     open()
       ? {
       ? {
@@ -76,7 +115,7 @@ export function SessionComposerRegion(props: {
   const progress = useSpring(() => (open() ? 1 : 0), config)
   const progress = useSpring(() => (open() ? 1 : 0), config)
   const value = createMemo(() => Math.max(0, Math.min(1, progress())))
   const value = createMemo(() => Math.max(0, Math.min(1, progress())))
   const [height, setHeight] = createSignal(320)
   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 full = createMemo(() => Math.max(78, height()))
   const [contentRef, setContentRef] = createSignal<HTMLDivElement>()
   const [contentRef, setContentRef] = createSignal<HTMLDivElement>()