Browse Source

fix(app): batch new session tab navigation (#34196)

Brendan Allan 1 month ago
parent
commit
2caa016fe1
2 changed files with 14 additions and 12 deletions
  1. 3 1
      packages/app/src/components/titlebar.tsx
  2. 11 11
      packages/app/src/context/tabs.tsx

+ 3 - 1
packages/app/src/components/titlebar.tsx

@@ -99,6 +99,8 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
 
   const path = () => `${location.pathname}${location.search}${location.hash}`
   const creating = createMemo(() => {
+    const route = layout.route()
+    if (route.type === "draft" || route.type === "dir-new-sesssion") return true
     if (!params.dir) return false
     if (params.id) return false
     const parts = location.pathname.replace(/\/+$/, "").split("/")
@@ -466,7 +468,7 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
                   }}
                   onReorder={(keys) => tabsStoreActions.reorder(keys)}
                 />
-                <Show when={!(creating() && params.dir)}>
+                <Show when={!creating()}>
                   <TooltipV2
                     placement="bottom"
                     value={

+ 11 - 11
packages/app/src/context/tabs.tsx

@@ -163,12 +163,14 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({
       },
       newDraft(draft: Omit<DraftTab, "type" | "draftID">, prompt?: string) {
         const draftID = uuid()
-        setStore(
-          produce((tabs) => {
-            tabs.push({ type: "draft", draftID, ...draft })
-          }),
-        )
-        navigate(prompt ? `${draftHref(draftID)}&prompt=${encodeURIComponent(prompt)}` : draftHref(draftID))
+        void startTransition(() => {
+          setStore(
+            produce((tabs) => {
+              tabs.push({ type: "draft", draftID, ...draft })
+            }),
+          )
+          navigate(prompt ? `${draftHref(draftID)}&prompt=${encodeURIComponent(prompt)}` : draftHref(draftID))
+        })
       },
       updateDraft(draftID: string, draft: Partial<Omit<DraftTab, "type" | "draftID">>) {
         setStore(
@@ -177,13 +179,11 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({
         )
       },
       promoteDraft(draftID: string, session: Omit<SessionTab, "type">) {
-        // We're viewing this draft when /new-session?draftId=… points at it. Promoting
-        // replaces the draft tab with a session tab, so the draft route would stop resolving
-        // and fall back home. Navigate to the new session first so we leave /new-session
-        // before the draft is removed from the store.
+        // Keep the replacement and navigation atomic so /new-session never renders
+        // after its backing draft tab has been removed from the store.
         const active = location.pathname === "/new-session" && location.query.draftId === draftID
         const next = { type: "session" as const, ...session }
-        startTransition(() => {
+        void startTransition(() => {
           setStore(
             produce((tabs) => {
               const index = tabs.findIndex((tab) => tab.type === "draft" && tab.draftID === draftID)