Skip to content

fix(web): prevent streamed search result navigation cancellation - #1577

Merged
brendan-kellam merged 3 commits into
mainfrom
brendan/fix-streaming-search-navigation
Aug 13, 2026
Merged

fix(web): prevent streamed search result navigation cancellation#1577
brendan-kellam merged 3 commits into
mainfrom
brendan/fix-streaming-search-navigation

Conversation

@brendan-kellam

@brendan-kellam brendan-kellam commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • preserve Next.js internal history state when saving search-result scroll restoration data
  • omit the URL from replaceState so streamed measurement updates cannot cancel pending result navigation
  • add regression coverage for navigation during streamed-result updates and back-navigation restoration state

Testing

  • yarn workspace @sourcebot/web test --run "src/app/(app)/search/components/searchResultsPanel/index.test.tsx" "src/app/(app)/search/components/searchResultsPanel/fileMatch.test.tsx"
  • yarn workspace @sourcebot/web lint
  • targeted TypeScript check for changed files

Note

Low Risk
Localized search UI history/scroll restoration change with regression coverage; no auth, API, or data-path impact.

Overview
Fixes in-flight navigation to a file being aborted when streamed search results arrive and the results panel refreshes virtualizer measurements.

SearchResultsPanel now writes scroll restoration data with history.replaceState by merging into the current history.state (keeping Next.js internals like __NA) and drops the URL argument, so Next.js 16’s patched replaceState no longer treats the update as a route restore while a result link navigation is pending. Scroll offset, measurement cache, and expanded-match state still persist for back navigation.

Adds a regression test that simulates Next.js’s replaceState behavior during a click-to-browse while the match list grows from streaming.

Reviewed by Cursor Bugbot for commit 624df1a. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed streamed code search updates cancelling in-progress result navigation.
    • Preserved search navigation state, including scroll position, expanded matches, and measurements, during result updates.
    • Ensured navigation continues to the selected file after streamed results refresh.
  • Tests

    • Added coverage for search result navigation and history-state preservation.

@github-actions

This comment has been minimized.

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0c2f3389-afbb-4ed2-b84f-e3544c12727b

📥 Commits

Reviewing files that changed from the base of the PR and between 86ea4d9 and 624df1a.

📒 Files selected for processing (1)
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md

Walkthrough

The search results panel now preserves existing Next.js history metadata during scroll-state updates. Tests cover streamed result rerenders, navigation continuity, virtualization state restoration, and final browse navigation. The changelog documents the fix.

Changes

Search history state

Layer / File(s) Summary
History update and navigation validation
packages/web/src/app/(app)/search/components/searchResultsPanel/index.tsx, packages/web/src/app/(app)/search/components/searchResultsPanel/index.test.tsx, CHANGELOG.md
history.replaceState preserves existing state and omits the URL argument while storing panel state. Tests validate streamed result navigation and restored virtualization data. The changelog records the fix.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Mergeability Score: ⚪ Minimal · up to 624df

This localized change preserves search navigation and scroll-restoration state during streamed result updates; no actionable merge-blocking risk remains after normal checks and review.

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: preventing streamed search result updates from cancelling pending navigation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan/fix-streaming-search-navigation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/web/src/app/(app)/search/components/searchResultsPanel/index.tsx (1)

104-112: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Preserve the ScrollHistoryState type check

history.state is any, so spreading it prevents satisfies ScrollHistoryState from rejecting incompatible field values. Build the scroll state in a separately typed object before merging it with history.state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/src/app/`(app)/search/components/searchResultsPanel/index.tsx
around lines 104 - 112, Update the history state construction in the search
results panel to create a separately typed ScrollHistoryState object before
merging with history.state, so its fields are validated by the satisfies check.
Preserve the existing scrollOffset, measurementsCache, and showAllMatchesMap
values, then pass the merged state to history.replaceState.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/web/src/app/`(app)/search/components/searchResultsPanel/index.tsx:
- Around line 104-112: Update the history state construction in the search
results panel to create a separately typed ScrollHistoryState object before
merging with history.state, so its fields are validated by the satisfies check.
Preserve the existing scrollOffset, measurementsCache, and showAllMatchesMap
values, then pass the merged state to history.replaceState.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f233dfe3-3727-429c-953b-7db427b7af83

📥 Commits

Reviewing files that changed from the base of the PR and between a07c681 and 86ea4d9.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • packages/web/src/app/(app)/search/components/searchResultsPanel/index.test.tsx
  • packages/web/src/app/(app)/search/components/searchResultsPanel/index.tsx

@brendan-kellam
brendan-kellam merged commit 8aae78d into main Aug 13, 2026
13 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/fix-streaming-search-navigation branch August 13, 2026 04:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant