refactor: make examples more friendly
This commit is contained in:
		
							parent
							
								
									6426ae5198
								
							
						
					
					
						commit
						4469cbc82d
					
				
							
								
								
									
										101
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								README.md
									
									
									
									
									
								
							@ -19,6 +19,32 @@ This is an addon/plugin template for [Zotero](https://www.zotero.org/).
 | 
			
		||||
- Some sample code of UI and lifecycle.
 | 
			
		||||
- ⭐Compatibilities for Zotero 6 & Zotero 7.(using [zotero-plugin-toolkit](https://github.com/windingwind/zotero-plugin-toolkit))
 | 
			
		||||
 | 
			
		||||
## Examples
 | 
			
		||||
 | 
			
		||||
This repo provides examples for [zotero-plugin-toolkit](https://github.com/windingwind/zotero-plugin-toolkit) APIs.
 | 
			
		||||
 | 
			
		||||
Search `@example` in `src/examples.ts`. The examples are called in `src/hooks.ts`.
 | 
			
		||||
 | 
			
		||||
### Basic Examples
 | 
			
		||||
 | 
			
		||||
- registerNotifier
 | 
			
		||||
- registerPrefs, unregisterPrefs
 | 
			
		||||
 | 
			
		||||
### UI Examples
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
- registerStyleSheet(the official make-it-red example)
 | 
			
		||||
- registerRightClickMenuItem
 | 
			
		||||
- registerRightClickMenuPopup
 | 
			
		||||
- registerWindowMenuWithSeprator
 | 
			
		||||
- registerExtraColumn
 | 
			
		||||
- registerExtraColumnWithCustomCell
 | 
			
		||||
- registerCustomCellRenderer
 | 
			
		||||
- registerLibraryTabPanel
 | 
			
		||||
- registerReaderTabPanel
 | 
			
		||||
- unregisterUIExamples
 | 
			
		||||
 | 
			
		||||
## Quick Start Guide
 | 
			
		||||
 | 
			
		||||
- Fork this repo;
 | 
			
		||||
@ -46,58 +72,38 @@ This is an addon/plugin template for [Zotero](https://www.zotero.org/).
 | 
			
		||||
- Run `npm run build` to build the plugin in production mode. Run `npm run build-dev` to build the plugin in development mode. The xpi for installation and the built code is under builds folder.
 | 
			
		||||
 | 
			
		||||
> What the difference between dev & prod?
 | 
			
		||||
>
 | 
			
		||||
> - This environment variable is stored in `Zotero.AddonTemplate.env`. The outputs to console is disabled in prod mode.
 | 
			
		||||
> - You can decide what users cannot see/use based on this variable.
 | 
			
		||||
 | 
			
		||||
### About Life Cycle
 | 
			
		||||
### About Hooks
 | 
			
		||||
 | 
			
		||||
> See also `src/hooks.ts`
 | 
			
		||||
 | 
			
		||||
1. When install/enable/startup triggered from Zotero, `bootstrap.js` > `startup` is called
 | 
			
		||||
   - Wait for Zotero ready
 | 
			
		||||
   - Prepare global variables `ctx`. They are available globally in the plugin scope
 | 
			
		||||
   - Load `index.js` (the main entrance of plugin code, built from `index.ts`)
 | 
			
		||||
   - Register resources if Zotero 7+
 | 
			
		||||
2. In the main entrance `index.js`, the plugin object is injected under `Zotero` and `events.ts` > `onInit` is called.
 | 
			
		||||
   - Initialize anything you want, including notify listeners, preference panes(`initPrefs`), and UI elements(`initViews`).
 | 
			
		||||
2. In the main entrance `index.js`, the plugin object is injected under `Zotero` and `hooks.ts` > `onStartup` is called.
 | 
			
		||||
   - Initialize anything you want, including notify listeners, preference panes, and UI elements.
 | 
			
		||||
3. When uninstall/disabled triggered from Zotero, `bootstrap.js` > `shutdown` is called.
 | 
			
		||||
   - `events.ts` > `onUninit` is called. Remove UI elements(`unInitViews`), preference panes(`uninitPrefs`), or anything created by the plugin.
 | 
			
		||||
   - `events.ts` > `onShutdown` is called. Remove UI elements, preference panes, or anything created by the plugin.
 | 
			
		||||
   - Remove scripts and release resources.
 | 
			
		||||
 | 
			
		||||
### About Global Variables
 | 
			
		||||
 | 
			
		||||
> See also `src/index.ts`
 | 
			
		||||
 | 
			
		||||
The bootstrapped plugin runs in a sandbox, which does not have default global variables like `Zotero` or `window`, which we used to have in the overlay plugins' window environment.
 | 
			
		||||
 | 
			
		||||
This template registers the following variables to the global scope:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
Zotero, ZoteroPane, Zotero_Tabs, window, document, rootURI, ZToolkit
 | 
			
		||||
Zotero, ZoteroPane, Zotero_Tabs, window, document, rootURI, ztoolkit, addon;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
See `src/events.ts` > `initGlobalVariables` for more details.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Examples
 | 
			
		||||
 | 
			
		||||
See https://github.com/windingwind/zotero-plugin-toolkit for more detailed API documentations.
 | 
			
		||||
 | 
			
		||||
#### Menu (file, edit, view, ...) & Right-click Menu (item, collection/library)
 | 
			
		||||
 | 
			
		||||
**File Menu**
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
https://github.com/windingwind/zotero-addon-template/blob/574ce88b9fd3535a9d062db51cf16e99dda35288/src/views.ts#L52-L60
 | 
			
		||||
 | 
			
		||||
**Item Menu**
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
https://github.com/windingwind/zotero-addon-template/blob/574ce88b9fd3535a9d062db51cf16e99dda35288/src/views.ts#L23-L51
 | 
			
		||||
 | 
			
		||||
`insertMenuItem` resolved the input object and inject the menu items.
 | 
			
		||||
 | 
			
		||||
You can choose an anchor element and insert before/after it using `insertPosition` and `anchorElement`. Default the insert position is the end of the menu.
 | 
			
		||||
 | 
			
		||||
#### Preference, for both Zotero 6 and Zotero 7 (all in bootstrap)
 | 
			
		||||
### About Preference
 | 
			
		||||
 | 
			
		||||
Zotero 6 doesn't support preference pane injection in bootstrap mode, thus I write a register for Zotero 6 or lower.
 | 
			
		||||
 | 
			
		||||
@ -133,7 +139,7 @@ Remember to call `unregisterPrefPane()` on plugin unload.
 | 
			
		||||
 | 
			
		||||
https://github.com/windingwind/zotero-addon-template/blob/574ce88b9fd3535a9d062db51cf16e99dda35288/src/views.ts#L88-L90
 | 
			
		||||
 | 
			
		||||
#### Create Elements API
 | 
			
		||||
### Create Elements API
 | 
			
		||||
 | 
			
		||||
The plugin template provides new APIs for bootstrap plugins. We have two reasons to use these APIs, instead of the `createElement/createElementNS`:
 | 
			
		||||
 | 
			
		||||
@ -142,30 +148,13 @@ The plugin template provides new APIs for bootstrap plugins. We have two reasons
 | 
			
		||||
 | 
			
		||||
There are more advanced APIs for creating elements in batch: `creatElementsFromJSON`. Input an element tree in JSON and return a fragment/element. These elements are also maintained by this plugin template.
 | 
			
		||||
 | 
			
		||||
#### Extra Column in Library
 | 
			
		||||
 | 
			
		||||
Using [Zotero Plugin Toolkit:ItemTreeTool](https://github.com/windingwind/zotero-plugin-toolkit/blob/HEAD/docs/zotero-plugin-toolkit.itemtreetool.md) to register an extra column in `src/views.ts`.
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
ZToolkit.ItemTree.registerExample();
 | 
			
		||||
```
 | 
			
		||||
This will register a column with dataKey `test`. Looks like:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
Remember to unregister it when exiting.
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
ZToolkit.ItemTree.unregister("test");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Directory Structure
 | 
			
		||||
 | 
			
		||||
This section shows the directory structure of a template.
 | 
			
		||||
 | 
			
		||||
- All `.js/.ts` code files are in `./src`;
 | 
			
		||||
- Addon config files: `./addon/chrome.manifest`, `./addon/install.rdf`;
 | 
			
		||||
- UI files: `./addon/chrome/content/*.xul`. The `overlay.xul` also defines the main entrance;
 | 
			
		||||
- Addon config files: `./addon/chrome.manifest`, `./addon/install.rdf`, and `./addon/manifest.json`;
 | 
			
		||||
- UI files: `./addon/chrome/content/*.xhtml`.
 | 
			
		||||
- Locale files: `./addon/chrome/locale/[*.dtd, *.properties]`;
 | 
			
		||||
- Resource files: `./addon/chrome/skin/default/__addonRef__/*.dtd`;
 | 
			
		||||
- Preferences file: `./addon/chrome/defaults/preferences/defaults.js`;
 | 
			
		||||
@ -184,8 +173,9 @@ This section shows the directory structure of a template.
 | 
			
		||||
├─.github           # github conf
 | 
			
		||||
│
 | 
			
		||||
├─addon             # addon dir
 | 
			
		||||
│  │  chrome.manifest  #addon conf
 | 
			
		||||
│  │  install.rdf   # addon install conf
 | 
			
		||||
│  │  chrome.manifest  # for Zotero 6
 | 
			
		||||
│  │  manifest.json # for Zotero 7
 | 
			
		||||
│  │  install.rdf   # addon install conf, for Zotero 6
 | 
			
		||||
│  │  bootstrap.js  # addon load/unload script, like a main.c
 | 
			
		||||
│  │
 | 
			
		||||
│  └─chrome
 | 
			
		||||
@ -211,10 +201,9 @@ This section shows the directory structure of a template.
 | 
			
		||||
│
 | 
			
		||||
└─src               # source code
 | 
			
		||||
    │  index.ts     # main entry
 | 
			
		||||
    │  module.ts    # module class
 | 
			
		||||
    │  addon.ts     # base class
 | 
			
		||||
    │  events.ts    # events class
 | 
			
		||||
    │  views.ts     # UI class
 | 
			
		||||
    │  hooks.ts     # lifecycle hooks
 | 
			
		||||
    │  examples.ts  # examples factory
 | 
			
		||||
    │  locale.ts    # Locale class for properties files
 | 
			
		||||
    └─ prefs.ts     # preferences class
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								addon/bootstrap.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								addon/bootstrap.js
									
									
									
									
										vendored
									
									
								
							@ -102,7 +102,7 @@ function shutdown({ id, version, resourceURI, rootURI }, reason) {
 | 
			
		||||
      Components.interfaces.nsISupports
 | 
			
		||||
    ).wrappedJSObject;
 | 
			
		||||
  }
 | 
			
		||||
  Zotero.AddonTemplate.events.onUnInit(Zotero);
 | 
			
		||||
  Zotero.AddonTemplate.hooks.onShutdown();
 | 
			
		||||
 | 
			
		||||
  Cc["@mozilla.org/intl/stringbundle;1"]
 | 
			
		||||
    .getService(Components.interfaces.nsIStringBundleService)
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
startup.begin=Addon is loading
 | 
			
		||||
startup.finish=Addon is ready
 | 
			
		||||
menuitem.label=Addon Template: Menuitem
 | 
			
		||||
menupopup.label=Addon Template: Menupopup
 | 
			
		||||
menuitem.submenulabel=Addon Template
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,9 @@
 | 
			
		||||
menuitem.label=Addon Template: 菜单
 | 
			
		||||
menupopup.label=Addon Template: 弹出菜单
 | 
			
		||||
menuitem.submenulabel=Addon Template
 | 
			
		||||
menuitem.filemenulabel=Addon Template: 文件菜单
 | 
			
		||||
startup.begin=插件加载中
 | 
			
		||||
startup.finish=插件已就绪
 | 
			
		||||
menuitem.label=插件模板: 菜单
 | 
			
		||||
menupopup.label=插件模板: 弹出菜单
 | 
			
		||||
menuitem.submenulabel=插件模板:子菜单
 | 
			
		||||
menuitem.filemenulabel=插件模板: 文件菜单
 | 
			
		||||
prefs.title=插件模板
 | 
			
		||||
tabpanel.lib.tab.label=库标签
 | 
			
		||||
tabpanel.reader.tab.label=阅读器标签
 | 
			
		||||
							
								
								
									
										2
									
								
								build.js
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								build.js
									
									
									
									
									
								
							@ -101,7 +101,7 @@ async function main() {
 | 
			
		||||
    .build({
 | 
			
		||||
      entryPoints: ["src/index.ts"],
 | 
			
		||||
      define: {
 | 
			
		||||
        __env__: process.env.NODE_ENV,
 | 
			
		||||
        __env__: `"${process.env.NODE_ENV}"`,
 | 
			
		||||
      },
 | 
			
		||||
      bundle: true,
 | 
			
		||||
      // Entry should be the same as addon/chrome/content/overlay.xul
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,6 @@
 | 
			
		||||
    "esbuild": "^0.16.10",
 | 
			
		||||
    "release-it": "^14.14.3",
 | 
			
		||||
    "replace-in-file": "^6.3.5",
 | 
			
		||||
    "zotero-types": "^0.1.2"
 | 
			
		||||
    "zotero-types": "^0.1.4"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								src/addon.ts
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/addon.ts
									
									
									
									
									
								
							@ -1,25 +1,24 @@
 | 
			
		||||
import AddonEvents from "./events";
 | 
			
		||||
import AddonHooks from "./hooks";
 | 
			
		||||
import AddonPrefs from "./prefs";
 | 
			
		||||
import AddonViews from "./views";
 | 
			
		||||
import AddonLocale from "./locale";
 | 
			
		||||
 | 
			
		||||
class Addon {
 | 
			
		||||
  // Env type, see build.js
 | 
			
		||||
  public env!: "development" | "production";
 | 
			
		||||
  // If addon is disabled/removed, set it false
 | 
			
		||||
  public alive: boolean;
 | 
			
		||||
  // Lifecycle events
 | 
			
		||||
  public events: AddonEvents;
 | 
			
		||||
  // UI operations
 | 
			
		||||
  public views: AddonViews;
 | 
			
		||||
  public hooks: AddonHooks;
 | 
			
		||||
  // Scripts for prefpane window
 | 
			
		||||
  public prefs: AddonPrefs;
 | 
			
		||||
  // Runtime locale with .properties
 | 
			
		||||
  public locale: AddonLocale;
 | 
			
		||||
 | 
			
		||||
  constructor() {
 | 
			
		||||
    this.events = new AddonEvents(this);
 | 
			
		||||
    this.views = new AddonViews(this);
 | 
			
		||||
    this.prefs = new AddonPrefs(this);
 | 
			
		||||
    this.locale = new AddonLocale(this);
 | 
			
		||||
    this.alive = true;
 | 
			
		||||
    this.hooks = new AddonHooks();
 | 
			
		||||
    this.prefs = new AddonPrefs();
 | 
			
		||||
    this.locale = new AddonLocale();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										119
									
								
								src/events.ts
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								src/events.ts
									
									
									
									
									
								
							@ -1,119 +0,0 @@
 | 
			
		||||
import Addon from "./addon";
 | 
			
		||||
import AddonModule from "./module";
 | 
			
		||||
import { config } from "../package.json";
 | 
			
		||||
import ZoteroToolkit from "zotero-plugin-toolkit";
 | 
			
		||||
 | 
			
		||||
class AddonEvents extends AddonModule {
 | 
			
		||||
  constructor(parent: Addon) {
 | 
			
		||||
    super(parent);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // This function is the setup code of the addon
 | 
			
		||||
  public async onInit() {
 | 
			
		||||
    this.initGlobalVariables();
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    const development = "development";
 | 
			
		||||
    const production = "production";
 | 
			
		||||
    // The env will be replaced after esbuild
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    this._Addon.env = __env__;
 | 
			
		||||
    ZToolkit.Tool.logOptionsGlobal.disableConsole =
 | 
			
		||||
      this._Addon.env === "production";
 | 
			
		||||
    ZToolkit.Tool.log("init called");
 | 
			
		||||
 | 
			
		||||
    // Initialize locale provider
 | 
			
		||||
    this._Addon.locale.initLocale();
 | 
			
		||||
    // Initialize preference window
 | 
			
		||||
    this.initPrefs();
 | 
			
		||||
    // Initialize notifier callback
 | 
			
		||||
    this.initNotifier();
 | 
			
		||||
    // Initialize UI elements
 | 
			
		||||
    this._Addon.views.initViews();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onUnInit(): void {
 | 
			
		||||
    ZToolkit.Tool.log("uninit called");
 | 
			
		||||
    this.unInitPrefs();
 | 
			
		||||
    //  Remove elements and do clean up
 | 
			
		||||
    this._Addon.views.unInitViews();
 | 
			
		||||
    // Remove addon object
 | 
			
		||||
    Zotero.AddonTemplate = undefined;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private initGlobalVariables() {
 | 
			
		||||
    _globalThis.ZToolkit = new ZoteroToolkit();
 | 
			
		||||
    ZToolkit.Tool.logOptionsGlobal.prefix = `[${config.addonName}]`;
 | 
			
		||||
    _globalThis.Zotero = ZToolkit.Compat.getGlobal("Zotero");
 | 
			
		||||
    _globalThis.ZoteroPane = ZToolkit.Compat.getGlobal("ZoteroPane");
 | 
			
		||||
    _globalThis.Zotero_Tabs = ZToolkit.Compat.getGlobal("Zotero_Tabs");
 | 
			
		||||
    _globalThis.window = ZToolkit.Compat.getGlobal("window");
 | 
			
		||||
    _globalThis.document = ZToolkit.Compat.getGlobal("document");
 | 
			
		||||
    ZToolkit.Tool.log("initializeing global variables");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private initNotifier() {
 | 
			
		||||
    const callback = {
 | 
			
		||||
      notify: async (
 | 
			
		||||
        event: string,
 | 
			
		||||
        type: string,
 | 
			
		||||
        ids: Array<string>,
 | 
			
		||||
        extraData: { [key: string]: any }
 | 
			
		||||
      ) => {
 | 
			
		||||
        // You can add your code to the corresponding notify type
 | 
			
		||||
        if (
 | 
			
		||||
          event == "select" &&
 | 
			
		||||
          type == "tab" &&
 | 
			
		||||
          extraData[ids[0]].type == "reader"
 | 
			
		||||
        ) {
 | 
			
		||||
          // Select a reader tab
 | 
			
		||||
        }
 | 
			
		||||
        if (event == "add" && type == "item") {
 | 
			
		||||
          // Add an item
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Register the callback in Zotero as an item observer
 | 
			
		||||
    let notifierID = Zotero.Notifier.registerObserver(callback, [
 | 
			
		||||
      "tab",
 | 
			
		||||
      "item",
 | 
			
		||||
      "file",
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    // Unregister callback when the window closes (important to avoid a memory leak)
 | 
			
		||||
    Zotero.getMainWindow().addEventListener(
 | 
			
		||||
      "unload",
 | 
			
		||||
      function (e: Event) {
 | 
			
		||||
        Zotero.Notifier.unregisterObserver(notifierID);
 | 
			
		||||
      },
 | 
			
		||||
      false
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private initPrefs() {
 | 
			
		||||
    const prefOptions = {
 | 
			
		||||
      pluginID: config.addonID,
 | 
			
		||||
      src: rootURI + "chrome/content/preferences.xhtml",
 | 
			
		||||
      label: this._Addon.locale.getString("prefs.title"),
 | 
			
		||||
      image: `chrome://${config.addonRef}/content/icons/favicon.png`,
 | 
			
		||||
      extraDTD: [`chrome://${config.addonRef}/locale/overlay.dtd`],
 | 
			
		||||
      defaultXUL: true,
 | 
			
		||||
      onload: (win: Window) => {
 | 
			
		||||
        this._Addon.prefs.initPreferences(win);
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
    if (ZToolkit.Compat.isZotero7()) {
 | 
			
		||||
      Zotero.PreferencePanes.register(prefOptions);
 | 
			
		||||
    } else {
 | 
			
		||||
      ZToolkit.Compat.registerPrefPane(prefOptions);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private unInitPrefs() {
 | 
			
		||||
    if (!ZToolkit.Compat.isZotero7()) {
 | 
			
		||||
      ZToolkit.Compat.unregisterPrefPane();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default AddonEvents;
 | 
			
		||||
@ -1,27 +1,100 @@
 | 
			
		||||
import Addon from "./addon";
 | 
			
		||||
import AddonModule from "./module";
 | 
			
		||||
import { log } from "zotero-plugin-toolkit/dist/utils";
 | 
			
		||||
import { config } from "../package.json";
 | 
			
		||||
 | 
			
		||||
class AddonViews extends AddonModule {
 | 
			
		||||
  // You can store some element in the object attributes
 | 
			
		||||
  private progressWindowIcon: { [key: string]: string };
 | 
			
		||||
 | 
			
		||||
  constructor(parent: Addon) {
 | 
			
		||||
    super(parent);
 | 
			
		||||
    this.progressWindowIcon = {
 | 
			
		||||
      success: "chrome://zotero/skin/tick.png",
 | 
			
		||||
      fail: "chrome://zotero/skin/cross.png",
 | 
			
		||||
      default: `chrome://${config.addonRef}/content/icons/favicon.png`,
 | 
			
		||||
export function example(type?: string): MethodDecorator {
 | 
			
		||||
  return function (
 | 
			
		||||
    target: Object,
 | 
			
		||||
    propertyKey: string | symbol,
 | 
			
		||||
    descriptor: PropertyDescriptor
 | 
			
		||||
  ) {
 | 
			
		||||
    log("Calling example", target, type, propertyKey, descriptor);
 | 
			
		||||
    return descriptor;
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  public initViews() {
 | 
			
		||||
    // You can init the UI elements that
 | 
			
		||||
    // cannot be initialized with overlay.xul
 | 
			
		||||
    ZToolkit.Tool.log("Initializing UI");
 | 
			
		||||
export class BasicExampleFactory {
 | 
			
		||||
  @example()
 | 
			
		||||
  static registerNotifier() {
 | 
			
		||||
    const callback = {
 | 
			
		||||
      notify: async (
 | 
			
		||||
        event: string,
 | 
			
		||||
        type: string,
 | 
			
		||||
        ids: Array<string>,
 | 
			
		||||
        extraData: { [key: string]: any }
 | 
			
		||||
      ) => {
 | 
			
		||||
        if (!addon.alive) {
 | 
			
		||||
          this.unregisterNotifier(notifierID);
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        ztoolkit.Tool.log("notify", event, type, ids, extraData);
 | 
			
		||||
        // You can add your code to the corresponding notify type
 | 
			
		||||
        if (
 | 
			
		||||
          event == "select" &&
 | 
			
		||||
          type == "tab" &&
 | 
			
		||||
          extraData[ids[0]].type == "reader"
 | 
			
		||||
        ) {
 | 
			
		||||
          // Select a reader tab
 | 
			
		||||
        }
 | 
			
		||||
        if (event == "add" && type == "item") {
 | 
			
		||||
          // Add an item
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // register style sheet
 | 
			
		||||
    const styles = ZToolkit.UI.creatElementsFromJSON(document, {
 | 
			
		||||
    // Register the callback in Zotero as an item observer
 | 
			
		||||
    const notifierID = Zotero.Notifier.registerObserver(callback, [
 | 
			
		||||
      "tab",
 | 
			
		||||
      "item",
 | 
			
		||||
      "file",
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    // Unregister callback when the window closes (important to avoid a memory leak)
 | 
			
		||||
    window.addEventListener(
 | 
			
		||||
      "unload",
 | 
			
		||||
      (e: Event) => {
 | 
			
		||||
        this.unregisterNotifier(notifierID);
 | 
			
		||||
      },
 | 
			
		||||
      false
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @example()
 | 
			
		||||
  private static unregisterNotifier(notifierID: string) {
 | 
			
		||||
    Zotero.Notifier.unregisterObserver(notifierID);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @example()
 | 
			
		||||
  static registerPrefs() {
 | 
			
		||||
    const prefOptions = {
 | 
			
		||||
      pluginID: config.addonID,
 | 
			
		||||
      src: rootURI + "chrome/content/preferences.xhtml",
 | 
			
		||||
      label: addon.locale.getString("prefs.title"),
 | 
			
		||||
      image: `chrome://${config.addonRef}/content/icons/favicon.png`,
 | 
			
		||||
      extraDTD: [`chrome://${config.addonRef}/locale/overlay.dtd`],
 | 
			
		||||
      defaultXUL: true,
 | 
			
		||||
      onload: (win: Window) => {
 | 
			
		||||
        addon.prefs.initPreferences(win);
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
    if (ztoolkit.Compat.isZotero7()) {
 | 
			
		||||
      Zotero.PreferencePanes.register(prefOptions);
 | 
			
		||||
    } else {
 | 
			
		||||
      ztoolkit.Compat.registerPrefPane(prefOptions);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @example()
 | 
			
		||||
  static unregisterPrefs() {
 | 
			
		||||
    if (!ztoolkit.Compat.isZotero7()) {
 | 
			
		||||
      ztoolkit.Compat.unregisterPrefPane();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class UIExampleFactory {
 | 
			
		||||
  @example()
 | 
			
		||||
  static registerStyleSheet() {
 | 
			
		||||
    const styles = ztoolkit.UI.creatElementsFromJSON(document, {
 | 
			
		||||
      tag: "link",
 | 
			
		||||
      directAttributes: {
 | 
			
		||||
        type: "text/css",
 | 
			
		||||
@ -33,26 +106,32 @@ class AddonViews extends AddonModule {
 | 
			
		||||
    document
 | 
			
		||||
      .getElementById("zotero-item-pane-content")
 | 
			
		||||
      ?.classList.add("makeItRed");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @example()
 | 
			
		||||
  static registerRightClickMenuItem() {
 | 
			
		||||
    const menuIcon = `chrome://${config.addonRef}/content/icons/favicon@0.5x.png`;
 | 
			
		||||
    // item menuitem with icon
 | 
			
		||||
    ZToolkit.UI.insertMenuItem("item", {
 | 
			
		||||
    ztoolkit.UI.insertMenuItem("item", {
 | 
			
		||||
      tag: "menuitem",
 | 
			
		||||
      id: "zotero-itemmenu-addontemplate-test",
 | 
			
		||||
      label: this._Addon.locale.getString("menuitem.label"),
 | 
			
		||||
      label: addon.locale.getString("menuitem.label"),
 | 
			
		||||
      oncommand: "alert('Hello World! Default Menuitem.')",
 | 
			
		||||
      icon: menuIcon,
 | 
			
		||||
    });
 | 
			
		||||
    // item menupopup with sub-menuitems
 | 
			
		||||
    ZToolkit.UI.insertMenuItem(
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @example()
 | 
			
		||||
  static registerRightClickMenuPopup() {
 | 
			
		||||
    ztoolkit.UI.insertMenuItem(
 | 
			
		||||
      "item",
 | 
			
		||||
      {
 | 
			
		||||
        tag: "menu",
 | 
			
		||||
        label: this._Addon.locale.getString("menupopup.label"),
 | 
			
		||||
        label: addon.locale.getString("menupopup.label"),
 | 
			
		||||
        subElementOptions: [
 | 
			
		||||
          {
 | 
			
		||||
            tag: "menuitem",
 | 
			
		||||
            label: this._Addon.locale.getString("menuitem.submenulabel"),
 | 
			
		||||
            label: addon.locale.getString("menuitem.submenulabel"),
 | 
			
		||||
            oncommand: "alert('Hello World! Sub Menuitem.')",
 | 
			
		||||
          },
 | 
			
		||||
        ],
 | 
			
		||||
@ -62,24 +141,24 @@ class AddonViews extends AddonModule {
 | 
			
		||||
        "#zotero-itemmenu-addontemplate-test"
 | 
			
		||||
      ) as XUL.MenuItem
 | 
			
		||||
    );
 | 
			
		||||
    ZToolkit.UI.insertMenuItem("menuFile", {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @example()
 | 
			
		||||
  static registerWindowMenuWithSeprator() {
 | 
			
		||||
    ztoolkit.UI.insertMenuItem("menuFile", {
 | 
			
		||||
      tag: "menuseparator",
 | 
			
		||||
    });
 | 
			
		||||
    // menu->File menuitem
 | 
			
		||||
    ZToolkit.UI.insertMenuItem("menuFile", {
 | 
			
		||||
    ztoolkit.UI.insertMenuItem("menuFile", {
 | 
			
		||||
      tag: "menuitem",
 | 
			
		||||
      label: this._Addon.locale.getString("menuitem.filemenulabel"),
 | 
			
		||||
      label: addon.locale.getString("menuitem.filemenulabel"),
 | 
			
		||||
      oncommand: "alert('Hello World! File Menuitem.')",
 | 
			
		||||
    });
 | 
			
		||||
    /**
 | 
			
		||||
     *  Example: menu items ends
 | 
			
		||||
     */
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  Example: extra column starts
 | 
			
		||||
     */
 | 
			
		||||
    // Initialize extra columns
 | 
			
		||||
    ZToolkit.ItemTree.register(
 | 
			
		||||
  @example()
 | 
			
		||||
  static async registerExtraColumn() {
 | 
			
		||||
    await ztoolkit.ItemTree.register(
 | 
			
		||||
      "test1",
 | 
			
		||||
      "text column",
 | 
			
		||||
      (
 | 
			
		||||
@ -94,7 +173,11 @@ class AddonViews extends AddonModule {
 | 
			
		||||
        iconPath: "chrome://zotero/skin/cross.png",
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
    ZToolkit.ItemTree.register(
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @example()
 | 
			
		||||
  static async registerExtraColumnWithCustomCell() {
 | 
			
		||||
    await ztoolkit.ItemTree.register(
 | 
			
		||||
      "test2",
 | 
			
		||||
      "custom column",
 | 
			
		||||
      (
 | 
			
		||||
@ -117,15 +200,11 @@ class AddonViews extends AddonModule {
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
    /**
 | 
			
		||||
     *  Example: extra column ends
 | 
			
		||||
     */
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  Example: custom cell starts
 | 
			
		||||
     */
 | 
			
		||||
    // Customize cells
 | 
			
		||||
    ZToolkit.ItemTree.addRenderCellHook(
 | 
			
		||||
  @example()
 | 
			
		||||
  static async registerCustomCellRenderer() {
 | 
			
		||||
    await ztoolkit.ItemTree.addRenderCellHook(
 | 
			
		||||
      "title",
 | 
			
		||||
      (index: number, data: string, column: any, original: Function) => {
 | 
			
		||||
        const span = original(index, data, column) as HTMLSpanElement;
 | 
			
		||||
@ -134,17 +213,17 @@ class AddonViews extends AddonModule {
 | 
			
		||||
        return span;
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
    /**
 | 
			
		||||
     *  Example: custom cell ends
 | 
			
		||||
     */
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    // This is a private method. Make it public in toolkit.
 | 
			
		||||
    await ztoolkit.ItemTree.refresh();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  Example: extra library tab starts
 | 
			
		||||
     */
 | 
			
		||||
    const libTabId = ZToolkit.UI.registerLibraryTabPanel(
 | 
			
		||||
      this._Addon.locale.getString("tabpanel.lib.tab.label"),
 | 
			
		||||
  @example()
 | 
			
		||||
  static registerLibraryTabPanel() {
 | 
			
		||||
    const tabId = ztoolkit.UI.registerLibraryTabPanel(
 | 
			
		||||
      addon.locale.getString("tabpanel.lib.tab.label"),
 | 
			
		||||
      (panel: XUL.Element, win: Window) => {
 | 
			
		||||
        const elem = ZToolkit.UI.creatElementsFromJSON(win.document, {
 | 
			
		||||
        const elem = ztoolkit.UI.creatElementsFromJSON(win.document, {
 | 
			
		||||
          tag: "vbox",
 | 
			
		||||
          namespace: "xul",
 | 
			
		||||
          subElementOptions: [
 | 
			
		||||
@ -172,7 +251,7 @@ class AddonViews extends AddonModule {
 | 
			
		||||
                {
 | 
			
		||||
                  type: "click",
 | 
			
		||||
                  listener: () => {
 | 
			
		||||
                    ZToolkit.UI.unregisterLibraryTabPanel(libTabId);
 | 
			
		||||
                    ztoolkit.UI.unregisterLibraryTabPanel(tabId);
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
              ],
 | 
			
		||||
@ -185,30 +264,26 @@ class AddonViews extends AddonModule {
 | 
			
		||||
        targetIndex: 1,
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
    /**
 | 
			
		||||
     *  Example: extra library tab ends
 | 
			
		||||
     */
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  Example: extra reader tab starts
 | 
			
		||||
     */
 | 
			
		||||
    const readerTabId = `${config.addonRef}-extra-reader-tab`;
 | 
			
		||||
    ZToolkit.UI.registerReaderTabPanel(
 | 
			
		||||
      this._Addon.locale.getString("tabpanel.reader.tab.label"),
 | 
			
		||||
  @example()
 | 
			
		||||
  static async registerReaderTabPanel() {
 | 
			
		||||
    const tabId = await ztoolkit.UI.registerReaderTabPanel(
 | 
			
		||||
      addon.locale.getString("tabpanel.reader.tab.label"),
 | 
			
		||||
      (
 | 
			
		||||
        panel: XUL.Element,
 | 
			
		||||
        panel: XUL.TabPanel | undefined,
 | 
			
		||||
        deck: XUL.Deck,
 | 
			
		||||
        win: Window,
 | 
			
		||||
        reader: _ZoteroReaderInstance
 | 
			
		||||
      ) => {
 | 
			
		||||
        if (!panel) {
 | 
			
		||||
          ZToolkit.Tool.log(
 | 
			
		||||
          ztoolkit.Tool.log(
 | 
			
		||||
            "This reader do not have right-side bar. Adding reader tab skipped."
 | 
			
		||||
          );
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        ZToolkit.Tool.log(reader);
 | 
			
		||||
        const elem = ZToolkit.UI.creatElementsFromJSON(win.document, {
 | 
			
		||||
        ztoolkit.Tool.log(reader);
 | 
			
		||||
        const elem = ztoolkit.UI.creatElementsFromJSON(win.document, {
 | 
			
		||||
          tag: "vbox",
 | 
			
		||||
          id: `${config.addonRef}-${reader._instanceID}-extra-reader-tab-div`,
 | 
			
		||||
          namespace: "xul",
 | 
			
		||||
@ -254,7 +329,7 @@ class AddonViews extends AddonModule {
 | 
			
		||||
                {
 | 
			
		||||
                  type: "click",
 | 
			
		||||
                  listener: () => {
 | 
			
		||||
                    ZToolkit.UI.unregisterReaderTabPanel(readerTabId);
 | 
			
		||||
                    ztoolkit.UI.unregisterReaderTabPanel(tabId);
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
              ],
 | 
			
		||||
@ -264,49 +339,13 @@ class AddonViews extends AddonModule {
 | 
			
		||||
        panel.append(elem);
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        tabId: readerTabId,
 | 
			
		||||
        targetIndex: 1,
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
    /**
 | 
			
		||||
     *  Example: extra reader tab ends
 | 
			
		||||
     */
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public unInitViews() {
 | 
			
		||||
    ZToolkit.Tool.log("Uninitializing UI");
 | 
			
		||||
    ZToolkit.unregisterAll();
 | 
			
		||||
    // toolkit.UI.removeAddonElements();
 | 
			
		||||
    // // Remove extra columns
 | 
			
		||||
    // toolkit.ItemTree.unregister("test1");
 | 
			
		||||
    // toolkit.ItemTree.unregister("test2");
 | 
			
		||||
 | 
			
		||||
    // // Remove title cell patch
 | 
			
		||||
    // toolkit.ItemTree.removeRenderCellHook("title");
 | 
			
		||||
 | 
			
		||||
    // toolkit.UI.unregisterReaderTabPanel(
 | 
			
		||||
    //   `${config.addonRef}-extra-reader-tab`
 | 
			
		||||
    // );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public showProgressWindow(
 | 
			
		||||
    header: string,
 | 
			
		||||
    context: string,
 | 
			
		||||
    type: string = "default",
 | 
			
		||||
    t: number = 5000
 | 
			
		||||
  ) {
 | 
			
		||||
    // A simple wrapper of the Zotero ProgressWindow
 | 
			
		||||
    let progressWindow = new Zotero.ProgressWindow({ closeOnClick: true });
 | 
			
		||||
    progressWindow.changeHeadline(header);
 | 
			
		||||
    progressWindow.progress = new progressWindow.ItemProgress(
 | 
			
		||||
      this.progressWindowIcon[type],
 | 
			
		||||
      context
 | 
			
		||||
    );
 | 
			
		||||
    progressWindow.show();
 | 
			
		||||
    if (t > 0) {
 | 
			
		||||
      progressWindow.startCloseTimer(t);
 | 
			
		||||
  @example()
 | 
			
		||||
  static unregisterUIExamples() {
 | 
			
		||||
    ztoolkit.unregisterAll();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default AddonViews;
 | 
			
		||||
							
								
								
									
										62
									
								
								src/hooks.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/hooks.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
import { BasicExampleFactory, UIExampleFactory } from "./examples";
 | 
			
		||||
import { changeProgressWindowLine, showProgressWindow } from "./tools/progress";
 | 
			
		||||
import { config } from "../package.json";
 | 
			
		||||
 | 
			
		||||
class AddonHooks {
 | 
			
		||||
  public async onStartup() {
 | 
			
		||||
    addon.locale.initLocale();
 | 
			
		||||
 | 
			
		||||
    const w = showProgressWindow(
 | 
			
		||||
      config.addonName,
 | 
			
		||||
      addon.locale.getString("startup.begin"),
 | 
			
		||||
      "default",
 | 
			
		||||
      -1
 | 
			
		||||
    );
 | 
			
		||||
    changeProgressWindowLine(w, { newProgress: 0 });
 | 
			
		||||
 | 
			
		||||
    BasicExampleFactory.registerPrefs();
 | 
			
		||||
 | 
			
		||||
    BasicExampleFactory.registerNotifier();
 | 
			
		||||
 | 
			
		||||
    await Zotero.Promise.delay(1000);
 | 
			
		||||
    changeProgressWindowLine(w, {
 | 
			
		||||
      newProgress: 30,
 | 
			
		||||
      newText: `[30%] ${addon.locale.getString("startup.begin")}`,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    UIExampleFactory.registerStyleSheet();
 | 
			
		||||
 | 
			
		||||
    UIExampleFactory.registerRightClickMenuItem();
 | 
			
		||||
 | 
			
		||||
    UIExampleFactory.registerRightClickMenuPopup();
 | 
			
		||||
 | 
			
		||||
    UIExampleFactory.registerWindowMenuWithSeprator();
 | 
			
		||||
 | 
			
		||||
    await UIExampleFactory.registerExtraColumn();
 | 
			
		||||
 | 
			
		||||
    await UIExampleFactory.registerExtraColumnWithCustomCell();
 | 
			
		||||
 | 
			
		||||
    await UIExampleFactory.registerCustomCellRenderer();
 | 
			
		||||
 | 
			
		||||
    UIExampleFactory.registerLibraryTabPanel();
 | 
			
		||||
 | 
			
		||||
    await UIExampleFactory.registerReaderTabPanel();
 | 
			
		||||
 | 
			
		||||
    await Zotero.Promise.delay(1000);
 | 
			
		||||
    changeProgressWindowLine(w, {
 | 
			
		||||
      newProgress: 100,
 | 
			
		||||
      newText: `[100%] ${addon.locale.getString("startup.finish")}`,
 | 
			
		||||
    });
 | 
			
		||||
    w.startCloseTimer(5000);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onShutdown(): void {
 | 
			
		||||
    BasicExampleFactory.unregisterPrefs();
 | 
			
		||||
    UIExampleFactory.unregisterUIExamples();
 | 
			
		||||
    // Remove addon object
 | 
			
		||||
    addon.alive = false;
 | 
			
		||||
    delete Zotero.AddonTemplate;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default AddonHooks;
 | 
			
		||||
							
								
								
									
										23
									
								
								src/index.ts
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								src/index.ts
									
									
									
									
									
								
							@ -1,7 +1,22 @@
 | 
			
		||||
import ZoteroToolkit from "zotero-plugin-toolkit";
 | 
			
		||||
import { getGlobal } from "zotero-plugin-toolkit/dist/utils";
 | 
			
		||||
import Addon from "./addon";
 | 
			
		||||
import { config } from "../package.json";
 | 
			
		||||
 | 
			
		||||
if (!Zotero.AddonTemplate) {
 | 
			
		||||
  Zotero.AddonTemplate = new Addon();
 | 
			
		||||
  // @ts-ignore
 | 
			
		||||
  Zotero.AddonTemplate.events.onInit();
 | 
			
		||||
if (!getGlobal("Zotero").AddonTemplate) {
 | 
			
		||||
  // Set global variables
 | 
			
		||||
  _globalThis.Zotero = getGlobal("Zotero");
 | 
			
		||||
  _globalThis.ZoteroPane = getGlobal("ZoteroPane");
 | 
			
		||||
  _globalThis.Zotero_Tabs = getGlobal("Zotero_Tabs");
 | 
			
		||||
  _globalThis.window = getGlobal("window");
 | 
			
		||||
  _globalThis.document = getGlobal("document");
 | 
			
		||||
  _globalThis.ztoolkit = new ZoteroToolkit();
 | 
			
		||||
  _globalThis.addon = new Addon();
 | 
			
		||||
  // The env will be replaced after esbuild
 | 
			
		||||
  addon.env = __env__;
 | 
			
		||||
  ztoolkit.Tool.logOptionsGlobal.prefix = `[${config.addonName}]`;
 | 
			
		||||
  ztoolkit.Tool.logOptionsGlobal.disableConsole = addon.env === "production";
 | 
			
		||||
  Zotero.AddonTemplate = addon;
 | 
			
		||||
  // Trigger addon hook for initialization
 | 
			
		||||
  addon.hooks.onStartup();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
import AddonModule from "./module";
 | 
			
		||||
import { config } from "../package.json";
 | 
			
		||||
 | 
			
		||||
class AddonLocale extends AddonModule {
 | 
			
		||||
class AddonLocale {
 | 
			
		||||
  private stringBundle: any;
 | 
			
		||||
 | 
			
		||||
  public initLocale() {
 | 
			
		||||
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
import Addon from "./addon";
 | 
			
		||||
 | 
			
		||||
class AddonModule {
 | 
			
		||||
  protected _Addon: Addon;
 | 
			
		||||
  constructor(parent: Addon) {
 | 
			
		||||
    this._Addon = parent;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default AddonModule;
 | 
			
		||||
							
								
								
									
										14
									
								
								src/prefs.ts
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/prefs.ts
									
									
									
									
									
								
							@ -1,17 +1,12 @@
 | 
			
		||||
import Addon from "./addon";
 | 
			
		||||
import AddonModule from "./module";
 | 
			
		||||
import { config } from "../package.json";
 | 
			
		||||
 | 
			
		||||
class AddonPrefs extends AddonModule {
 | 
			
		||||
class AddonPrefs {
 | 
			
		||||
  private _window!: Window;
 | 
			
		||||
  constructor(parent: Addon) {
 | 
			
		||||
    super(parent);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public initPreferences(_window: Window) {
 | 
			
		||||
    // This function is called when the prefs window is opened
 | 
			
		||||
    // See addon/chrome/content/preferences.xul onpaneload
 | 
			
		||||
    this._window = _window;
 | 
			
		||||
    ZToolkit.Tool.log("init preferences");
 | 
			
		||||
    this.updatePrefsUI();
 | 
			
		||||
    this.bindPrefEvents();
 | 
			
		||||
  }
 | 
			
		||||
@ -20,14 +15,13 @@ class AddonPrefs extends AddonModule {
 | 
			
		||||
    // You can initialize some UI elements on prefs window
 | 
			
		||||
    // with this._window.document
 | 
			
		||||
    // Or bind some events to the elements
 | 
			
		||||
    ZToolkit.Tool.log("init preferences UI");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private bindPrefEvents() {
 | 
			
		||||
    this._window.document
 | 
			
		||||
      .querySelector(`#zotero-prefpane-${config.addonRef}-enable`)
 | 
			
		||||
      ?.addEventListener("command", (e) => {
 | 
			
		||||
        ZToolkit.Tool.log(e);
 | 
			
		||||
        ztoolkit.Tool.log(e);
 | 
			
		||||
        this._window.alert(
 | 
			
		||||
          `Successfully changed to ${(e.target as XUL.Checkbox).checked}!`
 | 
			
		||||
        );
 | 
			
		||||
@ -36,7 +30,7 @@ class AddonPrefs extends AddonModule {
 | 
			
		||||
    this._window.document
 | 
			
		||||
      .querySelector(`#zotero-prefpane-${config.addonRef}-input`)
 | 
			
		||||
      ?.addEventListener("change", (e) => {
 | 
			
		||||
        ZToolkit.Tool.log(e);
 | 
			
		||||
        ztoolkit.Tool.log(e);
 | 
			
		||||
        this._window.alert(
 | 
			
		||||
          `Successfully changed to ${(e.target as HTMLInputElement).value}!`
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										48
									
								
								src/tools/progress.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/tools/progress.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
import { config } from "../../package.json";
 | 
			
		||||
 | 
			
		||||
const progressWindowIcon = {
 | 
			
		||||
  success: "chrome://zotero/skin/tick.png",
 | 
			
		||||
  fail: "chrome://zotero/skin/cross.png",
 | 
			
		||||
  default: `chrome://${config.addonRef}/content/icons/favicon.png`,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function showProgressWindow(
 | 
			
		||||
  header: string,
 | 
			
		||||
  context: string,
 | 
			
		||||
  type: "success" | "fail" | "default" = "default",
 | 
			
		||||
  t: number = 5000
 | 
			
		||||
): _ZoteroProgressWindow {
 | 
			
		||||
  // A simple wrapper of the Zotero ProgressWindow
 | 
			
		||||
  let progressWindow = new Zotero.ProgressWindow({
 | 
			
		||||
    closeOnClick: true,
 | 
			
		||||
  }) as _ZoteroProgressWindow;
 | 
			
		||||
  progressWindow.changeHeadline(header);
 | 
			
		||||
  // @ts-ignore
 | 
			
		||||
  progressWindow.progress = new progressWindow.ItemProgress(
 | 
			
		||||
    progressWindowIcon[type],
 | 
			
		||||
    context
 | 
			
		||||
  );
 | 
			
		||||
  progressWindow.show();
 | 
			
		||||
  if (t > 0) {
 | 
			
		||||
    progressWindow.startCloseTimer(t);
 | 
			
		||||
  }
 | 
			
		||||
  return progressWindow;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function changeProgressWindowLine(
 | 
			
		||||
  progressWindow: _ZoteroProgressWindow,
 | 
			
		||||
  options: {
 | 
			
		||||
    newText?: string;
 | 
			
		||||
    newIcon?: string;
 | 
			
		||||
    newProgress?: number;
 | 
			
		||||
  }
 | 
			
		||||
) {
 | 
			
		||||
  // @ts-ignore
 | 
			
		||||
  const progress = progressWindow.progress as _ZoteroItemProgress;
 | 
			
		||||
  if (!progress) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  options.newText && progress.setText(options.newText);
 | 
			
		||||
  options.newIcon && progress.setIcon(options.newIcon);
 | 
			
		||||
  options.newProgress && progress.setProgress(options.newProgress);
 | 
			
		||||
}
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "experimentalDecorators": true,
 | 
			
		||||
    "module": "commonjs",
 | 
			
		||||
    "target": "ES2016",
 | 
			
		||||
    "resolveJsonModule": true,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								typing/global.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								typing/global.d.ts
									
									
									
									
										vendored
									
									
								
							@ -5,9 +5,14 @@ declare const _globalThis: {
 | 
			
		||||
  Zotero_Tabs: typeof Zotero_Tabs;
 | 
			
		||||
  window: Window;
 | 
			
		||||
  document: Document;
 | 
			
		||||
  ZToolkit: typeof ZToolkit;
 | 
			
		||||
  ztoolkit: typeof ztoolkit;
 | 
			
		||||
  addon: typeof addon;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
declare const ZToolkit: import("zotero-plugin-toolkit").ZoteroToolkit;
 | 
			
		||||
declare const ztoolkit: import("zotero-plugin-toolkit").ZoteroToolkit;
 | 
			
		||||
 | 
			
		||||
declare const rootURI: string;
 | 
			
		||||
 | 
			
		||||
declare const addon: import("../src/addon").default;
 | 
			
		||||
 | 
			
		||||
declare const __env__: "production" | "development";
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user