Add item tree and info box refresh API (#4850)

For APIs that have lifecycle control, e.g. item
pane section, the `update` is passed in the init
hook.
For APIs without lifecycle, we can't pass a value.
Instead, we provide a method to refresh in the API
instance.
This commit is contained in:
windingwind 2024-11-20 14:35:56 +01:00 committed by GitHub
parent 8e2ec86e56
commit f5b653e7fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 75 additions and 15 deletions

View file

@ -488,7 +488,7 @@
//
notify(event, type, ids) {
if (event == 'refresh' && type == 'infobox' && this.item?.id) {
this.renderCustomRows();
this.renderCustomRows(ids);
return;
}
if (event == 'modify' && this.item?.id && ids.includes(this.item.id)) {
@ -863,11 +863,6 @@
this.restoreCustomRowElements();
// Update custom row data
for (let rowElem of this._infoTable.querySelectorAll('.meta-row[data-custom-row-id]')) {
this.updateCustomRowData(rowElem);
}
// Set focus on the last focused field
this._restoreFieldFocus();
// Make sure that any opened popup closes
@ -876,8 +871,18 @@
});
}
renderCustomRows() {
renderCustomRows(rowIDs) {
let { options: targetRows, updateID } = Zotero.ItemPaneManager.customInfoRowData;
// If rowIDs are provided, always update them
if (rowIDs?.length > 0) {
for (let rowID of rowIDs) {
let rowElem = this._infoTable.querySelector(`[data-custom-row-id="${rowID}"]`);
if (!rowElem) continue;
this.updateCustomRowData(rowElem);
}
}
if (this._lastUpdateCustomRows == updateID) return;
this._lastUpdateCustomRows = updateID;
@ -890,8 +895,15 @@
// Add rows that are in the target rows but not in the current rows
for (let row of targetRows) {
if (this._infoTable.querySelector(`[data-custom-row-id="${row.rowID}"]`)) continue;
let rowElem = document.createElement("div");
let rowElem = this._infoTable.querySelector(`[data-custom-row-id="${row.rowID}"]`);
if (rowElem) {
// If the row is already in the table, and not already updated, update it
if (!rowIDs?.includes(row.rowID)) {
this.updateCustomRowData(rowElem);
}
continue;
}
rowElem = document.createElement("div");
rowElem.dataset.customRowId = row.rowID;
let position = row.position || "end";
rowElem.dataset.position = position;
@ -933,6 +945,7 @@
this.updateCustomRowProperty(rowElem);
// The row is new, always update the data
this.updateCustomRowData(rowElem);
}
}

View file

@ -301,6 +301,13 @@
},
};
}
refresh(rowID) {
if (!this._optionsCache[rowID]) {
return;
}
this._refresh([rowID]);
}
}
@ -329,6 +336,10 @@
return this._infoRowManager.unregister(rowID);
}
refreshInfoRow(rowID) {
return this._infoRowManager.refresh(rowID);
}
get customInfoRowData() {
return this._infoRowManager.data;
}

View file

@ -158,6 +158,10 @@ import { COLUMNS } from 'zotero/itemTreeColumns';
return super._validate(option);
}
refresh() {
this._refresh();
}
}
@ -332,6 +336,10 @@ import { COLUMNS } from 'zotero/itemTreeColumns';
}
return "";
}
refreshColumns() {
this._columnManager.refresh();
}
}

View file

@ -121,7 +121,7 @@ class PluginAPIBase {
return false;
}
this._addPluginShutdownObserver();
this._update();
this._refresh();
return mainKey;
}
@ -135,7 +135,7 @@ class PluginAPIBase {
if (!success) {
return false;
}
this._update();
this._refresh();
return true;
}
@ -322,14 +322,14 @@ class PluginAPIBase {
/**
* Notify the receiver to update
*/
async _update() {
async _refresh(ids = [], extraData = {}) {
this._lastUpdateID = `${new Date().getTime()}-${lazy.Zotero.Utilities.randomString()}`;
await lazy.Zotero.DB.executeTransaction(async () => {
lazy.Zotero.Notifier.queue(
this._config.notifyAction,
this._config.notifyType,
[],
{},
ids,
extraData,
);
});
}
@ -347,7 +347,7 @@ class PluginAPIBase {
// Remove the registrations one by one
paneIDs.forEach(id => this._remove(id));
this._log(`Registrations for plugin ${pluginID} are unregistered due to shutdown`);
await this._update();
await this._refresh();
}
/**

View file

@ -359,6 +359,34 @@ describe("Plugin API", function () {
await waitForUnregister(rowID);
});
it("should refresh custom row value", async function () {
let item = new Zotero.Item('book');
await item.saveTx();
await ZoteroPane.selectItem(item.id);
let rowID = await waitForRegister(defaultOption);
let rowElem = infoSection.querySelector(`[data-custom-row-id="${rowID}"]`);
let valueElem = rowElem.querySelector(".value");
let oldValue = valueElem.value;
// Since this row does not have `onSetData`, changing value does not do anything
// We just want to test if the value can be refreshed by calling `updateInfoRow`
let newValue = "TEST CUSTOM ROW EDITED";
valueElem.value = newValue;
let notifyPromise = waitForNotifierEvent("refresh", "infobox");
// Manually refresh the row
Zotero.ItemPaneManager.refreshInfoRow(rowID);
await notifyPromise;
assert.equal(oldValue, valueElem.value);
await waitForUnregister(rowID);
});
});
describe("Item tree custom column", function () {