Skip to content

Commit 404f445

Browse files
committed
fix(comments): emit empty comment positions so undo clears orphan bubbles
PresentationEditor skipped emission when positions were empty, so undoing the last tracked-change mark never signaled the store to clear stale data. Also fix getFloatingComments to use isEditorBackedComment() so tracked-change comments (which lack selection.source) require live positions like editor comments.
1 parent d326f3a commit 404f445

3 files changed

Lines changed: 27 additions & 9 deletions

File tree

packages/super-editor/src/core/presentation-editor/PresentationEditor.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3524,14 +3524,12 @@ export class PresentationEditor extends EventEmitter {
35243524
this.emit('paginationUpdate', payload);
35253525

35263526
// Emit fresh comment positions after layout completes.
3527-
// This ensures positions are always in sync with the current document and layout.
3527+
// Always emit — even when empty — so the store can clear stale positions
3528+
// (e.g. when undo removes the last tracked-change mark).
35283529
const allowViewingCommentPositions = this.#layoutOptions.emitCommentPositionsInViewing === true;
35293530
if (this.#documentMode !== 'viewing' || allowViewingCommentPositions) {
35303531
const commentPositions = this.#collectCommentPositions();
3531-
const positionKeys = Object.keys(commentPositions);
3532-
if (positionKeys.length > 0) {
3533-
this.emit('commentPositions', { positions: commentPositions });
3534-
}
3532+
this.emit('commentPositions', { positions: commentPositions });
35353533
}
35363534

35373535
this.#selectionSync.requestRender({ immediate: true });

packages/superdoc/src/stores/comments-store.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -876,11 +876,12 @@ export const useCommentsStore = defineStore('comments', () => {
876876
const comments = getGroupedComments.value?.parentComments
877877
.filter((c) => !c.resolvedTime)
878878
.filter((c) => {
879-
const keys = Object.keys(editorCommentPositions.value);
880-
const isPdfComment = c.selection?.source !== 'super-editor';
881-
if (isPdfComment) return true;
879+
// Non-editor comments (e.g. PDF) are always shown.
880+
// Editor-backed comments (including tracked changes, which have no
881+
// selection.source) must have a live position in the document.
882+
if (!isEditorBackedComment(c)) return true;
882883
const commentKey = c.commentId || c.importedId;
883-
return keys.includes(commentKey);
884+
return Object.keys(editorCommentPositions.value).includes(commentKey);
884885
});
885886
return comments;
886887
});

packages/superdoc/src/stores/comments-store.test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,5 +946,24 @@ describe('comments-store', () => {
946946
const floating = store.getFloatingComments;
947947
expect(floating).toEqual([]);
948948
});
949+
950+
it('excludes unresolved tracked change when positions are cleared (regression: SD-2071)', () => {
951+
store.commentsList = [
952+
{ commentId: 'tc-1', trackedChange: true, resolvedTime: null, createdTime: 1, selection: {} },
953+
];
954+
// Undo removed the mark — positions are now empty
955+
store.editorCommentPositions = {};
956+
957+
const floating = store.getFloatingComments;
958+
expect(floating).toEqual([]);
959+
});
960+
961+
it('keeps PDF comments visible when editor positions are empty (SD-2071)', () => {
962+
store.commentsList = [{ commentId: 'pdf-1', createdTime: 1, selection: { source: 'pdf', selectionBounds: {} } }];
963+
store.editorCommentPositions = {};
964+
965+
const floating = store.getFloatingComments;
966+
expect(floating.map((c) => c.commentId)).toEqual(['pdf-1']);
967+
});
949968
});
950969
});

0 commit comments

Comments
 (0)