diff --git a/ext/bg/background.html b/ext/bg/background.html index c490df81..a9840e4a 100644 --- a/ext/bg/background.html +++ b/ext/bg/background.html @@ -3,6 +3,7 @@ + diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js new file mode 100644 index 00000000..73f0d479 --- /dev/null +++ b/ext/bg/js/anki.js @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2016 Alex Yatskov + * Author: Alex Yatskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +class AnkiConnect { + constructor(apiVersion) { + this.asyncPools = {}; + this.apiVersion = apiVersion; + this.ankiConnectVer = 0; + } + + addNote(note) { + return this.ankiInvokeSafe('addNote', {note}, null); + } + + canAddNotes(notes) { + return this.ankiInvokeSafe('canAddNotes', {notes}, 'notes'); + } + + getDeckNames() { + return this.ankiInvokeSafe('deckNames', {}, null); + } + + getModelNames() { + return this.ankiInvokeSafe('modelNames', {}, null); + } + + getModelFieldNames(modelName) { + return this.ankiInvokeSafe('modelFieldNames', {modelName}, null); + } + + getVersion() { + return this.ankiInvoke('version', {}, null); + } + + ankiInvokeSafe(action, params, pool) { + if (this.ankiConnectVer === this.apiVersion) { + return this.ankiInvoke(action, params, pool); + } + + return this.getVersion().then(version => { + if (version === this.apiVersion) { + return this.ankiInvoke(action, params, pool); + } + + return null; + }); + } + + ankiInvoke(action, params, pool) { + return new Promise((resolve, reject) => { + if (pool !== null && this.asyncPools.hasOwnProperty(pool)) { + this.asyncPools[pool].abort(); + } + + const xhr = new XMLHttpRequest(); + xhr.addEventListener('loadend', () => { + if (pool !== null) { + delete this.asyncPools[pool]; + } + + const resp = xhr.responseText; + resolve(resp ? JSON.parse(resp) : null); + }); + + xhr.open('POST', 'http://127.0.0.1:8765'); + xhr.send(JSON.stringify({action, params})); + }); + } +} diff --git a/ext/bg/js/yomichan.js b/ext/bg/js/yomichan.js index 46a240a3..c641bf6b 100644 --- a/ext/bg/js/yomichan.js +++ b/ext/bg/js/yomichan.js @@ -25,8 +25,7 @@ class Yomichan { this.translator = new Translator(); this.options = null; this.importTabId = null; - this.asyncPools = {}; - this.ankiConnectVer = 0; + this.anki = new AnkiConnect(this.getApiVersion()); this.setState('disabled'); chrome.runtime.onMessage.addListener(this.onMessage.bind(this)); @@ -120,44 +119,6 @@ class Yomichan { chrome.tabs.sendMessage(tabId, {action, params}, () => null); } - ankiInvokeSafe(action, params, pool, callback) { - if (this.ankiConnectVer === this.getApiVersion()) { - this.ankiInvoke(action, params, pool, callback); - } else { - this.api_getVersion({callback: version => { - if (version === this.getApiVersion()) { - this.ankiConnectVer = version; - this.ankiInvoke(action, params, pool, callback); - } else { - callback(null); - } - }}); - } - } - - ankiInvoke(action, params, pool, callback) { - if (this.options.enableAnkiConnect) { - if (pool !== null && this.asyncPools.hasOwnProperty(pool)) { - this.asyncPools[pool].abort(); - } - - const xhr = new XMLHttpRequest(); - xhr.addEventListener('loadend', () => { - if (pool !== null) { - delete this.asyncPools[pool]; - } - - const resp = xhr.responseText; - callback(resp ? JSON.parse(resp) : null); - }); - - xhr.open('POST', 'http://127.0.0.1:8765'); - xhr.send(JSON.stringify({action, params})); - } else { - callback(null); - } - } - formatField(field, definition, mode) { const markers = [ 'audio', @@ -260,9 +221,21 @@ class Yomichan { loadOptions().then(opts => callback(opts)); } + api_findKanji({text, callback}) { + this.translator.findKanji(text).then(result => callback(result)); + } + + api_findTerm({text, callback}) { + this.translator.findTerm(text).then(result => callback(result)); + } + + api_renderText({template, data, callback}) { + callback(Handlebars.templates[template](data)); + } + api_addDefinition({definition, mode, callback}) { const note = this.formatNote(definition, mode); - this.ankiInvokeSafe('addNote', {note}, null, callback); + this.anki.addNote(note).then(callback); } api_canAddDefinitions({definitions, modes, callback}) { @@ -273,7 +246,7 @@ class Yomichan { } } - this.ankiInvokeSafe('canAddNotes', {notes}, 'notes', results => { + this.anki.canAddNotes(notes).then(results => { const states = []; if (results !== null) { @@ -291,32 +264,20 @@ class Yomichan { }); } - api_findKanji({text, callback}) { - this.translator.findKanji(text).then(result => callback(result)); - } - - api_findTerm({text, callback}) { - this.translator.findTerm(text).then(result => callback(result)); - } - api_getDeckNames({callback}) { - this.ankiInvokeSafe('deckNames', {}, null, callback); + this.anki.getDeckNames().then(callback); } api_getModelNames({callback}) { - this.ankiInvokeSafe('modelNames', {}, null, callback); + this.anki.getModelFieldNames().then(callback); } api_getModelFieldNames({modelName, callback}) { - this.ankiInvokeSafe('modelFieldNames', {modelName}, null, callback); + this.anki.getModelFieldNames(modelName).then(callback); } api_getVersion({callback}) { - this.ankiInvoke('version', {}, null, callback); - } - - api_renderText({template, data, callback}) { - callback(Handlebars.templates[template](data)); + this.anki.getVersion().then(callback); } }