diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-04-07 19:27:44 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-07 19:27:44 -0400 | 
| commit | 623469272ed88680d767445b0290de0de6c75a6f (patch) | |
| tree | bd222fb37ad2afe42e4558704e7aa05d87c37e64 | |
| parent | fa68a8773605ee0943e1c5e9766fa6bcfb6c6a42 (diff) | |
| parent | a6773e0240f9cf25913d20ac75352b42d5c4e517 (diff) | |
Merge pull request #427 from toasted-nutbread/anki-card-media-injection
Anki card media injection refactor
| -rw-r--r-- | ext/bg/js/anki-note-builder.js | 67 | ||||
| -rw-r--r-- | ext/bg/js/backend.js | 89 | 
2 files changed, 75 insertions, 81 deletions
| diff --git a/ext/bg/js/anki-note-builder.js b/ext/bg/js/anki-note-builder.js index 51022da3..244aaab8 100644 --- a/ext/bg/js/anki-note-builder.js +++ b/ext/bg/js/anki-note-builder.js @@ -17,7 +17,8 @@   */  class AnkiNoteBuilder { -    constructor({renderTemplate}) { +    constructor({audioSystem, renderTemplate}) { +        this._audioSystem = audioSystem;          this._renderTemplate = renderTemplate;      } @@ -84,6 +85,70 @@ class AnkiNoteBuilder {          });      } +    async injectAudio(definition, fields, sources, optionsContext) { +        if (!this._containsMarker(fields, 'audio')) { return; } + +        try { +            const expressions = definition.expressions; +            const audioSourceDefinition = Array.isArray(expressions) ? expressions[0] : definition; + +            const {uri} = await this._audioSystem.getDefinitionAudio(audioSourceDefinition, sources, {tts: false, optionsContext}); +            const filename = this._createInjectedAudioFileName(audioSourceDefinition); +            if (filename !== null) { +                definition.audio = {url: uri, filename}; +            } +        } catch (e) { +            // NOP +        } +    } + +    async injectScreenshot(definition, fields, screenshot, anki) { +        if (!this._containsMarker(fields, 'screenshot')) { return; } + +        const now = new Date(Date.now()); +        const filename = `yomichan_browser_screenshot_${definition.reading}_${this._dateToString(now)}.${screenshot.format}`; +        const data = screenshot.dataUrl.replace(/^data:[\w\W]*?,/, ''); + +        try { +            await anki.storeMediaFile(filename, data); +        } catch (e) { +            return; +        } + +        definition.screenshotFileName = filename; +    } + +    _createInjectedAudioFileName(definition) { +        const {reading, expression} = definition; +        if (!reading && !expression) { return null; } + +        let filename = 'yomichan'; +        if (reading) { filename += `_${reading}`; } +        if (expression) { filename += `_${expression}`; } +        filename += '.mp3'; +        return filename; +    } + +    _dateToString(date) { +        const year = date.getUTCFullYear(); +        const month = date.getUTCMonth().toString().padStart(2, '0'); +        const day = date.getUTCDate().toString().padStart(2, '0'); +        const hours = date.getUTCHours().toString().padStart(2, '0'); +        const minutes = date.getUTCMinutes().toString().padStart(2, '0'); +        const seconds = date.getUTCSeconds().toString().padStart(2, '0'); +        return `${year}-${month}-${day}-${hours}-${minutes}-${seconds}`; +    } + +    _containsMarker(fields, marker) { +        marker = `{${marker}}`; +        for (const fieldValue of Object.values(fields)) { +            if (fieldValue.includes(marker)) { +                return true; +            } +        } +        return false; +    } +      static stringReplaceAsync(str, regex, replacer) {          let match;          let index = 0; diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index d4c822ca..1fa7ede1 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -51,12 +51,16 @@ class Backend {          this.anki = new AnkiNull();          this.mecab = new Mecab();          this.clipboardMonitor = new ClipboardMonitor({getClipboard: this._onApiClipboardGet.bind(this)}); -        this.ankiNoteBuilder = new AnkiNoteBuilder({renderTemplate: this._renderTemplate.bind(this)});          this.options = null;          this.optionsSchema = null;          this.defaultAnkiFieldTemplates = null;          this.audioSystem = new AudioSystem({getAudioUri: this._getAudioUri.bind(this)});          this.audioUriBuilder = new AudioUriBuilder(); +        this.ankiNoteBuilder = new AnkiNoteBuilder({ +            audioSystem: this.audioSystem, +            renderTemplate: this._renderTemplate.bind(this) +        }); +          this.optionsContext = {              depth: 0,              url: window.location.href @@ -460,7 +464,7 @@ class Backend {          const templates = this.defaultAnkiFieldTemplates;          if (mode !== 'kanji') { -            await this._audioInject( +            await this.ankiNoteBuilder.injectAudio(                  definition,                  options.anki.terms.fields,                  options.audio.sources, @@ -469,10 +473,11 @@ class Backend {          }          if (details && details.screenshot) { -            await this._injectScreenshot( +            await this.ankiNoteBuilder.injectScreenshot(                  definition,                  options.anki.terms.fields, -                details.screenshot +                details.screenshot, +                this.anki              );          } @@ -800,86 +805,10 @@ class Backend {          return await this.audioUriBuilder.getUri(definition, source, options);      } -    async _audioInject(definition, fields, sources, optionsContext) { -        let usesAudio = false; -        for (const fieldValue of Object.values(fields)) { -            if (fieldValue.includes('{audio}')) { -                usesAudio = true; -                break; -            } -        } - -        if (!usesAudio) { -            return true; -        } - -        try { -            const expressions = definition.expressions; -            const audioSourceDefinition = Array.isArray(expressions) ? expressions[0] : definition; - -            const {uri} = await this.audioSystem.getDefinitionAudio(audioSourceDefinition, sources, {tts: false, optionsContext}); -            const filename = this._createInjectedAudioFileName(audioSourceDefinition); -            if (filename !== null) { -                definition.audio = {url: uri, filename}; -            } - -            return true; -        } catch (e) { -            return false; -        } -    } - -    async _injectScreenshot(definition, fields, screenshot) { -        let usesScreenshot = false; -        for (const fieldValue of Object.values(fields)) { -            if (fieldValue.includes('{screenshot}')) { -                usesScreenshot = true; -                break; -            } -        } - -        if (!usesScreenshot) { -            return; -        } - -        const dateToString = (date) => { -            const year = date.getUTCFullYear(); -            const month = date.getUTCMonth().toString().padStart(2, '0'); -            const day = date.getUTCDate().toString().padStart(2, '0'); -            const hours = date.getUTCHours().toString().padStart(2, '0'); -            const minutes = date.getUTCMinutes().toString().padStart(2, '0'); -            const seconds = date.getUTCSeconds().toString().padStart(2, '0'); -            return `${year}-${month}-${day}-${hours}-${minutes}-${seconds}`; -        }; - -        const now = new Date(Date.now()); -        const filename = `yomichan_browser_screenshot_${definition.reading}_${dateToString(now)}.${screenshot.format}`; -        const data = screenshot.dataUrl.replace(/^data:[\w\W]*?,/, ''); - -        try { -            await this.anki.storeMediaFile(filename, data); -        } catch (e) { -            return; -        } - -        definition.screenshotFileName = filename; -    } -      async _renderTemplate(template, data) {          return handlebarsRenderDynamic(template, data);      } -    _createInjectedAudioFileName(definition) { -        const {reading, expression} = definition; -        if (!reading && !expression) { return null; } - -        let filename = 'yomichan'; -        if (reading) { filename += `_${reading}`; } -        if (expression) { filename += `_${expression}`; } -        filename += '.mp3'; -        return filename; -    } -      static _getTabUrl(tab) {          return new Promise((resolve) => {              chrome.tabs.sendMessage(tab.id, {action: 'getUrl'}, {frameId: 0}, (response) => { |