chore: use Zotero.Reader.registerEventListener

This commit is contained in:
windingwind 2023-11-02 20:04:04 +08:00
parent 83cbbb58f5
commit d6cb58c3e7
5 changed files with 62 additions and 161 deletions

View File

@ -98,6 +98,6 @@
"release-it": "^16.1.5",
"replace-in-file": "^7.0.1",
"typescript": "^5.2.2",
"zotero-types": "^1.3.2"
"zotero-types": "^1.3.5"
}
}

View File

@ -26,9 +26,7 @@ import {
import { registerNotify } from "./modules/notify";
import { showWorkspaceWindow } from "./modules/workspace/window";
import {
checkReaderAnnotationButton,
registerReaderInitializer,
unregisterReaderInitializer,
registerReaderAnnotationButton,
} from "./modules/reader";
import { setSyncing, callSyncing } from "./modules/sync/hooks";
import {
@ -70,6 +68,8 @@ async function onStartup() {
registerPrefsWindow();
registerReaderAnnotationButton();
initSyncList();
setSyncing();
@ -88,19 +88,15 @@ async function onMainWindowLoad(win: Window): Promise<void> {
registerWorkspaceTab();
registerReaderInitializer();
initTemplates();
}
async function onMainWindowUnload(win: Window): Promise<void> {
ztoolkit.unregisterAll();
unregisterReaderInitializer();
}
function onShutdown(): void {
ztoolkit.unregisterAll();
unregisterReaderInitializer();
// Remove addon object
addon.data.alive = false;
unregisterWorkspaceTab();
@ -150,15 +146,6 @@ function onNotify(
});
}
}
// Reader annotation buttons update
if (event === "add" && type === "item") {
const annotationItems = Zotero.Items.get(ids as number[]).filter((item) =>
item.isAnnotation(),
);
if (annotationItems.length !== 0) {
checkReaderAnnotationButton(annotationItems);
}
}
// Insert annotation when assigning tag starts with @
if (event === "add" && type === "item-tag") {
annotationTagAction(ids as number[], extraData);

View File

@ -1,153 +1,72 @@
import { TagElementProps } from "zotero-plugin-toolkit/dist/tools/ui";
import { config } from "../../package.json";
import { ICONS } from "../utils/config";
import { getNoteLink, getNoteLinkParams } from "../utils/link";
import { addLineToNote } from "../utils/note";
export function registerReaderInitializer() {
ztoolkit.ReaderInstance.register(
"initialized",
`${config.addonRef}-annotationButtons`,
initializeReaderAnnotationButton,
export function registerReaderAnnotationButton() {
Zotero.Reader.registerEventListener(
"renderSidebarAnnotationHeader",
(event) => {
const { doc, append, params } = event;
const annotationData = params.annotation;
const annotationItem = Zotero.Items.getByLibraryAndKey(
annotationData.libraryID,
annotationData.id,
) as Zotero.Item;
if (!annotationItem) {
return;
}
const itemID = annotationItem.id;
append(
ztoolkit.UI.createElement(doc, "div", {
tag: "div",
classList: ["icon"],
properties: {
innerHTML: ICONS.readerQuickNote,
},
listeners: [
{
type: "click",
listener: (e) => {
createNoteFromAnnotation(
itemID,
(e as MouseEvent).shiftKey ? "standalone" : "auto",
);
e.preventDefault();
},
},
{
type: "mouseover",
listener: (e) => {
(e.target as HTMLElement).style.backgroundColor = "#F0F0F0";
},
},
{
type: "mouseout",
listener: (e) => {
(e.target as HTMLElement).style.removeProperty(
"background-color",
);
},
},
],
enableElementRecord: true,
}),
);
},
config.addonID,
);
// Force re-initialize
Zotero.Reader._readers.forEach((r) => {
initializeReaderAnnotationButton(r);
});
}
export function unregisterReaderInitializer() {
Zotero.Reader._readers.forEach((r) => {
unInitializeReaderAnnotationButton(r);
});
}
export async function checkReaderAnnotationButton(items: Zotero.Item[]) {
const hitSet = new Set<number>();
let t = 0;
const period = 100;
const wait = 5000;
while (items.length > hitSet.size && t < wait) {
for (const instance of Zotero.Reader._readers) {
const hitItems = await initializeReaderAnnotationButton(instance);
hitItems.forEach((item) => hitSet.add(item.id));
}
await Zotero.Promise.delay(period);
t += period;
}
}
async function initializeReaderAnnotationButton(
instance: _ZoteroTypes.ReaderInstance,
): Promise<Zotero.Item[]> {
if (!instance) {
return [];
}
await instance._initPromise;
await instance._waitForReader();
const _document = instance._iframeWindow?.document;
if (!_document) {
return [];
}
const hitItems: Zotero.Item[] = [];
for (const moreButton of Array.from(_document.querySelectorAll(".more"))) {
if (moreButton.getAttribute("_betternotesInitialized") === "true") {
continue;
}
moreButton.setAttribute("_betternotesInitialized", "true");
let annotationWrapper = moreButton;
while (!annotationWrapper.getAttribute("data-sidebar-annotation-id")) {
annotationWrapper = annotationWrapper.parentElement!;
}
const itemKey =
annotationWrapper.getAttribute("data-sidebar-annotation-id") || "";
if (!instance.itemID) {
continue;
}
const libraryID = Zotero.Items.get(instance.itemID).libraryID;
const annotationItem = (await Zotero.Items.getByLibraryAndKeyAsync(
libraryID,
itemKey,
)) as Zotero.Item;
if (!annotationItem) {
continue;
}
hitItems.push(annotationItem);
const annotationButtons: TagElementProps[] = [
{
tag: "div",
classList: ["icon"],
properties: {
innerHTML: ICONS.readerQuickNote,
},
listeners: [
{
type: "click",
listener: (e) => {
createNoteFromAnnotation(
annotationItem,
(e as MouseEvent).shiftKey ? "standalone" : "auto",
);
e.preventDefault();
},
},
{
type: "mouseover",
listener: (e) => {
(e.target as HTMLElement).style.backgroundColor = "#F0F0F0";
},
},
{
type: "mouseout",
listener: (e) => {
(e.target as HTMLElement).style.removeProperty(
"background-color",
);
},
},
],
enableElementRecord: true,
},
];
ztoolkit.UI.insertElementBefore(
{
tag: "fragment",
children: annotationButtons,
},
moreButton,
);
}
return hitItems;
}
async function unInitializeReaderAnnotationButton(
instance: _ZoteroTypes.ReaderInstance,
): Promise<void> {
if (!instance) {
return;
}
await instance._initPromise;
await instance._waitForReader();
const _document = instance._iframeWindow?.document;
if (!_document) {
return;
}
for (const moreButton of Array.from(_document.querySelectorAll(".more"))) {
if (moreButton.getAttribute("_betternotesInitialized") === "true") {
moreButton.removeAttribute("_betternotesInitialized");
}
}
}
async function createNoteFromAnnotation(
annotationItem: Zotero.Item,
itemID: number,
openMode: "standalone" | "auto" = "auto",
) {
const annotationItem = Zotero.Items.get(itemID);
if (!annotationItem) {
return;
}
const annotationTags = annotationItem.getTags().map((_) => _.tag);
const linkRegex = new RegExp("^zotero://note/(.*)$");
for (const tag of annotationTags) {

View File

@ -38,7 +38,6 @@ import { VirtualizedTableHelper } from "zotero-plugin-toolkit/dist/helpers/virtu
import { LibraryTabPanelManager } from "zotero-plugin-toolkit/dist/managers/libraryTabPanel";
import { MenuManager } from "zotero-plugin-toolkit/dist/managers/menu";
import { PromptManager } from "zotero-plugin-toolkit/dist/managers/prompt";
import { ReaderInstanceManager } from "zotero-plugin-toolkit/dist/managers/readerInstance";
import { ReaderTabPanelManager } from "zotero-plugin-toolkit/dist/managers/readerTabPanel";
import { LargePrefHelper } from "zotero-plugin-toolkit/dist/helpers/largePref";
@ -47,7 +46,6 @@ class MyToolkit extends BasicTool {
Prompt: PromptManager;
LibraryTabPanel: LibraryTabPanelManager;
ReaderTabPanel: ReaderTabPanelManager;
ReaderInstance: ReaderInstanceManager;
Menu: MenuManager;
PreferencePane: PreferencePaneManager;
Clipboard: typeof ClipboardHelper;
@ -63,7 +61,6 @@ class MyToolkit extends BasicTool {
this.Prompt = new PromptManager(this);
this.LibraryTabPanel = new LibraryTabPanelManager(this);
this.ReaderTabPanel = new ReaderTabPanelManager(this);
this.ReaderInstance = new ReaderInstanceManager(this);
this.Menu = new MenuManager(this);
this.PreferencePane = new PreferencePaneManager(this);
this.Clipboard = ClipboardHelper;

2
typings/global.d.ts vendored
View File

@ -32,6 +32,4 @@ declare const addon: import("../src/addon").default;
declare const __env__: "production" | "development";
declare const ChromeUtils: any;
declare class Localization {}