perf(flowchat): Improve long-session scrolling and history paging - #3198
Merged
Merged
Conversation
Avoid parsing and mounting hidden Markdown when collapsed thinking cards enter the virtual window. Mount content on expansion and release it after the collapse transition settles, preserving rapid reopen behavior and existing typewriter reveal semantics. Cover collapsed content updates, forced expansion, transition completion, cancellation, and reopening with focused tests. Document the lifecycle.
Publish the actual viewport offset after accepted row measurement compensation so window selection uses the updated position. This avoids unmounting measured rows and mounting them again on delayed scroll events. Cover delayed scroll and scroll-end delivery with the real virtualizer.
Narrow Markdown, usage metadata, dispatch checks, and NumberInput sibling selectors to avoid invalidating unrelated transcript elements when virtual rows change. Preserve spacing and border behavior, and add renderer coverage plus frontend CSS invalidation guidance. Matched DOM samples support style-time reductions for usage metadata and dispatch checks. NumberInput and remaining Markdown rules have invalidation evidence, but no confirmed overall scrolling speedup. Validation: focused component tests, TypeScript, SCSS compilation, and theme color audits passed. The full Web UI check remains blocked by existing mobile typography violations.
Capture scroll height immediately before DOM mutation when history moves the old head, rather than reusing a previous commit's height. Keep compensation bounds and viewport ownership unchanged. Cover intervening geometry changes, consecutive prepends, and suspended viewport recovery. Browser performance and remote behavior remain separate validation requirements.
Coalesce label geometry reads before publishing overflow state through a per-window frame queue. Preserve reentrant requests, cancel stale results, and isolate callback failures while reporting their errors. Document the deferred overflow indicator and tooltip timing. Cover batch ordering, cancellation, reentrancy, and window isolation without claiming an overall scrolling speedup.
Only compute summary previews for summary cards. Once a thinking card finishes collapsing, cancel typewriter playback, catch up to the latest content, and release its reveal gate. Preserve playback while closing and resume new text normally after reopening. Cover ordinary and legacy reasoning, summary kind changes, collapse transitions, hidden updates, reopening, and finishing backlogs. Validation: 39 focused tests, TypeScript, and diff checks passed. Browser and remote validation remain pending.
The first page could clear boundary arrival history while leaving the request disarmed, preventing further paging when the reader returned to the top. Replace the independent latches with a paging controller that tracks request completion, committed layout, and coalesced reader demand. Keep prefetch independent of physical boundary arrival and prevent viewport corrections from triggering additional pages. Ignore stale request results and protect newer requests during session changes. Add regression coverage and update the paging contract. Remove temporary instrumentation after the user confirmed the original issue is resolved. Validation: 94 focused tests, Web UI type checking, and focused ESLint pass. Remote transports and the broader input-device matrix remain unverified.
Enable visual JSDOM windows for components using frame-based overflow measurement, and close windows and restore globals after each test. Load JSDOM outside the timeout indicator setup hook. Reuse the ESLint Node API and real file-selected config instead of starting a new CLI process for each adapter-fence probe. Preserve rule assertions without increasing global timeouts or changing production behavior. Validation: pnpm --dir src/web-ui run test:run passes all 858 files and 9293 tests. Focused ESLint and git diff --check also pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Type and Areas
Type: Performance improvement / bug fix / refactor
Areas: Web UI, FlowChat, Markdown rendering, shared design system, docs
Motivation / Impact
Long conversations containing large thinking and tool cards could show substantial temporary blank regions during fast scrolling. Hidden Markdown work, broad CSS invalidation, and stale virtualizer offsets contributed to the cost of changing the visible window.
These changes reduce unnecessary rendering and style work while preserving collapse transitions, Markdown spacing, and viewport ownership. Manual retesting showed substantially fewer temporary blank regions. Matched DOM trace samples also showed lower individual style-recalculation costs; these are individual measurements, not a general speedup guarantee.
A separate paging defect prevented loading more history after the first successful page. Window changes cleared boundary-arrival history while leaving paging disarmed. The new controller supports continued prefetch without requiring physical boundary arrival, preserves demand during loading, and prevents layout compensation from generating additional requests. The user confirmed that the original paging failure is resolved.
Verification
Recorded during implementation and probe cleanup; tests were not rerun solely to prepare this PR description.
Web UI TypeScript: passed.
pnpm --dir src/web-ui exec tsc --noEmitFocused paging, viewport, and prepend regression tests: 94 passed.
pnpm --dir src/web-ui exec vitest run \ src/flow_chat/components/modern/flowChatHistoryPager.test.ts \ src/flow_chat/components/modern/flowChatHistoryBoundary.test.ts \ src/flow_chat/components/modern/VirtualMessageList.session-boundary.test.tsx \ src/flow_chat/components/modern/useFlowChatViewportOwner.test.tsx \ src/flow_chat/components/modern/ModernFlowChatContainer.history-state.test.tsx \ src/flow_chat/components/modern/FlowChatPrependSnapshot.test.tsxEarlier implementation checks passed for thinking-card lifecycle/typewriter behavior, Markdown rendering, OverflowText scheduling, and delayed virtualizer scroll events. The thinking/typewriter change passed 39 focused tests.
Focused ESLint, SCSS compilation, and theme color audits passed during the relevant changes.
Combined diff whitespace check: passed.
Manual evidence:
Limitations:
pnpm run check:webattempt was blocked by existing mobile typography violations.Reviewer Notes
Checklist