summaryrefslogtreecommitdiff
path: root/ext/bg/js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/bg/js')
-rw-r--r--ext/bg/js/ankiconnect.js82
-rw-r--r--ext/bg/js/ankinull.js39
-rw-r--r--ext/bg/js/ankiweb.js148
-rw-r--r--ext/bg/js/options-form.js189
-rw-r--r--ext/bg/js/options.js5
-rw-r--r--ext/bg/js/util.js2
-rw-r--r--ext/bg/js/yomichan.js109
7 files changed, 414 insertions, 160 deletions
diff --git a/ext/bg/js/ankiconnect.js b/ext/bg/js/ankiconnect.js
new file mode 100644
index 00000000..d17f3268
--- /dev/null
+++ b/ext/bg/js/ankiconnect.js
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 Alex Yatskov <alex@foosoft.net>
+ * Author: Alex Yatskov <alex@foosoft.net>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+class AnkiConnect {
+ constructor() {
+ this.asyncPools = {};
+ this.localVersion = 1;
+ this.remoteVersion = null;
+ }
+
+ addNote(note) {
+ return this.checkVersion().then(() => this.ankiInvoke('addNote', {note}, null));
+ }
+
+ canAddNotes(notes) {
+ return this.checkVersion().then(() => this.ankiInvoke('canAddNotes', {notes}, 'notes'));
+ }
+
+ getDeckNames() {
+ return this.checkVersion().then(() => this.ankiInvoke('deckNames', {}, null));
+ }
+
+ getModelNames() {
+ return this.checkVersion().then(() => this.ankiInvoke('modelNames', {}, null));
+ }
+
+ getModelFieldNames(modelName) {
+ return this.checkVersion().then(() => this.ankiInvoke('modelFieldNames', {modelName}, null));
+ }
+
+ checkVersion() {
+ if (this.localVersion === this.remoteVersion) {
+ return Promise.resolve(true);
+ }
+
+ return this.ankiInvoke('version', {}, null).then(version => {
+ this.remoteVersion = version;
+ if (this.remoteVersion !== this.localVersion) {
+ return Promise.reject('extension and plugin version mismatch');
+ }
+ });
+ }
+
+ 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];
+ }
+
+ if (xhr.responseText) {
+ resolve(JSON.parse(xhr.responseText));
+ } else {
+ reject('unable to connect to plugin');
+ }
+ });
+
+ xhr.open('POST', 'http://127.0.0.1:8765');
+ xhr.send(JSON.stringify({action, params}));
+ });
+ }
+}
diff --git a/ext/bg/js/ankinull.js b/ext/bg/js/ankinull.js
new file mode 100644
index 00000000..0d0ed903
--- /dev/null
+++ b/ext/bg/js/ankinull.js
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 Alex Yatskov <alex@foosoft.net>
+ * Author: Alex Yatskov <alex@foosoft.net>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+class AnkiNull {
+ addNote(note) {
+ return Promise.reject('unsupported action');
+ }
+
+ canAddNotes(notes) {
+ return Promise.resolve([]);
+ }
+
+ getDeckNames() {
+ return Promise.resolve([]);
+ }
+
+ getModelNames() {
+ return Promise.resolve([]);
+ }
+
+ getModelFieldNames(modelName) {
+ return Promise.resolve([]);
+ }
+}
diff --git a/ext/bg/js/ankiweb.js b/ext/bg/js/ankiweb.js
new file mode 100644
index 00000000..1393f668
--- /dev/null
+++ b/ext/bg/js/ankiweb.js
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 Alex Yatskov <alex@foosoft.net>
+ * Author: Alex Yatskov <alex@foosoft.net>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+class AnkiWeb {
+ constructor(username, password) {
+ this.username = username;
+ this.password = password;
+ this.noteInfo = null;
+ }
+
+ addNote(note) {
+ return this.retrieve().then(info => {
+ const model = info.models.find(m => m.name === note.modelName);
+ if (!model) {
+ return Promise.reject('invalid model');
+ }
+
+ const fields = [];
+ for (const field of model.fields) {
+ fields.push(note.fields[field]);
+ }
+
+ const data = {
+ data: JSON.stringify([fields, note.tags.join(' ')]),
+ mid: model.id,
+ deck: note.deckName
+ };
+
+ return AnkiWeb.loadAccountPage('https://ankiweb.net/edit/save', data, this.username, this.password);
+ }).then(response => response !== '0');
+ }
+
+ canAddNotes(notes) {
+ return Promise.resolve(new Array(notes.length).fill(true));
+ }
+
+ getDeckNames() {
+ return this.retrieve().then(info => info.deckNames);
+ }
+
+ getModelNames() {
+ return this.retrieve().then(info => info.models.map(m => m.name));
+ }
+
+ getModelFieldNames(modelName) {
+ return this.retrieve().then(info => {
+ const model = info.models.find(m => m.name === modelName);
+ return model ? model.fields : [];
+ });
+ }
+
+ retrieve() {
+ if (this.noteInfo !== null) {
+ return Promise.resolve(this.noteInfo);
+ }
+
+ return AnkiWeb.scrape(this.username, this.password).then(({deckNames, models}) => {
+ this.noteInfo = {deckNames, models};
+ return this.noteInfo;
+ });
+ }
+
+ static scrape(username, password) {
+ return AnkiWeb.loadAccountPage('https://ankiweb.net/edit/', null, username, password).then(response => {
+ const modelsMatch = /editor\.models = (.*}]);/.exec(response);
+ if (modelsMatch === null) {
+ return Promise.reject('failed to scrape model data');
+ }
+
+ const decksMatch = /editor\.decks = (.*}});/.exec(response);
+ if (decksMatch === null) {
+ return Promise.reject('failed to scrape deck data');
+ }
+
+ const modelsJson = JSON.parse(modelsMatch[1]);
+ const decksJson = JSON.parse(decksMatch[1]);
+
+ const deckNames = Object.keys(decksJson).map(d => decksJson[d].name);
+ const models = [];
+ for (const modelJson of modelsJson) {
+ models.push({
+ name: modelJson.name,
+ id: modelJson.id,
+ fields: modelJson.flds.map(f => f.name)
+ });
+ }
+
+ return {deckNames, models};
+ });
+ }
+
+ static login(username, password) {
+ if (username.length === 0 || password.length === 0) {
+ return Promise.reject('unspecified login credentials');
+ }
+
+ const data = {username, password, submitted: 1};
+ return AnkiWeb.loadPage('https://ankiweb.net/account/login', data).then(response => {
+ if (!response.includes('class="mitem"')) {
+ return Promise.reject('failed to authenticate');
+ }
+ });
+ }
+
+ static loadAccountPage(url, data, username, password) {
+ return AnkiWeb.loadPage(url, data).then(response => {
+ if (response.includes('name="password"')) {
+ return AnkiWeb.login(username, password).then(() => AnkiWeb.loadPage(url, data));
+ } else {
+ return response;
+ }
+ });
+ }
+
+ static loadPage(url, data) {
+ return new Promise((resolve, reject) => {
+ if (data) {
+ const params = [];
+ for (const key in data) {
+ params.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`);
+ }
+
+ url += '?' + params.join('&');
+ }
+
+ const xhr = new XMLHttpRequest();
+ xhr.addEventListener('error', () => reject('failed to execute request'));
+ xhr.addEventListener('load', () => resolve(xhr.responseText));
+ xhr.open('GET', url);
+ xhr.send();
+ });
+ }
+}
diff --git a/ext/bg/js/options-form.js b/ext/bg/js/options-form.js
index 6508a9eb..170b1e8c 100644
--- a/ext/bg/js/options-form.js
+++ b/ext/bg/js/options-form.js
@@ -21,6 +21,10 @@ function yomichan() {
return chrome.extension.getBackgroundPage().yomichan;
}
+function anki() {
+ return yomichan().anki;
+}
+
function fieldsToDict(selection) {
const result = {};
selection.each((index, element) => {
@@ -44,30 +48,22 @@ function modelIdToMarkers(id) {
}[id];
}
-function getBasicOptions() {
+function getFormValues() {
return loadOptions().then(optsOld => {
const optsNew = $.extend({}, optsOld);
optsNew.activateOnStartup = $('#activate-on-startup').prop('checked');
- optsNew.showAdvancedOptions = $('#show-advanced-options').prop('checked');
optsNew.enableAudioPlayback = $('#enable-audio-playback').prop('checked');
- optsNew.enableAnkiConnect = $('#enable-anki-connect').prop('checked');
+ optsNew.showAdvancedOptions = $('#show-advanced-options').prop('checked');
+
optsNew.holdShiftToScan = $('#hold-shift-to-scan').prop('checked');
optsNew.selectMatchedText = $('#select-matched-text').prop('checked');
optsNew.scanDelay = parseInt($('#scan-delay').val(), 10);
optsNew.scanLength = parseInt($('#scan-length').val(), 10);
- return {
- optsNew: sanitizeOptions(optsNew),
- optsOld: sanitizeOptions(optsOld)
- };
- });
-}
-
-function getAnkiOptions() {
- return loadOptions().then(optsOld => {
- const optsNew = $.extend({}, optsOld);
-
+ optsNew.ankiMethod = $('#anki-method').val();
+ optsNew.ankiUsername = $('#anki-username').val();
+ optsNew.ankiPassword = $('#anki-password').val();
optsNew.ankiCardTags = $('#anki-card-tags').val().split(/[,; ]+/);
optsNew.sentenceExtent = parseInt($('#sentence-extent').val(), 10);
optsNew.ankiTermDeck = $('#anki-term-deck').val();
@@ -84,62 +80,76 @@ function getAnkiOptions() {
});
}
+function updateVisibility(opts) {
+ switch (opts.ankiMethod) {
+ case 'ankiweb':
+ $('#anki-general').show();
+ $('.anki-login').show();
+ break;
+ case 'ankiconnect':
+ $('#anki-general').show();
+ $('.anki-login').hide();
+ break;
+ default:
+ $('#anki-general').hide();
+ break;
+ }
+
+ if (opts.showAdvancedOptions) {
+ $('.options-advanced').show();
+ } else {
+ $('.options-advanced').hide();
+ }
+}
+
function populateAnkiDeckAndModel(opts) {
- const yomi = yomichan();
+ const ankiSpinner = $('#anki-spinner');
+ ankiSpinner.show();
+
+ const ankiFormat = $('#anki-format');
+ ankiFormat.hide();
const ankiDeck = $('.anki-deck');
ankiDeck.find('option').remove();
- yomi.api_getDeckNames({callback: names => {
- if (names !== null) {
- names.forEach(name => ankiDeck.append($('<option/>', {value: name, text: name})));
- }
-
- $('#anki-term-deck').val(opts.ankiTermDeck);
- $('#anki-kanji-deck').val(opts.ankiKanjiDeck);
- }});
const ankiModel = $('.anki-model');
ankiModel.find('option').remove();
- yomi.api_getModelNames({callback: names => {
- if (names !== null) {
- names.forEach(name => ankiModel.append($('<option/>', {value: name, text: name})));
- }
-
- populateAnkiFields($('#anki-term-model').val(opts.ankiTermModel), opts);
- populateAnkiFields($('#anki-kanji-model').val(opts.ankiKanjiModel), opts);
- }});
-}
-function updateAnkiStatus() {
- $('.error-dlg').hide();
-
- yomichan().api_getVersion({callback: version => {
- if (version === null) {
- $('.error-dlg-connection').show();
- $('.options-anki-controls').hide();
- } else if (version !== yomichan().getApiVersion()) {
- $('.error-dlg-version').show();
- $('.options-anki-controls').hide();
- } else {
- $('.options-anki-controls').show();
- }
- }});
+ return anki().getDeckNames().then(names => {
+ names.forEach(name => ankiDeck.append($('<option/>', {value: name, text: name})));
+ $('#anki-term-deck').val(opts.ankiTermDeck);
+ $('#anki-kanji-deck').val(opts.ankiKanjiDeck);
+ }).then(() => {
+ return anki().getModelNames();
+ }).then(names => {
+ names.forEach(name => ankiModel.append($('<option/>', {value: name, text: name})));
+ return populateAnkiFields($('#anki-term-model').val(opts.ankiTermModel), opts);
+ }).then(() => {
+ return populateAnkiFields($('#anki-kanji-model').val(opts.ankiKanjiModel), opts);
+ }).then(() => {
+ $('#anki-error').hide();
+ ankiFormat.show();
+ }).catch(error => {
+ $('#anki-error').show().find('span').text(error);
+ }).then(() => {
+ ankiSpinner.hide();
+ });
}
function populateAnkiFields(element, opts) {
+ const table = element.closest('.tab-pane').find('.anki-fields');
+ table.find('tbody').remove();
+
const modelName = element.val();
if (modelName === null) {
- return;
+ return Promise.resolve();
}
const modelId = element.attr('id');
const optKey = modelIdToFieldOptKey(modelId);
const markers = modelIdToMarkers(modelId);
- yomichan().api_getModelFieldNames({modelName, callback: names => {
- const table = element.closest('.tab-pane').find('.anki-fields');
- table.find('tbody').remove();
-
+ return anki().getModelFieldNames(modelName).then(names => {
const tbody = $('<tbody>');
names.forEach(name => {
const button = $('<button>', {type: 'button', class: 'btn btn-default dropdown-toggle'});
@@ -160,7 +170,11 @@ function populateAnkiFields(element, opts) {
groupBtn.append(markerItems);
const group = $('<div>', {class: 'input-group'});
- group.append($('<input>', {type: 'text', class: 'anki-field-value form-control', value: opts[optKey][name] || ''}).data('field', name).change(onOptionsAnkiChanged));
+ group.append($('<input>', {
+ type: 'text',
+ class: 'anki-field-value form-control',
+ value: opts[optKey][name] || ''
+ }).data('field', name).change(onOptionsChanged));
group.append(groupBtn);
const row = $('<tr>');
@@ -171,80 +185,73 @@ function populateAnkiFields(element, opts) {
});
table.append(tbody);
- }});
+ });
}
-function onOptionsBasicChanged(e) {
+function onOptionsChanged(e) {
if (!e.originalEvent && !e.isTrigger) {
return;
}
- getBasicOptions().then(({optsNew, optsOld}) => {
+ getFormValues().then(({optsNew, optsOld}) => {
saveOptions(optsNew).then(() => {
yomichan().setOptions(optsNew);
- if (!optsOld.enableAnkiConnect && optsNew.enableAnkiConnect) {
- updateAnkiStatus();
- populateAnkiDeckAndModel(optsNew);
- $('.options-anki').show();
- } else if (optsOld.enableAnkiConnect && !optsNew.enableAnkiConnect) {
- $('.options-anki').hide();
- }
+ updateVisibility(optsNew);
+
+ const invalidated =
+ optsNew.ankiMethod !== optsOld.ankiMethod ||
+ optsNew.ankiUsername !== optsOld.ankiUsername ||
+ optsNew.ankiPassword !== optsOld.ankiPassword;
- if (optsNew.showAdvancedOptions) {
- $('.options-advanced').show();
- } else {
- $('.options-advanced').hide();
+ if (invalidated) {
+ populateAnkiDeckAndModel(optsNew);
}
});
});
}
-function onOptionsAnkiChanged(e) {
- if (!e.originalEvent && !e.isTrigger) {
+function onAnkiModelChanged(e) {
+ if (!e.originalEvent) {
return;
}
- getAnkiOptions().then(({optsNew, optsOld}) => {
- saveOptions(optsNew).then(() => yomichan().setOptions(optsNew));
- });
-}
+ getFormValues().then(({optsNew, optsOld}) => {
+ optsNew[modelIdToFieldOptKey($(this).id)] = {};
-function onAnkiModelChanged(e) {
- if (e.originalEvent) {
- getAnkiOptions().then(({optsNew, optsOld}) => {
- optsNew[modelIdToFieldOptKey($(this).id)] = {};
- populateAnkiFields($(this), optsNew);
+ const ankiSpinner = $('#anki-spinner');
+ ankiSpinner.show();
+
+ populateAnkiFields($(this), optsNew).then(() => {
saveOptions(optsNew).then(() => yomichan().setOptions(optsNew));
+ }).catch(error => {
+ $('#anki-error').show().find('span').text(error);
+ }).then(() => {
+ $('#anki-error').hide();
+ ankiSpinner.hide();
});
- }
+ });
}
$(document).ready(() => {
loadOptions().then(opts => {
$('#activate-on-startup').prop('checked', opts.activateOnStartup);
$('#enable-audio-playback').prop('checked', opts.enableAudioPlayback);
- $('#enable-anki-connect').prop('checked', opts.enableAnkiConnect);
$('#show-advanced-options').prop('checked', opts.showAdvancedOptions);
$('#hold-shift-to-scan').prop('checked', opts.holdShiftToScan);
$('#select-matched-text').prop('checked', opts.selectMatchedText);
$('#scan-delay').val(opts.scanDelay);
$('#scan-length').val(opts.scanLength);
+
+ $('#anki-method').val(opts.ankiMethod);
+ $('#anki-username').val(opts.ankiUsername);
+ $('#anki-password').val(opts.ankiPassword);
$('#anki-card-tags').val(opts.ankiCardTags.join(' '));
$('#sentence-extent').val(opts.sentenceExtent);
- $('.options-basic input').change(onOptionsBasicChanged);
- $('.options-anki input').change(onOptionsAnkiChanged);
- $('.anki-deck').change(onOptionsAnkiChanged);
+ $('input, select').not('.anki-model').change(onOptionsChanged);
$('.anki-model').change(onAnkiModelChanged);
- if (opts.showAdvancedOptions) {
- $('.options-advanced').show();
- }
-
- if (opts.enableAnkiConnect) {
- updateAnkiStatus();
- populateAnkiDeckAndModel(opts);
- $('.options-anki').show();
- }
+ populateAnkiDeckAndModel(opts);
+ updateVisibility(opts);
});
});
diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js
index e9ad74a3..45af2ff1 100644
--- a/ext/bg/js/options.js
+++ b/ext/bg/js/options.js
@@ -21,12 +21,15 @@ function sanitizeOptions(options) {
const defaults = {
activateOnStartup: true,
enableAudioPlayback: true,
- enableAnkiConnect: false,
showAdvancedOptions: false,
selectMatchedText: true,
holdShiftToScan: true,
scanDelay: 15,
scanLength: 20,
+
+ ankiMethod: 'disabled',
+ ankiUsername: '',
+ ankiPassword: '',
ankiCardTags: ['yomichan'],
sentenceExtent: 200,
diff --git a/ext/bg/js/util.js b/ext/bg/js/util.js
index 95d1b43e..1e033eef 100644
--- a/ext/bg/js/util.js
+++ b/ext/bg/js/util.js
@@ -34,7 +34,7 @@ function loadJson(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.addEventListener('load', () => resolve(JSON.parse(xhr.responseText)));
- xhr.open('GET', chrome.extension.getURL(url), true);
+ xhr.open('GET', chrome.extension.getURL(url));
xhr.send();
});
}
diff --git a/ext/bg/js/yomichan.js b/ext/bg/js/yomichan.js
index 46a240a3..04f29f42 100644
--- a/ext/bg/js/yomichan.js
+++ b/ext/bg/js/yomichan.js
@@ -23,10 +23,9 @@ class Yomichan {
Handlebars.registerHelper('kanjiLinks', kanjiLinks);
this.translator = new Translator();
+ this.anki = new AnkiNull();
this.options = null;
this.importTabId = null;
- this.asyncPools = {};
- this.ankiConnectVer = 0;
this.setState('disabled');
chrome.runtime.onMessage.addListener(this.onMessage.bind(this));
@@ -101,11 +100,20 @@ class Yomichan {
setOptions(options) {
this.options = options;
- this.tabInvokeAll('setOptions', this.options);
- }
- getApiVersion() {
- return 1;
+ switch (options.ankiMethod) {
+ case 'ankiweb':
+ this.anki = new AnkiWeb(options.ankiUsername, options.ankiPassword);
+ break;
+ case 'ankiconnect':
+ this.anki = new AnkiConnect();
+ break;
+ default:
+ this.anki = new AnkiNull();
+ break;
+ }
+
+ this.tabInvokeAll('setOptions', this.options);
}
tabInvokeAll(action, params) {
@@ -120,49 +128,12 @@ 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',
'character',
'expression',
+ 'expression-furigana',
'glossary',
'glossary-list',
'kunyomi',
@@ -184,6 +155,13 @@ class Yomichan {
value = definition.reading;
}
break;
+ case 'expression-furigana':
+ if (mode === 'term_kana' && definition.reading) {
+ value = definition.reading;
+ } else {
+ value = `<ruby>${definition.expression}<rt>${definition.reading}</rt></ruby>`;
+ }
+ break;
case 'reading':
if (mode === 'term_kana') {
value = null;
@@ -257,12 +235,24 @@ class Yomichan {
}
api_getOptions({callback}) {
- loadOptions().then(opts => callback(opts));
+ loadOptions().then(opts => callback(opts)).catch(() => callback(null));
+ }
+
+ api_findKanji({text, callback}) {
+ this.translator.findKanji(text).then(result => callback(result)).catch(() => callback(null));
+ }
+
+ api_findTerm({text, callback}) {
+ this.translator.findTerm(text).then(result => callback(result)).catch(() => callback(null));
+ }
+
+ 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).catch(() => callback(null));
}
api_canAddDefinitions({definitions, modes, callback}) {
@@ -273,9 +263,8 @@ class Yomichan {
}
}
- this.ankiInvokeSafe('canAddNotes', {notes}, 'notes', results => {
+ this.anki.canAddNotes(notes).then(results => {
const states = [];
-
if (results !== null) {
for (let resultBase = 0; resultBase < results.length; resultBase += modes.length) {
const state = {};
@@ -288,35 +277,21 @@ class Yomichan {
}
callback(states);
+ }).catch(() => {
+ callback(null);
});
}
- 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).catch(() => callback(null));
}
api_getModelNames({callback}) {
- this.ankiInvokeSafe('modelNames', {}, null, callback);
+ this.anki.getModelNames().then(callback).catch(() => callback(null));
}
api_getModelFieldNames({modelName, callback}) {
- this.ankiInvokeSafe('modelFieldNames', {modelName}, null, callback);
- }
-
- api_getVersion({callback}) {
- this.ankiInvoke('version', {}, null, callback);
- }
-
- api_renderText({template, data, callback}) {
- callback(Handlebars.templates[template](data));
+ this.anki.getModelFieldNames(modelName).then(callback).catch(() => callback(null));
}
}