From cab5daa22e986fdf0c71a370ebd459efa0a13a61 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 26 Sep 2020 13:45:48 -0400 Subject: [PATCH] Add clipboard-text Anki field (#863) * Add clipboard-text anki field * Add markers * Update clipboard injection --- README.md | 2 ++ .../anki-field-templates-upgrade-v4.handlebars | 4 ++++ .../default-anki-field-templates.handlebars | 4 ++++ ext/bg/js/anki-note-builder.js | 4 ++-- ext/bg/js/backend.js | 18 +++++++++++++----- ext/bg/js/options.js | 1 + ext/bg/js/settings/anki-controller.js | 2 ++ ext/mixed/js/api.js | 4 ++-- ext/mixed/js/display.js | 10 +++++++--- 9 files changed, 37 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d8d45292..8be40026 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,7 @@ Flashcard fields can be configured with the following steps: -------|------------ `{audio}` | Audio sample of a native speaker's pronunciation in MP3 format (if available). `{clipboard-image}` | An image which is stored in the system clipboard, if present. + `{clipboard-text}` | Text which is stored in the system clipboard, if present. `{cloze-body}` | Raw, inflected term as it appeared before being reduced to dictionary form by Yomichan. `{cloze-prefix}` | Fragment of the containing `{sentence}` starting at the beginning of `{sentence}` until the beginning of `{cloze-body}`. `{cloze-suffix}` | Fragment of the containing `{sentence}` starting at the end of `{cloze-body}` until the end of `{sentence}`. @@ -180,6 +181,7 @@ Flashcard fields can be configured with the following steps: -------|------------ `{character}` | Unicode glyph representing the current kanji. `{clipboard-image}` | An image which is stored in the system clipboard, if present. + `{clipboard-text}` | Text which is stored in the system clipboard, if present. `{cloze-body}` | Raw, inflected parent term as it appeared before being reduced to dictionary form by Yomichan. `{cloze-prefix}` | Fragment of the containing `{sentence}` starting at the beginning of `{sentence}` until the beginning of `{cloze-body}`. `{cloze-suffix}` | Fragment of the containing `{sentence}` starting at the end of `{cloze-body}` until the end of `{sentence}`. diff --git a/ext/bg/data/anki-field-templates-upgrade-v4.handlebars b/ext/bg/data/anki-field-templates-upgrade-v4.handlebars index a16b5b68..dc88395a 100644 --- a/ext/bg/data/anki-field-templates-upgrade-v4.handlebars +++ b/ext/bg/data/anki-field-templates-upgrade-v4.handlebars @@ -3,3 +3,7 @@ {{~/if~}} {{/inline}} + +{{#*inline "clipboard-text"}} + {{~#if definition.clipboardText~}}{{definition.clipboardText}}{{~/if~}} +{{/inline}} diff --git a/ext/bg/data/default-anki-field-templates.handlebars b/ext/bg/data/default-anki-field-templates.handlebars index 98f6897b..2849ade9 100644 --- a/ext/bg/data/default-anki-field-templates.handlebars +++ b/ext/bg/data/default-anki-field-templates.handlebars @@ -282,4 +282,8 @@ {{~/if~}} {{/inline}} +{{#*inline "clipboard-text"}} + {{~#if definition.clipboardText~}}{{definition.clipboardText}}{{~/if~}} +{{/inline}} + {{~> (lookup . "marker") ~}} diff --git a/ext/bg/js/anki-note-builder.js b/ext/bg/js/anki-note-builder.js index 141259ce..f04a6bf7 100644 --- a/ext/bg/js/anki-note-builder.js +++ b/ext/bg/js/anki-note-builder.js @@ -37,11 +37,11 @@ class AnkiNoteBuilder { modeOptions: {fields, deck, model}, audioDetails=null, screenshotDetails=null, - clipboardImage=false, + clipboardDetails=null, errors=null }) { if (anki !== null) { - await this._injectMedia(anki, definition, fields, mode, audioDetails, screenshotDetails, clipboardImage); + await this._injectMedia(anki, definition, fields, mode, audioDetails, screenshotDetails, clipboardDetails); } const fieldEntries = Object.entries(fields); diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 2a90e8e1..d071a857 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -452,7 +452,7 @@ class Backend { return results; } - async _onApiInjectAnkiNoteMedia({expression, reading, timestamp, audioDetails, screenshotDetails, clipboardImage}, sender) { + async _onApiInjectAnkiNoteMedia({expression, reading, timestamp, audioDetails, screenshotDetails, clipboardDetails}, sender) { if (isObject(screenshotDetails)) { const {id: tabId, windowId} = (sender && sender.tab ? sender.tab : {}); screenshotDetails = Object.assign({}, screenshotDetails, {tabId, windowId}); @@ -464,7 +464,7 @@ class Backend { timestamp, audioDetails, screenshotDetails, - clipboardImage + clipboardDetails ); } @@ -1512,23 +1512,31 @@ class Backend { return await this._audioDownloader.downloadAudio(sources, expression, reading, details); } - async _injectAnkNoteMedia(ankiConnect, expression, reading, timestamp, audioDetails, screenshotDetails, clipboardImage) { + async _injectAnkNoteMedia(ankiConnect, expression, reading, timestamp, audioDetails, screenshotDetails, clipboardDetails) { const screenshotFileName = ( screenshotDetails !== null ? await this._injectAnkNoteScreenshot(ankiConnect, expression, reading, timestamp, screenshotDetails) : null ); const clipboardImageFileName = ( - clipboardImage ? + clipboardDetails !== null && clipboardDetails.image ? await this._injectAnkNoteClipboardImage(ankiConnect, expression, reading, timestamp) : null ); + let clipboardText = null; + try { + if (clipboardDetails !== null && clipboardDetails.text) { + clipboardText = await this._clipboardReader.getText(); + } + } catch (e) { + // NOP + } const audioFileName = ( audioDetails !== null ? await this._injectAnkNoteAudio(ankiConnect, expression, reading, timestamp, audioDetails) : null ); - return {screenshotFileName, clipboardImageFileName, audioFileName}; + return {screenshotFileName, clipboardImageFileName, clipboardText, audioFileName}; } async _injectAnkNoteAudio(ankiConnect, expression, reading, timestamp, details) { diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 6026fa07..5b61b870 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -503,6 +503,7 @@ class OptionsUtil { // Options conditions converted to string representations. // Added usePopupWindow. // Updated handlebars templates to include "clipboard-image" definition. + // Updated handlebars templates to include "clipboard-text" definition. // Added hideDelay. // Added inputs to profileOptions.scanning. // Added pointerEventsEnabled to profileOptions.scanning. diff --git a/ext/bg/js/settings/anki-controller.js b/ext/bg/js/settings/anki-controller.js index c1ba843e..526ddfb2 100644 --- a/ext/bg/js/settings/anki-controller.js +++ b/ext/bg/js/settings/anki-controller.js @@ -46,6 +46,7 @@ class AnkiController { return [ 'audio', 'clipboard-image', + 'clipboard-text', 'cloze-body', 'cloze-prefix', 'cloze-suffix', @@ -69,6 +70,7 @@ class AnkiController { return [ 'character', 'clipboard-image', + 'clipboard-text', 'cloze-body', 'cloze-prefix', 'cloze-suffix', diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index f7711cbd..e826b68b 100644 --- a/ext/mixed/js/api.js +++ b/ext/mixed/js/api.js @@ -77,8 +77,8 @@ const api = (() => { return this._invoke('getAnkiNoteInfo', {notes, duplicateScope}); } - injectAnkiNoteMedia(expression, reading, timestamp, audioDetails, screenshotDetails, clipboardImage) { - return this._invoke('injectAnkiNoteMedia', {expression, reading, timestamp, audioDetails, screenshotDetails, clipboardImage}); + injectAnkiNoteMedia(expression, reading, timestamp, audioDetails, screenshotDetails, clipboardDetails) { + return this._invoke('injectAnkiNoteMedia', {expression, reading, timestamp, audioDetails, screenshotDetails, clipboardDetails}); } noteView(noteId) { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 689fa7e4..377a491d 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -1389,18 +1389,22 @@ class Display extends EventDispatcher { const {expression, reading} = Array.isArray(definitionExpressions) ? definitionExpressions[0] : definition; const audioDetails = (mode !== 'kanji' && this._ankiNoteBuilder.containsMarker(fields, 'audio') ? {sources, customSourceUrl} : null); const screenshotDetails = (this._ankiNoteBuilder.containsMarker(fields, 'screenshot') ? {ownerFrameId, format, quality} : null); - const clipboardImage = (this._ankiNoteBuilder.containsMarker(fields, 'clipboard-image')); - const {screenshotFileName, clipboardImageFileName, audioFileName} = await api.injectAnkiNoteMedia( + const clipboardDetails = { + image: this._ankiNoteBuilder.containsMarker(fields, 'clipboard-image'), + text: this._ankiNoteBuilder.containsMarker(fields, 'clipboard-text') + }; + const {screenshotFileName, clipboardImageFileName, clipboardText, audioFileName} = await api.injectAnkiNoteMedia( expression, reading, timestamp, audioDetails, screenshotDetails, - clipboardImage + clipboardDetails ); if (screenshotFileName !== null) { definition.screenshotFileName = screenshotFileName; } if (clipboardImageFileName !== null) { definition.clipboardImageFileName = clipboardImageFileName; } if (audioFileName !== null) { definition.audioFileName = audioFileName; } + if (clipboardText !== null) { definition.clipboardText = clipboardText; } } return await this._ankiNoteBuilder.createNote({