Skip to content

fix(content-preview): keep compare open when clicking compared-pane annotation - #4842

Closed
zhirongwang wants to merge 1 commit into
box:masterfrom
zhirongwang:fix/preview-1895-compare-annotation-teardown
Closed

zhirongwang wants to merge 1 commit into
box:masterfrom
zhirongwang:fix/preview-1895-compare-annotation-teardown

Conversation

@zhirongwang

@zhirongwang zhirongwang commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Summary

In side-by-side version compare, clicking an annotation on the compared (older-version) pane tore down the compare view — the compared pane unmounted and the annotation disappeared — and the Activity sidebar never switched from version history to the annotation thread.

Root cause

Clicking an annotation on the compared pane emits annotations_active_change on the shared annotator event manager. withSidebarAnnotations.updateActiveVersion then rewrites the activity path's fileVersionId and calls onVersionChange; SidebarPanels additionally emits onVersionChange(null) when leaving the versions route. A comparing ContentPreview forwarded both to the host, which interpreted them as the user leaving version compare and unmounted the compared pane.

Changes

  • withSidebarAnnotations: tag annotation-driven onVersionChange calls with origin: 'annotation' (both router and router-disabled paths)
  • SidebarPanels: when leaving the versions route for an annotations path, emit onVersionChange(null, { origin: 'annotation' })
  • ContentPreview.onVersionChange: when isComparing and the change carries origin: 'annotation', don't forward to the host — compare stays open while the sidebar switches to the thread. Versions-sidebar clicks (no origin) still notify the host as before.
  • Compared pane now inherits the host's showAnnotations / boxAnnotations so annotations render on the compared version, with create, drawing, and discoverability explicitly disabled (PREVIEW-1818)
  • flowTypes: added origin?: 'annotation' to AdditionalVersionInfo

Tests

  • New integration test SidebarPanels.annotationCompare.rtl.test.js: a compared-pane annotation click pushes the annotation thread path and every resulting onVersionChange carries origin: 'annotation'
  • New unit tests in ContentPreview.test.js (suppression only when comparing + annotation origin) and SidebarPanels.test.js (versions-route exit tagging)
  • All affected suites pass (591 tests via pre-push --changedSince)

Related: PREVIEW-1876 (annotator cross-talk fix in box-annotations), PREVIEW-1818 (second annotator in the compared pane)

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where selecting annotations while comparing versions could unexpectedly disrupt the compared pane.
    • Annotation-driven navigation now preserves the correct version context without sending unintended version changes to the host.
    • Compared content now respects the configured annotation visibility settings while keeping annotation creation and discovery controls disabled.
    • Improved transitions between version and annotation views, including resetting version selections when appropriate.

…nnotation

Clicking an annotation on the compared (older-version) pane rewrites the
activity path's fileVersionId and fires onVersionChange; SidebarPanels also
emits onVersionChange(null) when leaving the versions route. A comparing
ContentPreview forwarded both to the host, which unmounted the compared pane.

- Tag annotation-driven version changes with origin: 'annotation' in
  withSidebarAnnotations and SidebarPanels
- ContentPreview.onVersionChange suppresses forwarding to the host when
  isComparing and origin is 'annotation', so compare stays open while the
  sidebar switches to the annotation thread
- Compared pane inherits host showAnnotations/boxAnnotations so annotations
  render on the compared version, with create/discoverability off (PREVIEW-1818)

PREVIEW-1895

Co-authored-by: Cursor <cursoragent@cursor.com>
@zhirongwang
zhirongwang requested review from a team as code owners September 18, 2026 01:02
@coderabbitai

coderabbitai Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 07df457a-5128-4d0c-8062-cb2d30ea64a5

📥 Commits

Reviewing files that changed from the base of the PR and between a4ca178 and d5927b2.

📒 Files selected for processing (7)
  • src/elements/common/flowTypes.js
  • src/elements/content-preview/ContentPreview.js
  • src/elements/content-preview/__tests__/ContentPreview.test.js
  • src/elements/content-sidebar/SidebarPanels.js
  • src/elements/content-sidebar/__tests__/SidebarPanels.annotationCompare.rtl.test.js
  • src/elements/content-sidebar/__tests__/SidebarPanels.test.js
  • src/elements/content-sidebar/withSidebarAnnotations.js

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


Walkthrough

The change tags annotation-driven version updates, propagates the tag through sidebar navigation, and prevents comparison mode from forwarding those updates to the host. The compared pane now inherits annotation visibility settings while disabling annotation creation and discoverability.

Changes

Annotation-aware version comparison

