Skip to content

fix(comments): prevent flicker when clicking comment with tracked changes#2986

Merged
caio-pizzol merged 6 commits into
superdoc-dev:mainfrom
gpardhivvarma:fix/comment-flicker-tracked-changes
Apr 29, 2026
Merged

fix(comments): prevent flicker when clicking comment with tracked changes#2986
caio-pizzol merged 6 commits into
superdoc-dev:mainfrom
gpardhivvarma:fix/comment-flicker-tracked-changes

Conversation

@gpardhivvarma
Copy link
Copy Markdown
Contributor

Summary

Closes #2861

Fixes rapid flickering when clicking a comment that contains a tracked change inside inline structured content.

Root Cause

When a comment is activated via sidebar click, comments-plugin.js correctly sets activeThreadId and returns early. However, the resulting DOM update triggers a ProseMirror selection-sync transaction. This secondary transaction hits position-based active comment detection (getActiveCommentId), which fails to resolve the comment inside tracked-change/structured-content nodes and returns null — clearing the active comment, triggering another DOM rebuild, and repeating in a loop.

Fix

Add explicitlySetThreadId flag to CommentsPlugin state. When a comment is activated via explicit action (setActiveComment meta), the flag is set. On subsequent selection-only transactions:

  • If cursor is still inside the explicitly activated comment's range → skip position-based detection (breaks the flicker loop)
  • If cursor moves outside the comment range → clear flag, resume normal detection
  • On document changes → clear flag (user is editing, detection should resume)

This extends the same principle already used at line 426-428 where setCursorById skips view.focus() to prevent DOM selection sync from overriding the active thread.

Also removes dead code: trChangedActiveComment variable was always false at the detection block because setActiveComment returns early at line 488.

Changes

File Change
comments-plugin.js Add explicitlySetThreadId to plugin state, guard position-based detection, clear on cursor-out and doc-change, remove dead code
comments-plugin.test.js 6 new tests

Tests

  1. Flag set on explicit activation
  2. Preserved on cursor-within (collapsed selection)
  3. Cleared when cursor moves outside comment range
  4. Preserved with tracked-change + comment marks (the actual bug scenario)
  5. Range selections bypass the guard (non-collapsed)
  6. Cleared on document change

Test plan

  • comments-plugin.test.js — 66/66 passing
  • Manual: open superdoc.dev, click the third comment (Added "WYSIWYG") — should not flicker
  • Manual: click a comment, then click elsewhere — should deactivate normally
  • Manual: click a comment, then type — detection resumes after edit

@gpardhivvarma
Copy link
Copy Markdown
Contributor Author

@caio-pizzol

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

@caio-pizzol caio-pizzol left a comment

Choose a reason for hiding this comment

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

hey @gpardhivvarma! good call going after this, but the live demo still flickered with the original guard.

clicking a tracked-change comment fires two selection changes back to back: cursor first, then a range over the whole tracked span. your guard only kicks in for a cursor, so the range part still cleared the active comment and the host kept re-setting it.

i pushed a one-line change to your branch (range selections no longer count as "user moved off"), plus unit and behavior tests. flicker went from ~700 class flips per 2s to 2.

left two inline.

lgtm once you decide on the flag.

Comment thread packages/super-editor/src/editors/v1/extensions/comment/comments-plugin.js Outdated
Comment thread packages/super-editor/src/editors/v1/extensions/comment/comments-plugin.js Outdated
@gpardhivvarma
Copy link
Copy Markdown
Contributor Author

gpardhivvarma commented Apr 29, 2026

@caio-pizzol

Both comments addressed:

  1. Flag removed — dropped explicitlySetThreadId entirely. Your isNonCollapsedClear handles the actual trigger.
  2. Mutation fixed — moot now since the flag is gone, but the dead code removal and condition simplification from the original commit are preserved.

Ready for re-review.

gpardhivvarma and others added 6 commits April 29, 2026 16:09
…nges

Add explicitlySetThreadId flag to CommentsPlugin state to prevent
position-based active comment detection from overriding sidebar-initiated
comment activation. When a comment is explicitly activated (e.g., sidebar
click), subsequent DOM-sync selection transactions preserve the active
comment as long as the cursor remains within its range.

