add: window load hook
This commit is contained in:
parent
96245a0923
commit
4f5f6f8e12
103
addon/bootstrap.js
vendored
103
addon/bootstrap.js
vendored
@ -11,6 +11,8 @@ if (typeof Zotero == "undefined") {
|
|||||||
|
|
||||||
var chromeHandle;
|
var chromeHandle;
|
||||||
|
|
||||||
|
var windowListener;
|
||||||
|
|
||||||
// In Zotero 6, bootstrap methods are called before Zotero is initialized, and using include.js
|
// In Zotero 6, bootstrap methods are called before Zotero is initialized, and using include.js
|
||||||
// to get the Zotero XPCOM service would risk breaking Zotero startup. Instead, wait for the main
|
// to get the Zotero XPCOM service would risk breaking Zotero startup. Instead, wait for the main
|
||||||
// Zotero window to open and get the Zotero object from there.
|
// Zotero window to open and get the Zotero object from there.
|
||||||
@ -18,53 +20,72 @@ var chromeHandle;
|
|||||||
// In Zotero 7, bootstrap methods are not called until Zotero is initialized, and the 'Zotero' is
|
// In Zotero 7, bootstrap methods are not called until Zotero is initialized, and the 'Zotero' is
|
||||||
// automatically made available.
|
// automatically made available.
|
||||||
async function waitForZotero() {
|
async function waitForZotero() {
|
||||||
if (typeof Zotero != "undefined") {
|
await new Promise(async (resolve) => {
|
||||||
await Zotero.initializationPromise;
|
if (typeof Zotero != "undefined") {
|
||||||
}
|
resolve();
|
||||||
|
|
||||||
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
||||||
var windows = Services.wm.getEnumerator("navigator:browser");
|
|
||||||
var found = false;
|
|
||||||
while (windows.hasMoreElements()) {
|
|
||||||
let win = windows.getNext();
|
|
||||||
if (win.Zotero) {
|
|
||||||
Zotero = win.Zotero;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!found) {
|
const { Services } = ChromeUtils.import(
|
||||||
await new Promise((resolve) => {
|
"resource://gre/modules/Services.jsm",
|
||||||
var listener = {
|
);
|
||||||
onOpenWindow: function (aWindow) {
|
const windows = Services.wm.getEnumerator("navigator:browser");
|
||||||
// Wait for the window to finish loading
|
let found = false;
|
||||||
let domWindow = aWindow
|
while (windows.hasMoreElements()) {
|
||||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
let win = windows.getNext();
|
||||||
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
|
if (win.Zotero) {
|
||||||
domWindow.addEventListener(
|
Zotero = win.Zotero;
|
||||||
"load",
|
found = true;
|
||||||
function () {
|
resolve();
|
||||||
domWindow.removeEventListener("load", arguments.callee, false);
|
break;
|
||||||
if (domWindow.Zotero) {
|
}
|
||||||
Services.wm.removeListener(listener);
|
}
|
||||||
Zotero = domWindow.Zotero;
|
windowListener = {
|
||||||
resolve();
|
onOpenWindow: function (aWindow) {
|
||||||
}
|
// Wait for the window to finish loading
|
||||||
},
|
const domWindow = aWindow
|
||||||
false,
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
);
|
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
|
||||||
},
|
domWindow.addEventListener(
|
||||||
};
|
"load",
|
||||||
Services.wm.addListener(listener);
|
async function () {
|
||||||
});
|
domWindow.removeEventListener("load", arguments.callee, false);
|
||||||
}
|
if (!found && domWindow.Zotero) {
|
||||||
await Zotero.initializationPromise;
|
Zotero = domWindow.Zotero;
|
||||||
|
resolve();
|
||||||
|
} else if (
|
||||||
|
domWindow.location.href ===
|
||||||
|
"chrome://zotero/content/zoteroPane.xhtml"
|
||||||
|
) {
|
||||||
|
// Call the hook for the main window load event
|
||||||
|
// Note that this is not called the first time the window is opened
|
||||||
|
// (when Zotero is initialized), but only when the window is re-opened
|
||||||
|
// after being closed
|
||||||
|
await Zotero.__addonInstance__?.hooks.onMainWindowLoad(domWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onCloseWindow: function (aWindow) {
|
||||||
|
const domWindow = aWindow
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
|
||||||
|
if (
|
||||||
|
domWindow.location.href === "chrome://zotero/content/zoteroPane.xhtml"
|
||||||
|
) {
|
||||||
|
Zotero.__addonInstance__?.hooks.onMainWindowUnload(domWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Services.wm.addListener(windowListener);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function install(data, reason) {}
|
function install(data, reason) {}
|
||||||
|
|
||||||
async function startup({ id, version, resourceURI, rootURI }, reason) {
|
async function startup({ id, version, resourceURI, rootURI }, reason) {
|
||||||
await waitForZotero();
|
await waitForZotero();
|
||||||
|
await Zotero.initializationPromise;
|
||||||
|
|
||||||
// String 'rootURI' introduced in Zotero 7
|
// String 'rootURI' introduced in Zotero 7
|
||||||
if (!rootURI) {
|
if (!rootURI) {
|
||||||
@ -100,6 +121,8 @@ function shutdown({ id, version, resourceURI, rootURI }, reason) {
|
|||||||
if (reason === APP_SHUTDOWN) {
|
if (reason === APP_SHUTDOWN) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Services.wm.removeListener(windowListener);
|
||||||
|
|
||||||
if (typeof Zotero === "undefined") {
|
if (typeof Zotero === "undefined") {
|
||||||
Zotero = Components.classes["@zotero.org/Zotero;1"].getService(
|
Zotero = Components.classes["@zotero.org/Zotero;1"].getService(
|
||||||
Components.interfaces.nsISupports,
|
Components.interfaces.nsISupports,
|
||||||
|
44
src/addon.ts
44
src/addon.ts
@ -1,14 +1,14 @@
|
|||||||
import ZoteroToolkit from "zotero-plugin-toolkit/dist/index";
|
|
||||||
import { ColumnOptions } from "zotero-plugin-toolkit/dist/helpers/virtualizedTable";
|
import { ColumnOptions } from "zotero-plugin-toolkit/dist/helpers/virtualizedTable";
|
||||||
|
import { DialogHelper } from "zotero-plugin-toolkit/dist/helpers/dialog";
|
||||||
import hooks from "./hooks";
|
import hooks from "./hooks";
|
||||||
|
import { createZToolkit } from "./utils/ztoolkit";
|
||||||
|
|
||||||
class Addon {
|
class Addon {
|
||||||
public data: {
|
public data: {
|
||||||
alive: boolean;
|
alive: boolean;
|
||||||
// Env type, see build.js
|
// Env type, see build.js
|
||||||
env: "development" | "production";
|
env: "development" | "production";
|
||||||
// ztoolkit: MyToolkit;
|
ztoolkit: ZToolkit;
|
||||||
ztoolkit: ZoteroToolkit;
|
|
||||||
locale?: {
|
locale?: {
|
||||||
current: any;
|
current: any;
|
||||||
};
|
};
|
||||||
@ -28,47 +28,11 @@ class Addon {
|
|||||||
this.data = {
|
this.data = {
|
||||||
alive: true,
|
alive: true,
|
||||||
env: __env__,
|
env: __env__,
|
||||||
// ztoolkit: new MyToolkit(),
|
ztoolkit: createZToolkit(),
|
||||||
ztoolkit: new ZoteroToolkit(),
|
|
||||||
};
|
};
|
||||||
this.hooks = hooks;
|
this.hooks = hooks;
|
||||||
this.api = {};
|
this.api = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Alternatively, import toolkit modules you use to minify the plugin size.
|
|
||||||
*
|
|
||||||
* Steps to replace the default `ztoolkit: ZoteroToolkit` with your `ztoolkit: MyToolkit`:
|
|
||||||
*
|
|
||||||
* 1. Uncomment this file's line 30: `ztoolkit: new MyToolkit(),`
|
|
||||||
* and comment line 31: `ztoolkit: new ZoteroToolkit(),`.
|
|
||||||
* 2. Uncomment this file's line 10: `ztoolkit: MyToolkit;` in this file
|
|
||||||
* and comment line 11: `ztoolkit: ZoteroToolkit;`.
|
|
||||||
* 3. Uncomment `../typings/global.d.ts` line 12: `declare const ztoolkit: import("../src/addon").MyToolkit;`
|
|
||||||
* and comment line 13: `declare const ztoolkit: import("zotero-plugin-toolkit").ZoteroToolkit;`.
|
|
||||||
*
|
|
||||||
* You can now add the modules under the `MyToolkit` class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { BasicTool, unregister } from "zotero-plugin-toolkit/dist/basic";
|
|
||||||
import { UITool } from "zotero-plugin-toolkit/dist/tools/ui";
|
|
||||||
import { PreferencePaneManager } from "zotero-plugin-toolkit/dist/managers/preferencePane";
|
|
||||||
import { DialogHelper } from "zotero-plugin-toolkit/dist/helpers/dialog";
|
|
||||||
|
|
||||||
export class MyToolkit extends BasicTool {
|
|
||||||
UI: UITool;
|
|
||||||
PreferencePane: PreferencePaneManager;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.UI = new UITool(this);
|
|
||||||
this.PreferencePane = new PreferencePaneManager(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
unregisterAll() {
|
|
||||||
unregister(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Addon;
|
export default Addon;
|
||||||
|
29
src/hooks.ts
29
src/hooks.ts
@ -8,6 +8,7 @@ import {
|
|||||||
import { config } from "../package.json";
|
import { config } from "../package.json";
|
||||||
import { getString, initLocale } from "./utils/locale";
|
import { getString, initLocale } from "./utils/locale";
|
||||||
import { registerPrefsScripts } from "./modules/preferenceScript";
|
import { registerPrefsScripts } from "./modules/preferenceScript";
|
||||||
|
import { createZToolkit } from "./utils/ztoolkit";
|
||||||
|
|
||||||
async function onStartup() {
|
async function onStartup() {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@ -16,10 +17,19 @@ async function onStartup() {
|
|||||||
Zotero.uiReadyPromise,
|
Zotero.uiReadyPromise,
|
||||||
]);
|
]);
|
||||||
initLocale();
|
initLocale();
|
||||||
ztoolkit.ProgressWindow.setIconURI(
|
|
||||||
"default",
|
BasicExampleFactory.registerPrefs();
|
||||||
`chrome://${config.addonRef}/content/icons/favicon.png`,
|
|
||||||
);
|
BasicExampleFactory.registerNotifier();
|
||||||
|
|
||||||
|
await onMainWindowLoad(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onMainWindowLoad(win: Window): Promise<void> {
|
||||||
|
// Create ztoolkit for every window
|
||||||
|
const _ztoolkit = createZToolkit();
|
||||||
|
addon.data.ztoolkit = _ztoolkit;
|
||||||
|
_globalThis.ztoolkit = _ztoolkit;
|
||||||
|
|
||||||
const popupWin = new ztoolkit.ProgressWindow(config.addonName, {
|
const popupWin = new ztoolkit.ProgressWindow(config.addonName, {
|
||||||
closeOnClick: true,
|
closeOnClick: true,
|
||||||
@ -32,10 +42,6 @@ async function onStartup() {
|
|||||||
})
|
})
|
||||||
.show();
|
.show();
|
||||||
|
|
||||||
BasicExampleFactory.registerPrefs();
|
|
||||||
|
|
||||||
BasicExampleFactory.registerNotifier();
|
|
||||||
|
|
||||||
KeyExampleFactory.registerShortcuts();
|
KeyExampleFactory.registerShortcuts();
|
||||||
|
|
||||||
await Zotero.Promise.delay(1000);
|
await Zotero.Promise.delay(1000);
|
||||||
@ -81,6 +87,11 @@ async function onStartup() {
|
|||||||
addon.hooks.onDialogEvents("dialogExample");
|
addon.hooks.onDialogEvents("dialogExample");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onMainWindowUnload(win: Window): Promise<void> {
|
||||||
|
ztoolkit.unregisterAll();
|
||||||
|
addon.data.dialog?.window?.close();
|
||||||
|
}
|
||||||
|
|
||||||
function onShutdown(): void {
|
function onShutdown(): void {
|
||||||
ztoolkit.unregisterAll();
|
ztoolkit.unregisterAll();
|
||||||
addon.data.dialog?.window?.close();
|
addon.data.dialog?.window?.close();
|
||||||
@ -173,6 +184,8 @@ function onDialogEvents(type: string) {
|
|||||||
export default {
|
export default {
|
||||||
onStartup,
|
onStartup,
|
||||||
onShutdown,
|
onShutdown,
|
||||||
|
onMainWindowLoad,
|
||||||
|
onMainWindowUnload,
|
||||||
onNotify,
|
onNotify,
|
||||||
onPrefsEvent,
|
onPrefsEvent,
|
||||||
onShortcuts,
|
onShortcuts,
|
||||||
|
24
src/index.ts
24
src/index.ts
@ -7,21 +7,21 @@ const basicTool = new BasicTool();
|
|||||||
if (!basicTool.getGlobal("Zotero")[config.addonInstance]) {
|
if (!basicTool.getGlobal("Zotero")[config.addonInstance]) {
|
||||||
// Set global variables
|
// Set global variables
|
||||||
_globalThis.Zotero = basicTool.getGlobal("Zotero");
|
_globalThis.Zotero = basicTool.getGlobal("Zotero");
|
||||||
_globalThis.ZoteroPane = basicTool.getGlobal("ZoteroPane");
|
defineGlobal("window");
|
||||||
_globalThis.Zotero_Tabs = basicTool.getGlobal("Zotero_Tabs");
|
defineGlobal("document");
|
||||||
_globalThis.window = basicTool.getGlobal("window");
|
defineGlobal("ZoteroPane");
|
||||||
_globalThis.document = basicTool.getGlobal("document");
|
defineGlobal("Zotero_Tabs");
|
||||||
_globalThis.addon = new Addon();
|
_globalThis.addon = new Addon();
|
||||||
_globalThis.ztoolkit = addon.data.ztoolkit;
|
_globalThis.ztoolkit = addon.data.ztoolkit;
|
||||||
ztoolkit.basicOptions.log.prefix = `[${config.addonName}]`;
|
|
||||||
ztoolkit.basicOptions.log.disableConsole = addon.data.env === "production";
|
|
||||||
ztoolkit.UI.basicOptions.ui.enableElementJSONLog =
|
|
||||||
addon.data.env === "development";
|
|
||||||
ztoolkit.UI.basicOptions.ui.enableElementDOMLog =
|
|
||||||
addon.data.env === "development";
|
|
||||||
ztoolkit.basicOptions.debug.disableDebugBridgePassword =
|
|
||||||
addon.data.env === "development";
|
|
||||||
Zotero[config.addonInstance] = addon;
|
Zotero[config.addonInstance] = addon;
|
||||||
// Trigger addon hook for initialization
|
// Trigger addon hook for initialization
|
||||||
addon.hooks.onStartup();
|
addon.hooks.onStartup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function defineGlobal(name: Parameters<BasicTool["getGlobal"]>[0]) {
|
||||||
|
Object.defineProperty(_globalThis, name, {
|
||||||
|
get() {
|
||||||
|
return basicTool.getGlobal(name);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
48
src/utils/ztoolkit.ts
Normal file
48
src/utils/ztoolkit.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import ZoteroToolkit from "zotero-plugin-toolkit";
|
||||||
|
import { config } from "../../package.json";
|
||||||
|
|
||||||
|
export { createZToolkit };
|
||||||
|
|
||||||
|
function createZToolkit() {
|
||||||
|
const _ztoolkit = new ZoteroToolkit();
|
||||||
|
/**
|
||||||
|
* Alternatively, import toolkit modules you use to minify the plugin size.
|
||||||
|
* You can add the modules under the `MyToolkit` class below and uncomment the following line.
|
||||||
|
*/
|
||||||
|
// const _ztoolkit = new MyToolkit();
|
||||||
|
initZToolkit(_ztoolkit);
|
||||||
|
return _ztoolkit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initZToolkit(_ztoolkit: ReturnType<typeof createZToolkit>) {
|
||||||
|
const env = __env__;
|
||||||
|
_ztoolkit.basicOptions.log.prefix = `[${config.addonName}]`;
|
||||||
|
_ztoolkit.basicOptions.log.disableConsole = env === "production";
|
||||||
|
_ztoolkit.UI.basicOptions.ui.enableElementJSONLog = __env__ === "development";
|
||||||
|
_ztoolkit.UI.basicOptions.ui.enableElementDOMLog = __env__ === "development";
|
||||||
|
_ztoolkit.basicOptions.debug.disableDebugBridgePassword =
|
||||||
|
__env__ === "development";
|
||||||
|
_ztoolkit.ProgressWindow.setIconURI(
|
||||||
|
"default",
|
||||||
|
`chrome://${config.addonRef}/content/icons/favicon.png`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
import { BasicTool, unregister } from "zotero-plugin-toolkit/dist/basic";
|
||||||
|
import { UITool } from "zotero-plugin-toolkit/dist/tools/ui";
|
||||||
|
import { PreferencePaneManager } from "zotero-plugin-toolkit/dist/managers/preferencePane";
|
||||||
|
|
||||||
|
class MyToolkit extends BasicTool {
|
||||||
|
UI: UITool;
|
||||||
|
PreferencePane: PreferencePaneManager;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.UI = new UITool(this);
|
||||||
|
this.PreferencePane = new PreferencePaneManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
unregisterAll() {
|
||||||
|
unregister(this);
|
||||||
|
}
|
||||||
|
}
|
9
typings/global.d.ts
vendored
9
typings/global.d.ts
vendored
@ -5,12 +5,15 @@ declare const _globalThis: {
|
|||||||
Zotero_Tabs: typeof Zotero_Tabs;
|
Zotero_Tabs: typeof Zotero_Tabs;
|
||||||
window: Window;
|
window: Window;
|
||||||
document: Document;
|
document: Document;
|
||||||
ztoolkit: typeof ztoolkit;
|
ztoolkit: ZToolkit;
|
||||||
addon: typeof addon;
|
addon: typeof addon;
|
||||||
};
|
};
|
||||||
|
|
||||||
// declare const ztoolkit: import("../src/addon").MyToolkit;
|
declare type ZToolkit = ReturnType<
|
||||||
declare const ztoolkit: import("zotero-plugin-toolkit").ZoteroToolkit;
|
typeof import("../src/utils/ztoolkit").createZToolkit
|
||||||
|
>;
|
||||||
|
|
||||||
|
declare const ztoolkit: ZToolkit;
|
||||||
|
|
||||||
declare const rootURI: string;
|
declare const rootURI: string;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user