diff options
-rw-r--r-- | ext/bg/js/backend.js | 179 | ||||
-rw-r--r-- | ext/mixed/js/api.js | 4 | ||||
-rw-r--r-- | ext/mixed/js/display.js | 21 |
3 files changed, 114 insertions, 90 deletions
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 65df0d49..f017d9e1 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -454,16 +454,15 @@ class Backend { return results; } - async _onApiInjectAnkiNoteMedia({expression, reading, timestamp, audioDetails, screenshotDetails, clipboardDetails}, sender) { + async _onApiInjectAnkiNoteMedia({timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails}, sender) { if (isObject(screenshotDetails)) { const {id: tabId, windowId} = (sender && sender.tab ? sender.tab : {}); screenshotDetails = Object.assign({}, screenshotDetails, {tabId, windowId}); } return await this._injectAnkNoteMedia( this._anki, - expression, - reading, timestamp, + definitionDetails, audioDetails, screenshotDetails, clipboardDetails @@ -1519,111 +1518,131 @@ class Backend { return await this._audioDownloader.downloadAudio(sources, expression, reading, details); } - async _injectAnkNoteMedia(ankiConnect, expression, reading, timestamp, audioDetails, screenshotDetails, clipboardDetails) { - const screenshotFileName = ( - screenshotDetails !== null ? - await this._injectAnkNoteScreenshot(ankiConnect, expression, reading, timestamp, screenshotDetails) : - null - ); - const clipboardImageFileName = ( - clipboardDetails !== null && clipboardDetails.image ? - await this._injectAnkNoteClipboardImage(ankiConnect, expression, reading, timestamp) : - null - ); + async _injectAnkNoteMedia(ankiConnect, timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails) { + let screenshotFileName = null; + let clipboardImageFileName = null; let clipboardText = null; + let audioFileName = null; + try { - if (clipboardDetails !== null && clipboardDetails.text) { - clipboardText = await this._clipboardReader.getText(); + if (screenshotDetails !== null) { + screenshotFileName = await this._injectAnkNoteScreenshot(ankiConnect, timestamp, definitionDetails, screenshotDetails); } } catch (e) { // NOP } - const audioFileName = ( - audioDetails !== null ? - await this._injectAnkNoteAudio(ankiConnect, expression, reading, timestamp, audioDetails) : - null - ); - return {screenshotFileName, clipboardImageFileName, clipboardText, audioFileName}; - } - async _injectAnkNoteAudio(ankiConnect, expression, reading, timestamp, details) { try { - if (!reading && !expression) { - throw new Error('Invalid reading and expression'); + if (clipboardDetails !== null && clipboardDetails.image) { + clipboardImageFileName = await this._injectAnkNoteClipboardImage(ankiConnect, timestamp, definitionDetails); } + } catch (e) { + // NOP + } - let fileName = 'yomichan'; - if (reading) { fileName += `_${reading}`; } - if (expression) { fileName += `_${expression}`; } - fileName += '.mp3'; - fileName = fileName.replace(/\]/g, ''); - fileName = this._replaceInvalidFileNameCharacters(fileName); - - const {sources, customSourceUrl} = details; - const data = await this._downloadDefinitionAudio( - sources, - expression, - reading, - { - textToSpeechVoice: null, - customSourceUrl, - binary: true, - disableCache: true - } - ); - - await ankiConnect.storeMediaFile(fileName, data); + try { + if (clipboardDetails !== null && clipboardDetails.text) { + clipboardText = await this._clipboardReader.getText(); + } + } catch (e) { + // NOP + } - return fileName; + try { + if (audioDetails !== null) { + audioFileName = await this._injectAnkNoteAudio(ankiConnect, timestamp, definitionDetails, audioDetails); + } } catch (e) { - return null; + // NOP } + + return {screenshotFileName, clipboardImageFileName, clipboardText, audioFileName}; } - async _injectAnkNoteScreenshot(ankiConnect, expression, reading, timestamp, details) { - try { - const now = new Date(timestamp); + async _injectAnkNoteAudio(ankiConnect, timestamp, definitionDetails, details) { + const {type, expression, reading} = definitionDetails; + if (type === 'kanji') { + throw new Error('Cannot inject audio for kanji'); + } + if (!reading && !expression) { + throw new Error('Invalid reading and expression'); + } + + const {sources, customSourceUrl} = details; + const data = await this._downloadDefinitionAudio( + sources, + expression, + reading, + { + textToSpeechVoice: null, + customSourceUrl, + binary: true, + disableCache: true + } + ); - const {windowId, tabId, ownerFrameId, format, quality} = details; - const dataUrl = await this._getScreenshot(windowId, tabId, ownerFrameId, format, quality); + let fileName = this._generateAnkiNoteMediaFileName('yomichan_audio', '.mp3', timestamp, definitionDetails); + fileName = fileName.replace(/\]/g, ''); + await ankiConnect.storeMediaFile(fileName, data); - const {mediaType, data} = this._getDataUrlInfo(dataUrl); - const extension = this._mediaUtility.getFileExtensionFromImageMediaType(mediaType); - if (extension === null) { throw new Error('Unknown image media type'); } + return fileName; + } - let fileName = `yomichan_browser_screenshot_${reading}_${this._ankNoteDateToString(now)}.${extension}`; - fileName = this._replaceInvalidFileNameCharacters(fileName); + async _injectAnkNoteScreenshot(ankiConnect, timestamp, definitionDetails, details) { + const {windowId, tabId, ownerFrameId, format, quality} = details; + const dataUrl = await this._getScreenshot(windowId, tabId, ownerFrameId, format, quality); - await ankiConnect.storeMediaFile(fileName, data); + const {mediaType, data} = this._getDataUrlInfo(dataUrl); + const extension = this._mediaUtility.getFileExtensionFromImageMediaType(mediaType); + if (extension === null) { throw new Error('Unknown image media type'); } - return fileName; - } catch (e) { - return null; - } + const fileName = this._generateAnkiNoteMediaFileName('yomichan_browser_screenshot', extension, timestamp, definitionDetails); + await ankiConnect.storeMediaFile(fileName, data); + + return fileName; } - async _injectAnkNoteClipboardImage(ankiConnect, expression, reading, timestamp) { - try { - const now = new Date(timestamp); + async _injectAnkNoteClipboardImage(ankiConnect, timestamp, definitionDetails) { + const dataUrl = await this._clipboardReader.getImage(); + if (dataUrl === null) { + throw new Error('No clipboard image'); + } - const dataUrl = await this._clipboardReader.getImage(); - if (dataUrl === null) { - throw new Error('No clipboard image'); - } + const {mediaType, data} = this._getDataUrlInfo(dataUrl); + const extension = this._mediaUtility.getFileExtensionFromImageMediaType(mediaType); + if (extension === null) { throw new Error('Unknown image media type'); } - const {mediaType, data} = this._getDataUrlInfo(dataUrl); - const extension = this._mediaUtility.getFileExtensionFromImageMediaType(mediaType); - if (extension === null) { throw new Error('Unknown image media type'); } + const fileName = this._generateAnkiNoteMediaFileName('yomichan_clipboard_image', extension, timestamp, definitionDetails); + await ankiConnect.storeMediaFile(fileName, data); - let fileName = `yomichan_clipboard_image_${reading}_${this._ankNoteDateToString(now)}.${extension}`; - fileName = this._replaceInvalidFileNameCharacters(fileName); + return fileName; + } - await ankiConnect.storeMediaFile(fileName, data); + _generateAnkiNoteMediaFileName(prefix, extension, timestamp, definitionDetails) { + let fileName = prefix; - return fileName; - } catch (e) { - return null; + switch (definitionDetails.type) { + case 'kanji': + { + const {character} = definitionDetails; + if (character) { fileName += `_${character}`; } + } + break; + default: + { + const {reading, expression} = definitionDetails; + if (reading) { fileName += `_${reading}`; } + if (expression) { fileName += `_${expression}`; } + } + break; } + + fileName += `_${this._ankNoteDateToString(new Date(timestamp))}`; + fileName += extension; + + fileName = this._replaceInvalidFileNameCharacters(fileName); + + return fileName; } _replaceInvalidFileNameCharacters(fileName) { diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index e826b68b..022d8bd7 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, clipboardDetails) { - return this._invoke('injectAnkiNoteMedia', {expression, reading, timestamp, audioDetails, screenshotDetails, clipboardDetails}); + injectAnkiNoteMedia(timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails) { + return this._invoke('injectAnkiNoteMedia', {timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails}); } noteView(noteId) { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 19634525..a9b5cf02 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -1386,7 +1386,7 @@ class Display extends EventDispatcher { const timestamp = Date.now(); const ownerFrameId = this._ownerFrameId; const {fields} = modeOptions; - const {expression, reading} = this._getDefinitionPrimaryExpressionAndReading(definition); + const definitionDetails = this._getDefinitionDetailsForNote(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 clipboardDetails = { @@ -1394,9 +1394,8 @@ class Display extends EventDispatcher { text: this._ankiNoteBuilder.containsMarker(fields, 'clipboard-text') }; const {screenshotFileName, clipboardImageFileName, clipboardText, audioFileName} = await api.injectAnkiNoteMedia( - expression, - reading, timestamp, + definitionDetails, audioDetails, screenshotDetails, clipboardDetails @@ -1420,11 +1419,13 @@ class Display extends EventDispatcher { }); } - async _getAudioInfo(source, expression, reading, details) { - return await api.getDefinitionAudioInfo(source, expression, reading, details); - } + _getDefinitionDetailsForNote(definition) { + const {type} = definition; + if (type === 'kanji') { + const {character} = definition; + return {type, character}; + } - _getDefinitionPrimaryExpressionAndReading(definition) { const termDetailsList = definition.expressions; let bestIndex = -1; for (let i = 0, ii = termDetailsList.length; i < ii; ++i) { @@ -1437,6 +1438,10 @@ class Display extends EventDispatcher { } } const {expression, reading} = termDetailsList[Math.max(0, bestIndex)]; - return {expression, reading}; + return {type, expression, reading}; + } + + async _getAudioInfo(source, expression, reading, details) { + return await api.getDefinitionAudioInfo(source, expression, reading, details); } } |