From 8800a3c8b33394abbfd4ea0baa87eff81dc5329f Mon Sep 17 00:00:00 2001 From: Research Assistant Date: Wed, 20 May 2026 17:05:41 +0800 Subject: [PATCH] fix: use full field names in annotation cache, render only on new page --- paperforge/annotation/cache.py | 28 ++++++++++++++-------------- paperforge/plugin/main.js | 26 +++++++++++++++----------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/paperforge/annotation/cache.py b/paperforge/annotation/cache.py index 1ba17c0f..a9d53877 100644 --- a/paperforge/annotation/cache.py +++ b/paperforge/annotation/cache.py @@ -46,20 +46,20 @@ def _row_to_dict(row: sqlite3.Row) -> dict[str, Any]: tags = [] return { "id": row["id"], - "pid": row["paper_id"], - "zk": row["zotero_key"] or "", - "ak": row["zotero_attachment_key"] or "", # storage folder name for key resolution - "t": row["type"], - "pi": row["page_index"], - "pl": row["page_label"] or "", - "st": row["selected_text"] or "", - "c": row["comment"] or "", - "cl": row["color"] or "#ffd400", - "si": row["sort_index"] or "", - "tg": tags, - "pos": pos, - "ss": row["sync_state"], - "ir": bool(row["is_readonly"]), + "paper_id": row["paper_id"], + "zotero_key": row["zotero_key"] or "", + "zotero_attachment_key": row["zotero_attachment_key"] or "", + "type": row["type"], + "page_index": row["page_index"], + "page_label": row["page_label"] or "", + "selected_text": row["selected_text"] or "", + "comment": row["comment"] or "", + "color": row["color"] or "#ffd400", + "sort_index": row["sort_index"] or "", + "tags": tags, + "position": pos, + "sync_state": row["sync_state"], + "is_readonly": bool(row["is_readonly"]), } diff --git a/paperforge/plugin/main.js b/paperforge/plugin/main.js index 23e9577d..16835dcb 100644 --- a/paperforge/plugin/main.js +++ b/paperforge/plugin/main.js @@ -447,11 +447,10 @@ function _resolvePaperIdFromCache(pdfPath, cache) { var m = pdfPath.match(/storage[\\/]([A-Z0-9]{8})/i); if (m) { var sk = m[1].toUpperCase(); - // Search all papers for matching attachment key (ak) for (var pid in cache.by_paper) { var anns = cache.by_paper[pid]; for (var i = 0; i < anns.length; i++) { - if (anns[i].ak === sk) return pid; + if (anns[i].zotero_attachment_key === sk) return pid; } } } @@ -608,13 +607,18 @@ function injectPdfEventHooks(containerEl, view, vaultPath, pdfPath, plugin) { var anns = fetchAnnotationsForPaper(vaultPath, pdfPath); console.log('[PF] fetched ' + (anns ? anns.length : 0) + ' annotations for ' + pdfPath); if (anns && anns.length > 0) { renderAnnotationsOnExistingPages(containerEl); } - var _debounceTimer = null; - var pageObserver = new MutationObserver(function () { - if (_debounceTimer) clearTimeout(_debounceTimer); - _debounceTimer = setTimeout(function () { - _debounceTimer = null; - renderAnnotationsOnExistingPages(containerEl); - }, 200); + var pageObserver = new MutationObserver(function (mutations) { + var hasNewPage = false; + for (var mi = 0; mi < mutations.length; mi++) { + var added = mutations[mi].addedNodes; + for (var ai = 0; ai < added.length; ai++) { + if (added[ai].nodeType === 1 && added[ai].matches && added[ai].matches('.page[data-page-number]')) { + hasNewPage = true; break; + } + } + if (hasNewPage) break; + } + if (hasNewPage) renderAnnotationsOnExistingPages(containerEl); }); pageObserver.observe(containerEl, { childList: true, subtree: true }); if (plugin && typeof plugin.register === 'function') { @@ -898,8 +902,8 @@ function hideAnnotationPopover() { function getAnnotationRects(ann) { if (!ann) return null; - // Cache format: "pos" is already parsed object: {pageIndex:N, rects:[[l,b,r,t],...]} - if (ann.pos && Array.isArray(ann.pos.rects)) return ann.pos.rects; + // Cache format: "position" is already parsed: {pageIndex:N, rects:[[l,b,r,t],...]} + if (ann.position && Array.isArray(ann.position.rects)) return ann.position.rects; // Full position_json string from CLI output if (ann.position_json) { try {