export async function waitNoMoreThan( promise: Promise, timeout: number = 3000, message: string = "Timeout", ) { let resolved = false; return Promise.any([ promise.then((result) => { resolved = true; return result; }), Zotero.Promise.delay(timeout).then(() => { if (resolved) return; throw new Error(message); }), ]); } export async function waitForNotifierEvent( event: _ZoteroTypes.Notifier.Event, type: _ZoteroTypes.Notifier.Type, timeout: number = 3000, ) { if (!event) throw new Error("event not provided"); let resolved = false; return waitNoMoreThan( new Promise((resolve, reject) => { const notifierID = Zotero.Notifier.registerObserver( { notify: function (ev, type, ids, extraData) { if (ev == event) { Zotero.Notifier.unregisterObserver(notifierID); resolved = true; resolve({ ids: ids, extraData: extraData, }); } }, }, [type], "test", 101, ); }), timeout, ); } export function waitForTabSelectEvent(timeout: number = 3000) { return waitForNotifierEvent("select", "tab", timeout); } /** * Waits for a window with a specific URL to open. Returns a promise for the window, and * optionally passes the window to a callback immediately for use with modal dialogs, * which prevent async code from continuing */ export async function waitForWindow(uri: string, timeout: number = 3000) { return waitNoMoreThan( new Promise((resolve, reject) => { const loadObserver = function (ev: Event) { ev.originalTarget?.removeEventListener("load", loadObserver, false); const href = (ev.target as Window)?.location.href; Zotero.debug("Window opened: " + href); if (href != uri) { Zotero.debug(`Ignoring window ${href} in waitForWindow()`); return; } Services.ww.unregisterNotification(winObserver); const win = ev.target?.ownerGlobal; // Give window code time to run on load win?.setTimeout(function () { resolve(win); }); }; const winObserver = { observe: function (subject: Window, topic: string, data: any) { if (topic != "domwindowopened") return; subject.addEventListener("load", loadObserver, false); }, } as nsIObserver; Services.ww.registerNotification(winObserver); }), timeout, ); } export async function waitForNoteWindow() { return await waitForWindow("chrome://zotero/content/note.xhtml"); }