From e8397e48c53d5b498cb0358c7d1fca9257b4c901 Mon Sep 17 00:00:00 2001 From: Bogdan Abaev Date: Thu, 16 Apr 2026 17:26:14 -0700 Subject: [PATCH] citation dlg: insert note refactoring - allow one to insert multiple notes at a time - in list mode, match notes by their parent item and render them as children of collapsible regular items - in library mode, add parent title to the item card similar to annotation and add note preview sidebar that displays the content of the note when it is selected - refactor list mode to use virtualized-table for rendering. Now that we need to render parent-child row relations, virtualized-table offers more flexibility, and we can no longer have the same workflow for suggested items in library mode as for list mode. --- .../zotero/integration/citationDialog.js | 1130 +++++++++++------ .../zotero/integration/citationDialog.xhtml | 10 +- .../integration/citationDialog/helpers.mjs | 194 ++- .../citationDialog/keyboardHandler.mjs | 114 +- .../citationDialog/searchHandler.mjs | 208 ++- chrome/content/zotero/xpcom/data/notes.js | 62 + chrome/content/zotero/xpcom/integration.js | 16 +- chrome/locale/en-US/zotero/integration.ftl | 4 +- scss/components/_citationDialog.scss | 340 +++-- scss/elements/_bubbleInput.scss | 2 - test/tests/citationDialogTest.js | 135 +- 11 files changed, 1621 insertions(+), 594 deletions(-) diff --git a/chrome/content/zotero/integration/citationDialog.js b/chrome/content/zotero/integration/citationDialog.js index 9f8145ee57..3772bb3ea5 100644 --- a/chrome/content/zotero/integration/citationDialog.js +++ b/chrome/content/zotero/integration/citationDialog.js @@ -25,6 +25,9 @@ const CollectionViewItemTree = require('zotero/collectionViewItemTree'); +const React = require('react'); +const ReactDOM = require('react-dom'); +const VirtualizedTable = require('components/virtualized-table'); const { getCSSIcon } = require('components/icons'); const { COLUMNS } = require('zotero/itemTreeColumns'); var doc, io, ioReadyPromise, ioIsReady, accepted; @@ -47,10 +50,12 @@ var { CitationDialogKeyboardHandler } = ChromeUtils.importESModule('chrome://zot var DIALOG_STATE = { type: null, // 'citation' or 'add-note' loaded: false, + isTestRun: false, isCitingItems: () => DIALOG_STATE.type == 'citation', isAddingNote: () => DIALOG_STATE.type == 'add-note', isAddingAnnotations: () => DIALOG_STATE.type == 'annotations', + getCurrentLayoutType: () => currentLayout?.type, }; @@ -75,7 +80,7 @@ async function onLoad() { let timer = new Zotero.Integration.Timer(); timer.start(); - Helpers = new CitationDialogHelpers({ doc, io }); + Helpers = new CitationDialogHelpers({ doc, dialogState: DIALOG_STATE }); SearchHandler = new CitationDialogSearchHandler({ dialogState: DIALOG_STATE, io }); PopupsHandler = new CitationDialogPopupsHandler({ doc, dialogState: DIALOG_STATE }); KeyboardHandler = new CitationDialogKeyboardHandler({ doc }); @@ -123,6 +128,7 @@ async function onLoad() { // init library layout after bubble input is built since bubble-input's height is a factor // determining initial library layout height await libraryLayout.init(); + await listLayout.init(); // fetch selected items so they are known // before refreshing items list after dialog mode setting await SearchHandler.refreshSelectedAndOpenItems(); @@ -263,7 +269,7 @@ async function setDialogType(type) { } // Set proper settings availability depending on the type - _id("bubble-input").sortable = DIALOG_STATE.isCitingItems(); + _id("bubble-input").sortable = DIALOG_STATE.isCitingItems() || DIALOG_STATE.isAddingNote(); _id("keepSorted").disabled = !io.sortable || !DIALOG_STATE.isCitingItems(); _id("keepSorted").checked = !_id("keepSorted").disabled && !io.citation.properties.unsorted; if (DIALOG_STATE.isCitingItems()) { @@ -276,6 +282,17 @@ async function setDialogType(type) { else if (DIALOG_STATE.isAddingNote()) { _id("settings-button").hidden = true; _id("keepSorted").disabled = true; + _id("note-preview").mode = "merge"; // hides the toolbar + // insert a