diff --git a/desktop/frontend/src/App.tsx b/desktop/frontend/src/App.tsx index 35e193000..9c4a45d0a 100644 --- a/desktop/frontend/src/App.tsx +++ b/desktop/frontend/src/App.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useDeferredValue, useEffect, useMemo, useRef, useState } from "react"; import type { CSSProperties, KeyboardEvent, PointerEvent as ReactPointerEvent } from "react"; import { SquarePen, @@ -257,6 +257,12 @@ export default function App() { todos.length > 0 && todos.some((t) => t.status !== "completed"); + // useDeferredValue lets React prioritise Composer input (high-priority) over + // Transcript re-renders (low-priority) during streaming. When a keystroke + // and a transcript update collide, the keystroke is processed immediately + // and the transcript re-render is deferred to idle time. + const deferredItems = useDeferredValue(state.items); + useEffect(() => { if (!pendingPlanRevision || state.running) return; const text = pendingPlanRevision; @@ -927,7 +933,7 @@ export default function App() { {t("common.loading")} ) : ( - + )}