aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2020-04-07 19:27:44 -0400
committerGitHub <noreply@github.com>2020-04-07 19:27:44 -0400
commit623469272ed88680d767445b0290de0de6c75a6f (patch)
treebd222fb37ad2afe42e4558704e7aa05d87c37e64
parentfa68a8773605ee0943e1c5e9766fa6bcfb6c6a42 (diff)
parenta6773e0240f9cf25913d20ac75352b42d5c4e517 (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.js67
-rw-r--r--ext/bg/js/backend.js89
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) => {