diff options
| -rw-r--r-- | ext/js/background/backend.js | 76 | ||||
| -rw-r--r-- | ext/js/comm/api.js | 4 | ||||
| -rw-r--r-- | ext/js/data/anki-note-builder.js | 26 | 
3 files changed, 88 insertions, 18 deletions
| diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index 8ad6c19f..7f9fe7f8 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -490,14 +490,15 @@ class Backend {          return results;      } -    async _onApiInjectAnkiNoteMedia({timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails}) { +    async _onApiInjectAnkiNoteMedia({timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails, dictionaryMediaDetails}) {          return await this._injectAnkNoteMedia(              this._anki,              timestamp,              definitionDetails,              audioDetails,              screenshotDetails, -            clipboardDetails +            clipboardDetails, +            dictionaryMediaDetails          );      } @@ -1682,7 +1683,7 @@ class Backend {          }      } -    async _injectAnkNoteMedia(ankiConnect, timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails) { +    async _injectAnkNoteMedia(ankiConnect, timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails, dictionaryMediaDetails) {          let screenshotFileName = null;          let clipboardImageFileName = null;          let clipboardText = null; @@ -1721,14 +1722,25 @@ class Backend {              errors.push(serializeError(e));          } +        let dictionaryMedia; +        try { +            let errors2; +            ({results: dictionaryMedia, errors: errors2} = await this._injectAnkiNoteDictionaryMedia(ankiConnect, timestamp, definitionDetails, dictionaryMediaDetails)); +            for (const error of errors2) { +                errors.push(serializeError(error)); +            } +        } catch (e) { +            dictionaryMedia = []; +            errors.push(serializeError(e)); +        } +          return { -            result: { -                screenshotFileName, -                clipboardImageFileName, -                clipboardText, -                audioFileName -            }, -            errors +            screenshotFileName, +            clipboardImageFileName, +            clipboardText, +            audioFileName, +            dictionaryMedia, +            errors: errors          };      } @@ -1801,6 +1813,50 @@ class Backend {          return fileName;      } +    async _injectAnkiNoteDictionaryMedia(ankiConnect, timestamp, definitionDetails, dictionaryMediaDetails) { +        const targets = []; +        const detailsList = []; +        const detailsMap = new Map(); +        for (const {dictionary, path} of dictionaryMediaDetails) { +            const target = {dictionary, path}; +            const details = {dictionary, path, media: null}; +            const key = JSON.stringify(target); +            targets.push(target); +            detailsList.push(details); +            detailsMap.set(key, details); +        } +        const mediaList = await this._dictionaryDatabase.getMedia(targets); + +        for (const media of mediaList) { +            const {dictionary, path} = media; +            const key = JSON.stringify({dictionary, path}); +            const details = detailsMap.get(key); +            if (typeof details === 'undefined' || details.media !== null) { continue; } +            details.media = media; +        } + +        const errors = []; +        const results = []; +        for (let i = 0, ii = detailsList.length; i < ii; ++i) { +            const {dictionary, path, media} = detailsList[i]; +            let fileName = null; +            if (media !== null) { +                const {content, mediaType} = media; +                const extension = MediaUtil.getFileExtensionFromImageMediaType(mediaType); +                fileName = this._generateAnkiNoteMediaFileName(`yomichan_dictionary_media_${i + 1}`, extension, timestamp, definitionDetails); +                try { +                    await ankiConnect.storeMediaFile(fileName, content); +                } catch (e) { +                    errors.push(e); +                    fileName = null; +                } +            } +            results.push({dictionary, path, fileName}); +        } + +        return {results, errors}; +    } +      _generateAnkiNoteMediaFileName(prefix, extension, timestamp, definitionDetails) {          let fileName = prefix; diff --git a/ext/js/comm/api.js b/ext/js/comm/api.js index 7e77180e..7c89f0c5 100644 --- a/ext/js/comm/api.js +++ b/ext/js/comm/api.js @@ -56,8 +56,8 @@ class API {          return this._invoke('getAnkiNoteInfo', {notes, fetchAdditionalInfo});      } -    injectAnkiNoteMedia(timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails) { -        return this._invoke('injectAnkiNoteMedia', {timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails}); +    injectAnkiNoteMedia(timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails, dictionaryMediaDetails) { +        return this._invoke('injectAnkiNoteMedia', {timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails, dictionaryMediaDetails});      }      noteView(noteId) { diff --git a/ext/js/data/anki-note-builder.js b/ext/js/data/anki-note-builder.js index c69d6741..65740254 100644 --- a/ext/js/data/anki-note-builder.js +++ b/ext/js/data/anki-note-builder.js @@ -283,7 +283,7 @@ class AnkiNoteBuilder {          let injectScreenshot = false;          let injectClipboardImage = false;          let injectClipboardText = false; -        const injectDictionaryMedia = []; +        const dictionaryMediaDetails = [];          for (const requirement of requirements) {              const {type} = requirement;              switch (type) { @@ -291,7 +291,12 @@ class AnkiNoteBuilder {                  case 'screenshot': injectScreenshot = true; break;                  case 'clipboardImage': injectClipboardImage = true; break;                  case 'clipboardText': injectClipboardText = true; break; -                case 'dictionaryMedia': injectDictionaryMedia.push(requirement); break; +                case 'dictionaryMedia': +                    { +                        const {dictionary, path} = requirement; +                        dictionaryMediaDetails.push({dictionary, path}); +                    } +                    break;              }          } @@ -318,17 +323,26 @@ class AnkiNoteBuilder {          }          // Inject media -        // TODO : injectDictionaryMedia -        const {result: {audioFileName, screenshotFileName, clipboardImageFileName, clipboardText}, errors} = await yomichan.api.injectAnkiNoteMedia( +        const {audioFileName, screenshotFileName, clipboardImageFileName, clipboardText, dictionaryMedia: dictionaryMediaArray, errors} = await yomichan.api.injectAnkiNoteMedia(              timestamp,              dictionaryEntryDetails,              audioDetails,              screenshotDetails, -            clipboardDetails +            clipboardDetails, +            dictionaryMediaDetails          );          // Format results -        const dictionaryMedia = {}; // TODO +        const dictionaryMedia = {}; +        for (const {dictionary, path, fileName} of dictionaryMediaArray) { +            if (fileName === null) { continue; } +            const dictionaryMedia2 = ( +                Object.prototype.hasOwnProperty.call(dictionaryMedia, dictionary) ? +                (dictionaryMedia[dictionary]) : +                (dictionaryMedia[dictionary] = {}) +            ); +            dictionaryMedia2[path] = {fileName}; +        }          const media = {              audio: (typeof audioFileName === 'string' ? {fileName: audioFileName} : null),              screenshot: (typeof screenshotFileName === 'string' ? {fileName: screenshotFileName} : null), |