From cb77a57062264047a2edf1530eb98e59b38774de Mon Sep 17 00:00:00 2001 From: windingwind <33902321+windingwind@users.noreply.github.com> Date: Sat, 4 May 2024 00:18:11 +0800 Subject: [PATCH] fix: registerLibraryTabPanel and registerReaderTabPanel --- addon/locale/en-US/mainWindow.ftl | 10 ++ addon/locale/zh-CN/mainWindow.ftl | 10 ++ package.json | 24 ++-- src/hooks.ts | 5 +- src/modules/examples.ts | 202 ++++++++++++++---------------- 5 files changed, 133 insertions(+), 118 deletions(-) create mode 100644 addon/locale/en-US/mainWindow.ftl create mode 100644 addon/locale/zh-CN/mainWindow.ftl diff --git a/addon/locale/en-US/mainWindow.ftl b/addon/locale/en-US/mainWindow.ftl new file mode 100644 index 0000000..cdf76e0 --- /dev/null +++ b/addon/locale/en-US/mainWindow.ftl @@ -0,0 +1,10 @@ +item-section-example1-head-text = + .label = Plugin Template: Item Info +item-section-example1-sidenav-tooltip = + .tooltiptext = This is Plugin Template section (item info) +item-section-example2-head-text = + .label = Plugin Template: Reader [{$status}] +item-section-example2-sidenav-tooltip = + .tooltiptext = This is Plugin Template section (reader) +item-section-example2-button-tooltip = + .tooltiptext = Unregister this section diff --git a/addon/locale/zh-CN/mainWindow.ftl b/addon/locale/zh-CN/mainWindow.ftl new file mode 100644 index 0000000..8174cbb --- /dev/null +++ b/addon/locale/zh-CN/mainWindow.ftl @@ -0,0 +1,10 @@ +item-section-example1-head-text = + .label = 插件模板: 条目信息 +item-section-example1-sidenav-tooltip = + .tooltiptext = 这是插件模板面板(条目信息) +item-section-example2-head-text = + .label = 插件模板: 阅读器[{$status}] +item-section-example2-sidenav-tooltip = + .tooltiptext = 这是插件模板面板(阅读器) +item-section-example2-button-tooltip = + .tooltiptext = 移除此面板 diff --git a/package.json b/package.json index 87147ed..3312c0d 100644 --- a/package.json +++ b/package.json @@ -32,22 +32,22 @@ }, "homepage": "https://github.com/windingwind/zotero-addon-template#readme", "dependencies": { - "zotero-plugin-toolkit": "^2.3.15" + "zotero-plugin-toolkit": "^2.3.29" }, "devDependencies": { - "@types/node": "^20.10.4", - "@typescript-eslint/eslint-plugin": "^7.3.1", - "@typescript-eslint/parser": "^7.1.1", - "chokidar": "^3.5.3", + "@types/node": "^20.12.8", + "@typescript-eslint/eslint-plugin": "^7.8.0", + "@typescript-eslint/parser": "^7.8.0", + "chokidar": "^3.6.0", "compressing": "^1.10.0", - "esbuild": "^0.20.1", - "eslint": "^8.55.0", + "esbuild": "^0.20.2", + "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "prettier": "^3.1.1", - "release-it": "^17.0.1", - "replace-in-file": "^7.0.2", - "typescript": "^5.3.3", - "zotero-types": "^1.3.10" + "prettier": "^3.2.5", + "release-it": "^17.2.1", + "replace-in-file": "^7.1.0", + "typescript": "^5.4.5", + "zotero-types": "^1.3.24" }, "eslintConfig": { "env": { diff --git a/src/hooks.ts b/src/hooks.ts index 0f3faa6..aded752 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -39,6 +39,9 @@ async function onMainWindowLoad(win: Window): Promise { // Create ztoolkit for every window addon.data.ztoolkit = createZToolkit(); + // @ts-ignore + window.MozXULElement.insertFTLIfNeeded(`${config.addonRef}-mainWindow.ftl`); + const popupWin = new ztoolkit.ProgressWindow(config.addonName, { closeOnClick: true, closeTime: -1, @@ -72,7 +75,7 @@ async function onMainWindowLoad(win: Window): Promise { UIExampleFactory.registerLibraryTabPanel(); - await UIExampleFactory.registerReaderTabPanel(); + UIExampleFactory.registerReaderTabPanel(); PromptExampleFactory.registerNormalCommandExample(); diff --git a/src/modules/examples.ts b/src/modules/examples.ts index f69fba7..90a767a 100644 --- a/src/modules/examples.ts +++ b/src/modules/examples.ts @@ -89,7 +89,7 @@ export class KeyExampleFactory { // Register an event key for Alt+L ztoolkit.Keyboard.register((ev, keyOptions) => { ztoolkit.log(ev, keyOptions.keyboard); - if (keyOptions.keyboard.equals("shift,l")) { + if (keyOptions.keyboard?.equals("shift,l")) { addon.hooks.onShortcuts("larger"); } if (ev.shiftKey && ev.key === "S") { @@ -280,118 +280,110 @@ export class UIExampleFactory { @example static registerLibraryTabPanel() { - const tabId = ztoolkit.LibraryTabPanel.register( - getString("tabpanel-lib-tab-label"), - (panel: XUL.Element, win: Window) => { - const elem = ztoolkit.UI.createElement(win.document, "vbox", { - children: [ - { - tag: "h2", - properties: { - innerText: "Hello World!", - }, - }, - { - tag: "div", - properties: { - innerText: "This is a library tab.", - }, - }, - { - tag: "button", - namespace: "html", - properties: { - innerText: "Unregister", - }, - listeners: [ - { - type: "click", - listener: () => { - ztoolkit.LibraryTabPanel.unregister(tabId); - }, - }, - ], - }, - ], + Zotero.ItemPaneManager.registerSection({ + paneID: "example", + pluginID: config.addonID, + header: { + l10nID: `${config.addonRef}-item-section-example1-head-text`, + icon: "chrome://zotero/skin/16/universal/book.svg", + }, + sidenav: { + l10nID: `${config.addonRef}-item-section-example1-sidenav-tooltip`, + icon: "chrome://zotero/skin/20/universal/save.svg", + }, + onRender: ({ body, item, editable, tabType }) => { + body.textContent = JSON.stringify({ + id: item?.id, + editable, + tabType, }); - panel.append(elem); }, - { - targetIndex: 1, - }, - ); + }); } @example static async registerReaderTabPanel() { - const tabId = await ztoolkit.ReaderTabPanel.register( - getString("tabpanel-reader-tab-label"), - ( - panel: XUL.TabPanel | undefined, - deck: XUL.Deck, - win: Window, - reader: _ZoteroTypes.ReaderInstance, - ) => { - if (!panel) { - ztoolkit.log( - "This reader do not have right-side bar. Adding reader tab skipped.", - ); - return; - } - ztoolkit.log(reader); - const elem = ztoolkit.UI.createElement(win.document, "vbox", { - id: `${config.addonRef}-${reader._instanceID}-extra-reader-tab-div`, - // This is important! Don't create content for multiple times - // ignoreIfExists: true, - removeIfExists: true, - children: [ - { - tag: "h2", - properties: { - innerText: "Hello World!", - }, - }, - { - tag: "div", - properties: { - innerText: "This is a reader tab.", - }, - }, - { - tag: "div", - properties: { - innerText: `Reader: ${reader._title.slice(0, 20)}`, - }, - }, - { - tag: "div", - properties: { - innerText: `itemID: ${reader.itemID}.`, - }, - }, - { - tag: "button", - namespace: "html", - properties: { - innerText: "Unregister", - }, - listeners: [ - { - type: "click", - listener: () => { - ztoolkit.ReaderTabPanel.unregister(tabId); - }, - }, - ], - }, - ], - }); - panel.append(elem); + Zotero.ItemPaneManager.registerSection({ + paneID: "reader-example", + pluginID: config.addonID, + header: { + l10nID: `${config.addonRef}-item-section-example2-head-text`, + // Optional + l10nArgs: `{"status": "Initialized"}`, + // Can also have a optional dark icon + icon: "chrome://zotero/skin/16/universal/book.svg", }, - { - targetIndex: 1, + sidenav: { + l10nID: `${config.addonRef}-item-section-example2-sidenav-tooltip`, + icon: "chrome://zotero/skin/20/universal/save.svg", }, - ); + // Optional + bodyXHTML: 'THIS IS TEST', + // Optional, Called when the section is first created, must be synchronous + onInit: ({ item }) => { + ztoolkit.log("Section init!", item?.id); + }, + // Optional, Called when the section is destroyed, must be synchronous + onDestroy: (props) => { + ztoolkit.log("Section destroy!"); + }, + // Optional, Called when the section data changes (setting item/mode/tabType/inTrash), must be synchronous. return false to cancel the change + onItemChange: ({ item, setEnabled, tabType }) => { + ztoolkit.log(`Section item data changed to ${item?.id}`); + setEnabled(tabType === "reader"); + return true; + }, + // Called when the section is asked to render, must be synchronous. + onRender: ({ + body, + item, + setL10nArgs, + setSectionSummary, + setSectionButtonStatus, + }) => { + ztoolkit.log("Section rendered!", item?.id); + const title = body.querySelector("#test") as HTMLElement; + title.style.color = "red"; + title.textContent = "LOADING"; + setL10nArgs(`{ "status": "Loading" }`); + setSectionSummary("loading!"); + setSectionButtonStatus("test", { hidden: true }); + }, + // Optional, can be asynchronous. + onAsyncRender: async ({ + body, + item, + setL10nArgs, + setSectionSummary, + setSectionButtonStatus, + }) => { + ztoolkit.log("Section secondary render start!", item?.id); + await Zotero.Promise.delay(1000); + ztoolkit.log("Section secondary render finish!", item?.id); + const title = body.querySelector("#test") as HTMLElement; + title.style.color = "green"; + title.textContent = item.getField("title"); + setL10nArgs(`{ "status": "Loaded" }`); + setSectionSummary("rendered!"); + setSectionButtonStatus("test", { hidden: false }); + }, + // Optional, Called when the section is toggled. Can happen anytime even if the section is not visible or not rendered + onToggle: ({ item }) => { + ztoolkit.log("Section toggled!", item?.id); + }, + // Optional, Buttons to be shown in the section header + sectionButtons: [ + { + type: "test", + icon: "chrome://zotero/skin/16/universal/empty-trash.svg", + l10nID: "make-it-red-item-section-example2-button-tooltip", + onClick: ({ item, paneID }) => { + ztoolkit.log("Section clicked!", item?.id); + Zotero.ItemPaneManager.unregisterSection(paneID); + }, + }, + ], + }); } }