Skip to content

Commit 70fd7d9

Browse files
authored
perf(comments): batch tracked change creation and virtualize floating bubbles (SD-1997) (#2168)
* perf(comments): virtualize floating comment bubbles with IntersectionObserver Replace the two-pass render pipeline (hidden measurement container + visible container mounting all 588 CommentDialogs simultaneously) with IntersectionObserver virtualization. Only comments within 600px of the viewport mount the heavy CommentDialog component; the rest are lightweight placeholder divs. - allPositions computed with collision avoidance replaces imperative processLocations - Module-level _heightsCache survives component remounts - verticalOffset converted to computed for proper reactivity - SuperDoc.vue watcher changed to one-way false→true (prevents unmount/remount flicker) - Expose getCommentPositionKey from comments-store for canonical ID resolution SD-1997 * test(comments): add behavior tests for floating comment virtualization Verify that: - Floating comment placeholders appear after creating tracked changes - CommentDialogs mount near the viewport via IntersectionObserver - Typing does not cause comment sidebar to flicker (hasInitializedLocations fix) SD-1997 * chore: fix lockfile missing SDK optional dependency specifiers The SDK platform packages (@superdoc-dev/sdk-darwin-arm64, etc.) were added as optionalDependencies in a093891 but pnpm skipped resolving them because of os/cpu restrictions, leaving the lockfile without specifiers. CI with --frozen-lockfile then failed. * chore: ignore SDK scripts in eslint config The .mjs files in packages/sdk/scripts/ cause parse errors with typescript-eslint. These are standalone Node scripts, not part of the library source. * fix(comments): resolve activeComment key mismatch for imported Word comments activeComment stores commentId but pos.id uses getCommentPositionKey (prefers importedId). For imported comments where importedId !== commentId, the template guard failed and the active dialog could unmount when scrolled out of viewport. * fix(tests): update comment test selectors for virtualized FloatingComments The selector .floating-comment > .comments-dialog expected a parent-child relationship, but Vue merges both classes onto the same DOM element. Changed to .comment-placeholder .comments-dialog which matches the virtualized template.
1 parent 6221580 commit 70fd7d9

9 files changed

Lines changed: 312 additions & 157 deletions

File tree

eslint.config.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export default [
4646
'**/commitlint.config.js',
4747
// E2E tests
4848
'e2e-tests/**',
49+
// SDK scripts — ESM parsed incorrectly by typescript-eslint
50+
'packages/sdk/scripts/**',
4951
],
5052
},
5153
{

packages/superdoc/src/SuperDoc.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -956,11 +956,13 @@ watch(
956956
},
957957
);
958958
959+
// Ensure hasInitializedLocations is set when comments arrive (backup for cases
960+
// where handleDocumentReady hasn't fired yet). Never toggle false→true→false —
961+
// the virtualized FloatingComments reacts to comment changes via computed properties.
959962
watch(getFloatingComments, () => {
960-
hasInitializedLocations.value = false;
961-
nextTick(() => {
963+
if (!hasInitializedLocations.value) {
962964
hasInitializedLocations.value = true;
963-
});
965+
}
964966
});
965967
966968
const {

0 commit comments

Comments
 (0)