Skip to content

Don't repaint comments when no highlight moved#3

Open
Fyko wants to merge 1 commit into
jonesphillip:mainfrom
Fyko:fix/annotation-flash-on-doc-mutation
Open

Don't repaint comments when no highlight moved#3
Fyko wants to merge 1 commit into
jonesphillip:mainfrom
Fyko:fix/annotation-flash-on-doc-mutation

Conversation

@Fyko

@Fyko Fyko commented Jun 25, 2026

Copy link
Copy Markdown

Symptom

Open a document whose own content mutates on a timer (e.g. a live clock doing el.textContent = ... every second) and the comments/annotations sidebar flashes on every tick — even though nothing about the comments changed.

Root cause

The runtime injected into the document watches document.body with a MutationObserver (collab-client.ts) so highlights stay anchored as the document reflows. Any mutation — including a one-character text swap from a clock — schedules a re-measure and posts a fresh highlights:positions report to the shell.

In the shell, the non-animated branch of the highlights:positions handler (shell-client.ts) sets shouldRender = true unconditionally:

} else {
  highlightPixelPositions = nextPixelPositions;
  shouldRender = true;
}

So every report triggers renderComments(), repainting the sidebar even when every anchor is in the exact same place. A ticking document = a repaint per tick = the flash.

Fix

Diff the incoming positions against the current ones and only repaint when something actually moved:

} else if (!pixelPositionsEqual(highlightPixelPositions, nextPixelPositions)) {
  highlightPixelPositions = nextPixelPositions;
  shouldRender = true;
}

Real reflows (a highlight added/removed, content shifting an anchor) still report different positions and repaint as before; only the no-op reports are dropped. This also quiets unrelated spurious reports (resize jitter, etc.), not just clocks.

The document runtime still re-measures on mutation (cheap), it just no longer forces a paint when the result is identical.

Tests

pixelPositionsEqual extracted as a pure helper with unit coverage (identical / moved / added / removed). 50 passed, typecheck clean.

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