From 850f695d3a0678a032407302e301743db8ff206f Mon Sep 17 00:00:00 2001 From: xiangyu <3170102889@zju.edu.cn> Date: Sat, 30 Apr 2022 00:45:40 +0800 Subject: [PATCH] add: workspace window add: knowledge workspace methods fix: protocol bugs --- addon/chrome/content/workspace.xul | 51 +++++++++++ addon/chrome/locale/en-US/overlay.dtd | 2 + src/addon.ts | 1 + src/events.ts | 51 ++++------- src/index.ts | 3 - src/knowledge.ts | 117 ++++++++++++++++++-------- src/views.ts | 15 ++++ src/zotero-protocol-handler.js | 4 +- 8 files changed, 169 insertions(+), 75 deletions(-) create mode 100644 addon/chrome/content/workspace.xul diff --git a/addon/chrome/content/workspace.xul b/addon/chrome/content/workspace.xul new file mode 100644 index 0000000..fbd8f18 --- /dev/null +++ b/addon/chrome/content/workspace.xul @@ -0,0 +1,51 @@ + + + + + + + + %zoteroDTD; + + %knowledgeDTD; +]> + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/addon/chrome/locale/en-US/overlay.dtd b/addon/chrome/locale/en-US/overlay.dtd index 1775113..9831159 100644 --- a/addon/chrome/locale/en-US/overlay.dtd +++ b/addon/chrome/locale/en-US/overlay.dtd @@ -1,3 +1,5 @@ + + diff --git a/src/addon.ts b/src/addon.ts index cf6d93c..6148bac 100644 --- a/src/addon.ts +++ b/src/addon.ts @@ -13,6 +13,7 @@ class Knowledge4Zotero { this.events = new AddonEvents(this); this.views = new AddonViews(this); this.prefs = new AddonPrefs(this); + this.knowledge = new Knowledge } } diff --git a/src/events.ts b/src/events.ts index ca3a1db..1f874a3 100644 --- a/src/events.ts +++ b/src/events.ts @@ -8,7 +8,8 @@ class AddonEvents extends AddonBase { public async onInit() { Zotero.debug("Knowledge4Zotero: init called"); - this._Addon.knowledge = new Knowledge(); + await Zotero.uiReadyPromise; + this._Addon.views.addOpenWorkspaceButton(); this.addEditorInstanceListener(); this.resetState(); } @@ -57,9 +58,8 @@ class AddonEvents extends AddonBase { } public async onEditorEvent(message: EditorMessage) { - Zotero.debug( - `Knowledge4Zotero: onEditorEvent\n${message.type}\n${message.content}` - ); + Zotero.debug(`Knowledge4Zotero: onEditorEvent\n${message.type}`); + Zotero.debug(message.content); if (message.type === "addNoteInstance") { let mainKnowledgeID = parseInt( Zotero.Prefs.get("Knowledge4Zotero.mainKnowledgeID") @@ -88,11 +88,6 @@ class AddonEvents extends AddonBase { itemID: message.content.editorInstance._item.id, }) ); - this.addEditorEventListener( - message.content.editorInstance, - "click", - new EditorMessage("noteEditorClick", {}) - ); if (!message.content.editorInstance._knowledgeSelectionInitialized) { this.addEditorDocumentEventListener( message.content.editorInstance, @@ -144,6 +139,7 @@ class AddonEvents extends AddonBase { "This Note is Knowledge Workspace" ); // TODO: update workspace window here + await this._Addon.knowledge.setWorkspaceMainNote(); for (let editor of Zotero.Notes._editorInstances) { await editor._initPromise; if (editor._item.id === mainKnowledgeID) { @@ -159,37 +155,20 @@ class AddonEvents extends AddonBase { } } } - } else if (message.type === "noteEditorClick") { - let el: XUL.Element = message.content.event.target; - if (el.children.length !== 0) { - // This is not a line element - return; - } - if ( - el.tagName === "A" && - (el as HTMLLinkElement).href.search(/zotero:\/\/note\//g) >= 0 - ) { - let urlIndex = (el as HTMLLinkElement).href.search( - /zotero:\/\/note\//g - ); - if (urlIndex >= 0) { - let noteID = parseInt( - (el as HTMLLinkElement).href.substring( - urlIndex + "zotero://note/".length - ) - ); - let note = Zotero.Items.get(noteID); - if (note && note.isNote()) { - // TODO: Open note - Zotero.debug(`Knowledge4Zotero: noteEditorClick ${note.id}`); - } - } - } } else if (message.type === "onNoteLink") { // TODO: Open note Zotero.debug( - `Knowledge4Zotero: onNoteLink ${message.content.params.item}` + `Knowledge4Zotero: onNoteLink ${message.content.params.item.id}` ); + let _window = this._Addon.knowledge.getWorkspaceWindow(); + if (_window) { + this._Addon.knowledge.setWorkspacePreviewNote( + message.content.params.item + ); + (_window as Window).focus(); + } else { + ZoteroPane.openNoteWindow(message.content.params.item.id); + } } else if (message.type === "noteEditorSelectionChange") { if ( message.content.editorInstance._item.id === diff --git a/src/index.ts b/src/index.ts index b614b16..35ea863 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,7 @@ import Knowledge4Zotero from "./addon"; -import { Knowledge } from "./knowledge"; Zotero.Knowledge4Zotero = new Knowledge4Zotero(); -Zotero.Knowledge = Knowledge - window.addEventListener( "load", async function (e) { diff --git a/src/knowledge.ts b/src/knowledge.ts index cf39306..69dceac 100644 --- a/src/knowledge.ts +++ b/src/knowledge.ts @@ -2,6 +2,7 @@ const TreeModel = require("./treemodel"); class Knowledge { currentLine: number; + workspaceWindow: Window; constructor() { this.currentLine = 0; } @@ -12,6 +13,72 @@ class Knowledge { ); } + getWorkspaceWindow(): Window | boolean { + if (this.workspaceWindow && !this.workspaceWindow.closed) { + return this.workspaceWindow; + } + return false; + } + + async openWorkspaceWindow() { + if (this.getWorkspaceWindow()) { + (this.getWorkspaceWindow() as Window).focus(); + } else { + let win = window.open( + "chrome://Knowledge4Zotero/content/workspace.xul", + "_blank", + "chrome,extrachrome,menubar,resizable,scrollbars,status,width=900,height=600" + ); + this.workspaceWindow = win; + await this.waitWorkspaceRedy(); + this.setWorkspaceMainNote(); + } + } + + async waitWorkspaceRedy() { + let _window = this.getWorkspaceWindow() as Window; + if (!_window) { + return false; + } + let t = 0; + while (_window.document.readyState !== "complete" && t < 500) { + t += 1; + await Zotero.Promise.delay(10); + } + return t < 500; + } + + async setWorkspaceMainNote(note: ZoteroItem = undefined) { + let _window = this.getWorkspaceWindow() as Window; + note = note || this.getWorkspaceNote(); + if (!_window) { + return; + } + await this.waitWorkspaceRedy(); + let noteEditor: any = _window.document.getElementById( + "zotero-note-editor-main" + ); + noteEditor.mode = "edit"; + noteEditor.viewMode = "library"; + noteEditor.parent = null; + noteEditor.item = note; + } + + async setWorkspacePreviewNote(note: ZoteroItem) { + let _window = this.getWorkspaceWindow() as Window; + if (!_window) { + return; + } + await this.waitWorkspaceRedy(); + let noteEditor: any = _window.document.getElementById( + "zotero-note-editor-preview" + ); + noteEditor.mode = "edit"; + noteEditor.viewMode = "library"; + noteEditor.parent = null; + noteEditor.item = note; + } + getLinesInNote(note: ZoteroItem): string[] { note = note || this.getWorkspaceNote(); if (!note) { @@ -279,55 +346,35 @@ class Knowledge { return [node.model.lineIndex, endIndex]; } - async getNoteMarkdown(note: ZoteroItem) { + async getNoteExport(note: ZoteroItem, format: "markdown" | "html") { note = note || this.getWorkspaceNote(); if (!note) { return; } let items = [note]; - let markdownFormat = { + let formatObj = { mode: "export", - id: Zotero.Translators.TRANSLATOR_ID_NOTE_MARKDOWN, + id: + format === "markdown" + ? Zotero.Translators.TRANSLATOR_ID_NOTE_MARKDOWN + : Zotero.Translators.TRANSLATOR_ID_NOTE_HTML, }; - // let htmlFormat = { - // mode: "export", - // id: Zotero.Translators.TRANSLATOR_ID_NOTE_HTML, - // }; - let mdText = ""; + let text = ""; let done = false; - Zotero.QuickCopy.getContentFromItems( - items, - markdownFormat, - (obj, worked) => { - if (!worked) { - Zotero.log(Zotero.getString("fileInterface.exportError"), "warning"); - return; - } - mdText = obj.string.replace(/\r\n/g, "\n"); - done = true; - // Zotero.QuickCopy.getContentFromItems( - // items, - // htmlFormat, - // (obj2, worked) => { - // if (!worked) { - // Zotero.log( - // Zotero.getString("fileInterface.exportError"), - // "warning" - // ); - // return; - // } - // console.log(obj.string.replace(/\r\n/g, "\n")); - // console.log("text/html", obj2.string.replace(/\r\n/g, "\n")); - // } - // ); + Zotero.QuickCopy.getContentFromItems(items, formatObj, (obj, worked) => { + if (!worked) { + Zotero.log(Zotero.getString("fileInterface.exportError"), "warning"); + return; } - ); + text = obj.string.replace(/\r\n/g, "\n"); + done = true; + }); let t = 0; while (!done && t < 500) { t += 1; await Zotero.Promise.delay(10); } - return mdText; + return text; } parseNoteHTML(note: ZoteroItem): Element { diff --git a/src/views.ts b/src/views.ts index ed728fc..b018120 100644 --- a/src/views.ts +++ b/src/views.ts @@ -63,6 +63,21 @@ class AddonViews extends AddonBase { editor.parentNode.scrollTo(0, editor.children[lineIndex].offsetTop); } + addOpenWorkspaceButton() { + let lastButton = document.getElementById("zotero-tb-advanced-search"); + let button = document.createElement("toolbarbutton"); + button.setAttribute("id", "zotero-tb-knowledge-openwindow"); + button.setAttribute("tooltiptext", "Open Knowledge Workspace"); + button.addEventListener("click", (e) => { + this._Addon.knowledge.openWorkspaceWindow(); + }); + button.setAttribute( + "style", + "list-style-image: url('chrome://Knowledge4Zotero/skin/favicon@0.5x.png');" + ); + lastButton.after(button); + } + showProgressWindow( header: string, context: string, diff --git a/src/zotero-protocol-handler.js b/src/zotero-protocol-handler.js index cf2fe2a..0cc6f31 100644 --- a/src/zotero-protocol-handler.js +++ b/src/zotero-protocol-handler.js @@ -1286,7 +1286,9 @@ function ZoteroProtocolHandler() { Zotero.debug(`${noteID} called with ${extraParams}`); let item = Zotero.Items.get(noteID); if (item && item.isNote()) { - Zotero.Knowledge4Zotero.events.onEditorEvent({ + Zotero.Knowledge4Zotero.events.onEditorEvent.bind( + Zotero.Knowledge4Zotero.events + )({ type: "onNoteLink", content: { params: {