Layer / File(s) Summary
Annotation origin propagation
src/elements/common/flowTypes.js, src/elements/content-sidebar/SidebarPanels.js, src/elements/content-sidebar/withSidebarAnnotations.js, src/elements/content-sidebar/__tests__/*
AdditionalVersionInfo accepts an annotation origin. Annotation route transitions and annotation navigation pass this origin with version changes. Tests cover route resets and compared-pane annotation navigation.
Comparison pane handling
src/elements/content-preview/ContentPreview.js, src/elements/content-preview/__tests__/ContentPreview.test.js
Comparison mode suppresses host callbacks for annotation-originated version changes. The compared pane inherits annotation visibility settings and disables annotation creation and discoverability. Tests cover callbacks and inherited props.

Priority: ⬇️ Low

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

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Annotator
  participant SidebarPanels
  participant ContentPreview
  participant Host
  Annotator->>SidebarPanels: emit annotation selection
  SidebarPanels->>SidebarPanels: navigate to annotation route
  SidebarPanels->>ContentPreview: pass annotation-originated version change
  ContentPreview->>ContentPreview: detect comparison mode
  ContentPreview-->>Host: suppress version change callback
Loading

Suggested reviewers: greg-in-a-box

Merge Risk: ⚪ Minimal · up to d5927

The comparison flow retains the selected annotation thread without forwarding annotation-driven version changes to the host. No actionable current-head risk remains.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 7 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly and concisely describes the primary fix: keeping comparison open when a user clicks an annotation in the compared pane.
Description check ✅ Passed The description explains the problem, root cause, implementation changes, affected behavior, tests, and related issues. It provides sufficient information for review and matches the repository templat…
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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

I hop through routes with tags in tow
The compared pane stays put below
Annotation marks remain in view
Creation tools stay quiet too
The host hears only changes due

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

@greg-in-a-box greg-in-a-box 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.

Review summary

Reviewed the PREVIEW-1895 fix end-to-end: annotation-driven onVersionChange tagging (withSidebarAnnotations router + router-disabled paths, SidebarPanels versions→annotations exit), ContentPreview.onVersionChange suppression gated on isComparing && origin === 'annotation', and compared-pane annotation inheritance with create/discoverability explicitly off.

Verdict: approve

This is a clean, well-scoped fix for the compare teardown bug.

What looks correct

  • Suppression is narrow: versions-sidebar clicks (no origin) still notify the host while comparing — covered by the existing unit test and left intact.
  • Both teardown sources are tagged: updateActiveVersion (version object) and the SidebarPanels null reset when leaving /versions for an annotations path.
  • additionalVersionInfo defaults to {} in ContentPreview.onVersionChange, so the .origin check is safe.
  • Non-comparing path still forwards annotation-origin events to the host (including the null reset).
  • Compared pane: inheriting showAnnotations / boxAnnotations while forcing create + discoverability off matches PREVIEW-1818 and avoids opening a composer on text select.
  • Test coverage is strong: unit cases for suppress/forward matrix, SidebarPanels path tagging table, compared-pane prop inheritance, plus the RTL integration that asserts every onVersionChange from a compared-pane annotation click carries origin: 'annotation'.

Nits (non-blocking)

  • SIDEBAR_PATH_ANNOTATIONS (/:sidebar/annotations/...) is slightly looser than the real activity route (/activity/.../annotations/...). Harmless in practice; tightening to activity-only would match production routes more closely.
  • AdditionalVersionInfo.updateVersionToCurrent remains required in the Flow type while SidebarPanels still passes { origin: 'annotation' } without it — pre-existing shape mismatch, not introduced here.

No material correctness, regression, or missing-test issues. LGTM.

@greg-in-a-box greg-in-a-box 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.

Verdict: Approve

Solid fix for PREVIEW-1895. The origin: 'annotation' tagging cleanly separates annotation-driven path changes from versions-sidebar clicks, and suppressing those in ContentPreview.onVersionChange only while isComparing is the right place to keep side-by-side compare mounted.

What looks good

  • Root cause and fix match: both the withSidebarAnnotations version report and the SidebarPanels versions-route exit are tagged, which covers the two events that were tearing down compare.
  • Compared pane inheriting showAnnotations / boxAnnotations via {...rest} while explicitly disabling create/discoverability/drawing create matches PREVIEW-1818 intent and is covered by a unit test.
  • Integration test (SidebarPanels.annotationCompare.rtl.test.js) actually exercises the annotator → sidebar path → tagged onVersionChange chain, not just the leaf helpers.
  • Existing “comparing still notifies host when origin is absent” behavior is preserved and still tested.

Nits (non-blocking)

  • AdditionalVersionInfo.updateVersionToCurrent is still required in Flow, but the versions-route exit path has always called onVersionChange(null) / now onVersionChange(null, { origin: 'annotation' }) without it. Worth making that field optional when you next touch the type.
  • SidebarPanels still only tags the location-based exit (no routerDisabled / internal-nav equivalent). Same pre-existing shape as before; fine if compare + annotations always use the router path today.

LGTM.

@greg-in-a-box greg-in-a-box 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.

Review

Nice, targeted fix for PREVIEW-1895. Tagging annotation-driven onVersionChange with origin: 'annotation' and suppressing host forwarding only while isComparing is a clean way to keep side-by-side compare mounted without changing versions-sidebar behavior.

What looks good

  • withSidebarAnnotations and SidebarPanels both tag the paths that were tearing down compare (active-version update + versions-route exit into an annotations path).
  • Compared pane inheriting showAnnotations / boxAnnotations while forcing create/discoverability off matches PREVIEW-1818 intent.
  • Unit coverage for the suppress/forward matrix and the new RTL integration test that asserts every resulting onVersionChange carries origin: 'annotation' are convincing.

Nits (non-blocking)

  • SIDEBAR_PATH_ANNOTATIONS (/:sidebar/annotations/...) is a looser pattern than the activity Route’s /:activeFeedEntryType(annotations)/.... It matches today’s paths, but tying the componentDidUpdate check to the same helper/constant as the Route (or getAnnotationsMatchPath) would reduce drift risk.
  • Confirm in a quick compare-mode pass that showAnnotationsDrawing={false} does not hide existing drawing annotations on the compared version (docs call out showAnnotationsDrawingCreate for create; if drawing view is gated by the non-Create flag, prefer leaving view on and only disabling create/discoverability).

Approved from my side assuming CI stays green.

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.

2 participants