From 40357239e3408c7a3596b1c7203fde22d747fa6e Mon Sep 17 00:00:00 2001 From: skalthoff <32023561+skalthoff@users.noreply.github.com> Date: Sun, 1 Feb 2026 17:25:07 -0800 Subject: [PATCH] Skip replacing annotations with unsaved local changes in setAnnotations() When setAnnotations() receives annotations from the client side (e.g. during sync), it unconditionally replaces all matching annotation objects. If an annotation has unsaved local changes tracked in _unsavedAnnotations, this replacement triggers unnecessary re-renders due to broken reference identity, visually disrupting in-progress ink and image annotations. Skip annotations whose ID exists in _unsavedAnnotations, since the local version is authoritative until saved. This covers both locally modified annotations (non-null entries) and locally deleted annotations (null entries), preventing resurrection of deleted annotations. Fixes zotero/reader#106 --- src/common/annotation-manager.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/common/annotation-manager.js b/src/common/annotation-manager.js index 46672e0cd..32ca6f5c8 100644 --- a/src/common/annotation-manager.js +++ b/src/common/annotation-manager.js @@ -49,11 +49,18 @@ class AnnotationManager { // Called when changes come from the client side async setAnnotations(annotations) { + let changed = false; for (let annotation of annotations) { + if (this._unsavedAnnotations.has(annotation.id)) { + continue; + } this._annotations = this._annotations.filter(x => x.id !== annotation.id); this._annotations.push(annotation); + changed = true; + } + if (changed) { + this._annotations.sort((a, b) => (a.sortIndex > b.sortIndex) - (a.sortIndex < b.sortIndex)); } - this._annotations.sort((a, b) => (a.sortIndex > b.sortIndex) - (a.sortIndex < b.sortIndex)); this._clearInterferingHistory(annotations.map(x => x.id)); this.render(); }