From 177da5937e5f76b578988e3cc92be01213f79b31 Mon Sep 17 00:00:00 2001 From: Abe Jellinek Date: Thu, 10 Nov 2022 17:50:40 -0500 Subject: [PATCH] Add "Add to Dictionary" to note editor context menu (#2897) As well as "Undo Add to Dictionary", as in Firefox. --- chrome/content/zotero/elements/noteEditor.js | 2 ++ chrome/content/zotero/note.xhtml | 1 + chrome/content/zotero/xpcom/editorInstance.js | 35 ++++++++++++++++--- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/chrome/content/zotero/elements/noteEditor.js b/chrome/content/zotero/elements/noteEditor.js index f23497a27c..27176ea185 100644 --- a/chrome/content/zotero/elements/noteEditor.js +++ b/chrome/content/zotero/elements/noteEditor.js @@ -60,6 +60,8 @@ window.addEventListener("unload", this.destroy); var shadow = this.attachShadow({ mode: "open" }); + MozXULElement.insertFTLIfNeeded('mozilla/textActions.ftl'); + document.l10n.connectRoot(shadow); // var s1 = document.createElement("link"); // s1.rel = "stylesheet"; diff --git a/chrome/content/zotero/note.xhtml b/chrome/content/zotero/note.xhtml index 430bc719d0..999c1ae68c 100644 --- a/chrome/content/zotero/note.xhtml +++ b/chrome/content/zotero/note.xhtml @@ -23,6 +23,7 @@ Services.scriptloader.loadSubScript("chrome://zotero/content/include.js", this); Services.scriptloader.loadSubScript("resource://zotero/require.js", this); + Services.scriptloader.loadSubScript("chrome://global/content/customElements.js", this); Services.scriptloader.loadSubScript("chrome://zotero/content/elements/shadowAutocompleteInput.js", this); Services.scriptloader.loadSubScript("chrome://zotero/content/elements/noteEditor.js", this); Services.scriptloader.loadSubScript("chrome://zotero/content/elements/relatedBox.js", this); diff --git a/chrome/content/zotero/xpcom/editorInstance.js b/chrome/content/zotero/xpcom/editorInstance.js index 497ae2c6d4..b2d0b527e9 100644 --- a/chrome/content/zotero/xpcom/editorInstance.js +++ b/chrome/content/zotero/xpcom/editorInstance.js @@ -78,6 +78,7 @@ class EditorInstance { Zotero.Prefs.registerObserver('note.css', this._handleStyleChange), Zotero.Prefs.registerObserver('layout.spellcheckDefault', this._handleSpellCheckChange, true) ]; + this._spellChecker = null; // Run Cut/Copy/Paste with chrome privileges this._iframeWindow.wrappedJSObject.zoteroExecCommand = function (doc, command, ui, value) { @@ -872,8 +873,31 @@ class EditorInstance { } let firstElementChild = this._popup.firstElementChild; + let showSeparator = false; let suggestionCount = spellChecker.addSuggestionsToMenuOnParent(this._popup, firstElementChild, 5); if (suggestionCount) { + showSeparator = true; + } + if (spellChecker.overMisspelling) { + let addToDictionary = this._popup.ownerDocument.createXULElement('menuitem'); + addToDictionary.setAttribute('data-l10n-id', 'text-action-spell-add-to-dictionary'); + addToDictionary.addEventListener('command', () => { + spellChecker.addToDictionary(); + }); + this._popup.insertBefore(addToDictionary, firstElementChild); + showSeparator = true; + } + if (spellChecker.canUndo()) { + let undo = this._popup.ownerDocument.createXULElement('menuitem'); + undo.setAttribute('data-l10n-id', 'text-action-spell-undo-add-to-dictionary'); + undo.addEventListener('command', () => { + spellChecker.undoAddToDictionary(); + }); + this._popup.insertBefore(undo, firstElementChild); + showSeparator = true; + } + + if (showSeparator) { let separator = this._popup.ownerDocument.createXULElement('menuseparator'); this._popup.insertBefore(separator, firstElementChild); } @@ -883,10 +907,13 @@ class EditorInstance { } _getSpellChecker() { - let editingSession = this._iframeWindow.docShell.editingSession; - return new InlineSpellChecker( - editingSession.getEditorForWindow(this._iframeWindow) - ); + if (!this._spellChecker) { + let editingSession = this._iframeWindow.docShell.editingSession; + this._spellChecker = new InlineSpellChecker( + editingSession.getEditorForWindow(this._iframeWindow) + ); + } + return this._spellChecker; } async _ensureNoteCreated() {