The flag clears naturally when the cursor moves outside the comment range
or when the document is edited, allowing position-based detection to
resume for normal user navigation.

Closes superdoc-dev#2861
…superdoc-dev#2861)

getActiveCommentId returns undefined for any non-collapsed selection. The
plugin coerced that into commentsUpdate({activeCommentId: null}), which the
host listener echoed back as a fresh setActiveComment dispatch. For tracked
changes inside an inline SDT, presentation.navigateTo dispatches a collapsed
cursor placement followed by a non-collapsed NodeSelection on the SDT
wrapper, so the second tx blanked the just-activated comment and triggered a
flicker loop (~400 toggles/sec on .track-change-focused).

Skip the emit when getActiveCommentId returned no information for a
non-collapsed selection. A non-collapsed selection is not a reliable signal
that the user moved off the comment.
Four tests pinning the new contract:
- preserves activeThreadId when a non-collapsed selection follows explicit
  activation
- preserves activeThreadId when a follow-up non-collapsed selection sits
  entirely within the comment range (the WYSIWYG repro shape)
- still clears activeThreadId when a collapsed cursor moves outside the
  comment range (existing behavior preserved)
- does not enter a dispatch loop when a host listener re-asserts after each
  commentsUpdate (models the SuperDoc.vue store round-trip)

Three of the four fail without the plugin fix.
…uperdoc-dev#2861)

Programmatically reproduces the two-transaction pattern from
presentation.navigateTo at the live editor level: setActiveComment on a
comment-marked range, then a non-collapsed selection over the same range.
Counts dispatches and class toggles on .track-change-focused.

Without the plugin fix, dispatchCount climbs into the hundreds within a
second as the host re-asserts on every commentsUpdate emit. With the fix,
both counts stay bounded and the active comment survives.
Address review feedback — avoid mutating pluginState directly before
spreading. Use conditional copy pattern consistent with Caio's suggestion.
Drop the flag in favor of Caio's isNonCollapsedClear guard, which
handles the actual flicker trigger (range selection from SDT wrapper).
Keeps the dead code removal and condition simplification from the
original commit.
@gpardhivvarma gpardhivvarma force-pushed the fix/comment-flicker-tracked-changes branch from 5f6b8d9 to d6463a2 Compare April 29, 2026 10:39
Copy link
Copy Markdown
Contributor

@caio-pizzol caio-pizzol left a comment

Choose a reason for hiding this comment

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

hey @gpardhivvarma! thanks for cleaning that up.

re-ran the click test, no flicker. lgtm.

@caio-pizzol caio-pizzol enabled auto-merge April 29, 2026 11:02
@caio-pizzol caio-pizzol added this pull request to the merge queue Apr 29, 2026
Merged via the queue into superdoc-dev:main with commit 98c540a Apr 29, 2026
55 checks passed
@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented Apr 29, 2026

🎉 This PR is included in @superdoc-dev/mcp v0.3.0-next.5

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented Apr 29, 2026

🎉 This PR is included in vscode-ext v2.3.0-next.52

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented Apr 29, 2026

🎉 This PR is included in @superdoc-dev/react v1.2.0-next.50

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented Apr 29, 2026

🎉 This PR is included in superdoc v1.30.0-next.10

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented Apr 29, 2026

🎉 This PR is included in superdoc-cli v0.8.0-next.25

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented Apr 29, 2026

🎉 This PR is included in superdoc-sdk v1.8.0-next.10

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented Apr 30, 2026

🎉 This PR is included in superdoc v1.30.0

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 1, 2026

🎉 This PR is included in superdoc-cli v0.8.0

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 1, 2026

🎉 This PR is included in superdoc-sdk v1.8.0

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 1, 2026

🎉 This PR is included in @superdoc-dev/mcp v0.3.0

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 5, 2026

🎉 This PR is included in vscode-ext v2.3.0

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 7, 2026

🎉 This PR is included in @superdoc-dev/react v1.3.0

The release is available on GitHub release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rapid flicker when clicking a comment

3 participants