From ade1b705d2370be9222ba4164f79bbdfae590bc1 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 12 Apr 2020 12:20:02 -0400 Subject: [PATCH 1/9] Mark internals as private --- ext/bg/js/anki.js | 76 ++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js index c7f7c0cc..021cb4c4 100644 --- a/ext/bg/js/anki.js +++ b/ext/bg/js/anki.js @@ -25,82 +25,84 @@ class AnkiConnect { constructor(server) { - this.server = server; - this.localVersion = 2; - this.remoteVersion = 0; + this._server = server; + this._localVersion = 2; + this._remoteVersion = 0; } async addNote(note) { - await this.checkVersion(); - return await this.ankiInvoke('addNote', {note}); + await this._checkVersion(); + return await this._ankiInvoke('addNote', {note}); } async canAddNotes(notes) { - await this.checkVersion(); - return await this.ankiInvoke('canAddNotes', {notes}); + await this._checkVersion(); + return await this._ankiInvoke('canAddNotes', {notes}); } async getDeckNames() { - await this.checkVersion(); - return await this.ankiInvoke('deckNames'); + await this._checkVersion(); + return await this._ankiInvoke('deckNames'); } async getModelNames() { - await this.checkVersion(); - return await this.ankiInvoke('modelNames'); + await this._checkVersion(); + return await this._ankiInvoke('modelNames'); } async getModelFieldNames(modelName) { - await this.checkVersion(); - return await this.ankiInvoke('modelFieldNames', {modelName}); + await this._checkVersion(); + return await this._ankiInvoke('modelFieldNames', {modelName}); } async guiBrowse(query) { - await this.checkVersion(); - return await this.ankiInvoke('guiBrowse', {query}); + await this._checkVersion(); + return await this._ankiInvoke('guiBrowse', {query}); } async storeMediaFile(filename, dataBase64) { - await this.checkVersion(); - return await this.ankiInvoke('storeMediaFile', {filename, data: dataBase64}); + await this._checkVersion(); + return await this._ankiInvoke('storeMediaFile', {filename, data: dataBase64}); } - async checkVersion() { - if (this.remoteVersion < this.localVersion) { - this.remoteVersion = await this.ankiInvoke('version'); - if (this.remoteVersion < this.localVersion) { + async findNoteIds(notes) { + await this._checkVersion(); + const actions = notes.map((note) => ({ + action: 'findNotes', + params: { + query: `deck:"${this._escapeQuery(note.deckName)}" ${this._fieldsToQuery(note.fields)}` + } + })); + return await this._ankiInvoke('multi', {actions}); + } + + // Private + + async _checkVersion() { + if (this._remoteVersion < this._localVersion) { + this._remoteVersion = await this._ankiInvoke('version'); + if (this._remoteVersion < this._localVersion) { throw new Error('Extension and plugin versions incompatible'); } } } - async findNoteIds(notes) { - await this.checkVersion(); - const actions = notes.map((note) => ({ - action: 'findNotes', - params: { - query: `deck:"${AnkiConnect.escapeQuery(note.deckName)}" ${AnkiConnect.fieldsToQuery(note.fields)}` - } - })); - return await this.ankiInvoke('multi', {actions}); + _ankiInvoke(action, params) { + return requestJson(this._server, 'POST', {action, params, version: this._localVersion}); } - ankiInvoke(action, params) { - return requestJson(this.server, 'POST', {action, params, version: this.localVersion}); - } - - static escapeQuery(text) { + _escapeQuery(text) { return text.replace(/"/g, ''); } - static fieldsToQuery(fields) { + _fieldsToQuery(fields) { const fieldNames = Object.keys(fields); if (fieldNames.length === 0) { return ''; } const key = fieldNames[0]; - return `${key.toLowerCase()}:"${AnkiConnect.escapeQuery(fields[key])}"`; + return `${key.toLowerCase()}:"${this._escapeQuery(fields[key])}"`; } } From c41c7252aeb5f10fca7403a19740d869743a38a5 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 12 Apr 2020 12:37:13 -0400 Subject: [PATCH 2/9] Add enabled checks --- ext/bg/js/anki.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js index 021cb4c4..f7a24291 100644 --- a/ext/bg/js/anki.js +++ b/ext/bg/js/anki.js @@ -25,47 +25,74 @@ class AnkiConnect { constructor(server) { + this._enabled = true; this._server = server; this._localVersion = 2; this._remoteVersion = 0; } + setServer(server) { + this._server = server; + } + + getServer() { + return this._server; + } + + setEnabled(enabled) { + this._enabled = enabled; + } + + isEnabled() { + return this._enabled; + } + async addNote(note) { + if (!this._enabled) { return null; } await this._checkVersion(); return await this._ankiInvoke('addNote', {note}); } async canAddNotes(notes) { + if (!this._enabled) { return []; } await this._checkVersion(); return await this._ankiInvoke('canAddNotes', {notes}); } async getDeckNames() { + if (!this._enabled) { return []; } await this._checkVersion(); return await this._ankiInvoke('deckNames'); } async getModelNames() { + if (!this._enabled) { return []; } await this._checkVersion(); return await this._ankiInvoke('modelNames'); } async getModelFieldNames(modelName) { + if (!this._enabled) { return []; } await this._checkVersion(); return await this._ankiInvoke('modelFieldNames', {modelName}); } async guiBrowse(query) { + if (!this._enabled) { return []; } await this._checkVersion(); return await this._ankiInvoke('guiBrowse', {query}); } async storeMediaFile(filename, dataBase64) { + if (!this._enabled) { + return {result: null, error: 'AnkiConnect not enabled'}; + } await this._checkVersion(); return await this._ankiInvoke('storeMediaFile', {filename, data: dataBase64}); } async findNoteIds(notes) { + if (!this._enabled) { return []; } await this._checkVersion(); const actions = notes.map((note) => ({ action: 'findNotes', From 4c2ca82a2937fa4e1d0f3f6744f4e1a7b88692a1 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 12 Apr 2020 12:38:33 -0400 Subject: [PATCH 3/9] Use single instance of AnkiConnect --- ext/bg/js/anki.js | 2 +- ext/bg/js/backend.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js index f7a24291..dd802424 100644 --- a/ext/bg/js/anki.js +++ b/ext/bg/js/anki.js @@ -25,7 +25,7 @@ class AnkiConnect { constructor(server) { - this._enabled = true; + this._enabled = false; this._server = server; this._localVersion = 2; this._remoteVersion = 0; diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index be8ea322..24a16199 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -47,7 +47,7 @@ class Backend { this.database = new Database(); this.dictionaryImporter = new DictionaryImporter(); this.translator = new Translator(this.database); - this.anki = new AnkiNull(); + this.anki = new AnkiConnect(); this.mecab = new Mecab(); this.clipboardMonitor = new ClipboardMonitor({getClipboard: this._onApiClipboardGet.bind(this)}); this.options = null; @@ -210,7 +210,8 @@ class Backend { this.setExtensionBadgeText(''); } - this.anki = options.anki.enable ? new AnkiConnect(options.anki.server) : new AnkiNull(); + this.anki.setServer(options.anki.server); + this.anki.setEnabled(options.anki.enable); if (options.parsing.enableMecabParser) { this.mecab.startListener(); From cc5e4294223f9d0106ddec1d561b29ac449b1115 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 12 Apr 2020 12:38:52 -0400 Subject: [PATCH 4/9] Remove AnkiNull and redundant comment --- ext/bg/js/anki.js | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js index dd802424..27590311 100644 --- a/ext/bg/js/anki.js +++ b/ext/bg/js/anki.js @@ -19,10 +19,6 @@ * requestJson */ -/* - * AnkiConnect - */ - class AnkiConnect { constructor(server) { this._enabled = false; @@ -132,38 +128,3 @@ class AnkiConnect { return `${key.toLowerCase()}:"${this._escapeQuery(fields[key])}"`; } } - - -/* - * AnkiNull - */ - -class AnkiNull { - async addNote() { - return null; - } - - async canAddNotes() { - return []; - } - - async getDeckNames() { - return []; - } - - async getModelNames() { - return []; - } - - async getModelFieldNames() { - return []; - } - - async guiBrowse() { - return []; - } - - async findNoteIds() { - return []; - } -} From 3c335e68cdd41860d791ffe85dd07abf8932d3ce Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 12 Apr 2020 12:43:24 -0400 Subject: [PATCH 5/9] Throw errors in returned by invocation --- ext/bg/js/anki.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js index 27590311..c07af462 100644 --- a/ext/bg/js/anki.js +++ b/ext/bg/js/anki.js @@ -81,7 +81,7 @@ class AnkiConnect { async storeMediaFile(filename, dataBase64) { if (!this._enabled) { - return {result: null, error: 'AnkiConnect not enabled'}; + throw new Error('AnkiConnect not enabled'); } await this._checkVersion(); return await this._ankiInvoke('storeMediaFile', {filename, data: dataBase64}); @@ -110,8 +110,19 @@ class AnkiConnect { } } - _ankiInvoke(action, params) { - return requestJson(this._server, 'POST', {action, params, version: this._localVersion}); + async _ankiInvoke(action, params) { + const result = await requestJson(this._server, 'POST', {action, params, version: this._localVersion}); + if ( + result !== null && + typeof result === 'object' && + !Array.isArray(result) + ) { + const error = result.error; + if (typeof error !== 'undefined') { + throw new Error(`AnkiConnect error: ${error}`); + } + } + return result; } _escapeQuery(text) { From 37c374fb633a5b2f224348a8e5490f0275d348e7 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 12 Apr 2020 12:44:33 -0400 Subject: [PATCH 6/9] Rename _ankiInvoke to _invoke to remove redundancy --- ext/bg/js/anki.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js index c07af462..928b5159 100644 --- a/ext/bg/js/anki.js +++ b/ext/bg/js/anki.js @@ -46,37 +46,37 @@ class AnkiConnect { async addNote(note) { if (!this._enabled) { return null; } await this._checkVersion(); - return await this._ankiInvoke('addNote', {note}); + return await this._invoke('addNote', {note}); } async canAddNotes(notes) { if (!this._enabled) { return []; } await this._checkVersion(); - return await this._ankiInvoke('canAddNotes', {notes}); + return await this._invoke('canAddNotes', {notes}); } async getDeckNames() { if (!this._enabled) { return []; } await this._checkVersion(); - return await this._ankiInvoke('deckNames'); + return await this._invoke('deckNames'); } async getModelNames() { if (!this._enabled) { return []; } await this._checkVersion(); - return await this._ankiInvoke('modelNames'); + return await this._invoke('modelNames'); } async getModelFieldNames(modelName) { if (!this._enabled) { return []; } await this._checkVersion(); - return await this._ankiInvoke('modelFieldNames', {modelName}); + return await this._invoke('modelFieldNames', {modelName}); } async guiBrowse(query) { if (!this._enabled) { return []; } await this._checkVersion(); - return await this._ankiInvoke('guiBrowse', {query}); + return await this._invoke('guiBrowse', {query}); } async storeMediaFile(filename, dataBase64) { @@ -84,7 +84,7 @@ class AnkiConnect { throw new Error('AnkiConnect not enabled'); } await this._checkVersion(); - return await this._ankiInvoke('storeMediaFile', {filename, data: dataBase64}); + return await this._invoke('storeMediaFile', {filename, data: dataBase64}); } async findNoteIds(notes) { @@ -96,21 +96,21 @@ class AnkiConnect { query: `deck:"${this._escapeQuery(note.deckName)}" ${this._fieldsToQuery(note.fields)}` } })); - return await this._ankiInvoke('multi', {actions}); + return await this._invoke('multi', {actions}); } // Private async _checkVersion() { if (this._remoteVersion < this._localVersion) { - this._remoteVersion = await this._ankiInvoke('version'); + this._remoteVersion = await this._invoke('version'); if (this._remoteVersion < this._localVersion) { throw new Error('Extension and plugin versions incompatible'); } } } - async _ankiInvoke(action, params) { + async _invoke(action, params) { const result = await requestJson(this._server, 'POST', {action, params, version: this._localVersion}); if ( result !== null && From ebfc7ca945109c6700b3dbf6d45542ddbba94f3d Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 12 Apr 2020 12:46:32 -0400 Subject: [PATCH 7/9] Pass anki reference to AnkiNoteBuilder constructor --- ext/bg/js/anki-note-builder.js | 7 ++++--- ext/bg/js/backend.js | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ext/bg/js/anki-note-builder.js b/ext/bg/js/anki-note-builder.js index 8a707006..700d8237 100644 --- a/ext/bg/js/anki-note-builder.js +++ b/ext/bg/js/anki-note-builder.js @@ -16,7 +16,8 @@ */ class AnkiNoteBuilder { - constructor({audioSystem, renderTemplate}) { + constructor({anki, audioSystem, renderTemplate}) { + this._anki = anki; this._audioSystem = audioSystem; this._renderTemplate = renderTemplate; } @@ -101,7 +102,7 @@ class AnkiNoteBuilder { } } - async injectScreenshot(definition, fields, screenshot, anki) { + async injectScreenshot(definition, fields, screenshot) { if (!this._containsMarker(fields, 'screenshot')) { return; } const now = new Date(Date.now()); @@ -109,7 +110,7 @@ class AnkiNoteBuilder { const data = screenshot.dataUrl.replace(/^data:[\w\W]*?,/, ''); try { - await anki.storeMediaFile(filename, data); + await this._anki.storeMediaFile(filename, data); } catch (e) { return; } diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 24a16199..6a6819e9 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -56,6 +56,7 @@ class Backend { this.audioSystem = new AudioSystem({getAudioUri: this._getAudioUri.bind(this)}); this.audioUriBuilder = new AudioUriBuilder(); this.ankiNoteBuilder = new AnkiNoteBuilder({ + anki: this.anki, audioSystem: this.audioSystem, renderTemplate: this._renderTemplate.bind(this) }); @@ -482,8 +483,7 @@ class Backend { await this.ankiNoteBuilder.injectScreenshot( definition, options.anki.terms.fields, - details.screenshot, - this.anki + details.screenshot ); } From 018913d03fff627fb7d34f594340c47a607e8839 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Fri, 17 Apr 2020 19:25:07 -0400 Subject: [PATCH 8/9] Use isObject --- ext/bg/js/anki.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js index 928b5159..38823431 100644 --- a/ext/bg/js/anki.js +++ b/ext/bg/js/anki.js @@ -112,11 +112,7 @@ class AnkiConnect { async _invoke(action, params) { const result = await requestJson(this._server, 'POST', {action, params, version: this._localVersion}); - if ( - result !== null && - typeof result === 'object' && - !Array.isArray(result) - ) { + if (isObject(result)) { const error = result.error; if (typeof error !== 'undefined') { throw new Error(`AnkiConnect error: ${error}`); From 06e95b8747e7222d3aa513cda28b0878a11921d9 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Fri, 17 Apr 2020 22:16:08 -0400 Subject: [PATCH 9/9] Remove unused global --- ext/bg/js/backend.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 6a6819e9..1b922730 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -18,7 +18,6 @@ /* global * AnkiConnect * AnkiNoteBuilder - * AnkiNull * AudioSystem * AudioUriBuilder * BackendApiForwarder