Merge pull request #453 from toasted-nutbread/reuse-anki-instance
Reuse AnkiConnect instance
This commit is contained in:
commit
5b3d7fadc3
@ -16,7 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class AnkiNoteBuilder {
|
class AnkiNoteBuilder {
|
||||||
constructor({audioSystem, renderTemplate}) {
|
constructor({anki, audioSystem, renderTemplate}) {
|
||||||
|
this._anki = anki;
|
||||||
this._audioSystem = audioSystem;
|
this._audioSystem = audioSystem;
|
||||||
this._renderTemplate = renderTemplate;
|
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; }
|
if (!this._containsMarker(fields, 'screenshot')) { return; }
|
||||||
|
|
||||||
const now = new Date(Date.now());
|
const now = new Date(Date.now());
|
||||||
@ -109,7 +110,7 @@ class AnkiNoteBuilder {
|
|||||||
const data = screenshot.dataUrl.replace(/^data:[\w\W]*?,/, '');
|
const data = screenshot.dataUrl.replace(/^data:[\w\W]*?,/, '');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await anki.storeMediaFile(filename, data);
|
await this._anki.storeMediaFile(filename, data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -19,122 +19,119 @@
|
|||||||
* requestJson
|
* requestJson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* AnkiConnect
|
|
||||||
*/
|
|
||||||
|
|
||||||
class AnkiConnect {
|
class AnkiConnect {
|
||||||
constructor(server) {
|
constructor(server) {
|
||||||
this.server = server;
|
this._enabled = false;
|
||||||
this.localVersion = 2;
|
this._server = server;
|
||||||
this.remoteVersion = 0;
|
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) {
|
async addNote(note) {
|
||||||
await this.checkVersion();
|
if (!this._enabled) { return null; }
|
||||||
return await this.ankiInvoke('addNote', {note});
|
await this._checkVersion();
|
||||||
|
return await this._invoke('addNote', {note});
|
||||||
}
|
}
|
||||||
|
|
||||||
async canAddNotes(notes) {
|
async canAddNotes(notes) {
|
||||||
await this.checkVersion();
|
if (!this._enabled) { return []; }
|
||||||
return await this.ankiInvoke('canAddNotes', {notes});
|
await this._checkVersion();
|
||||||
|
return await this._invoke('canAddNotes', {notes});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDeckNames() {
|
async getDeckNames() {
|
||||||
await this.checkVersion();
|
if (!this._enabled) { return []; }
|
||||||
return await this.ankiInvoke('deckNames');
|
await this._checkVersion();
|
||||||
|
return await this._invoke('deckNames');
|
||||||
}
|
}
|
||||||
|
|
||||||
async getModelNames() {
|
async getModelNames() {
|
||||||
await this.checkVersion();
|
if (!this._enabled) { return []; }
|
||||||
return await this.ankiInvoke('modelNames');
|
await this._checkVersion();
|
||||||
|
return await this._invoke('modelNames');
|
||||||
}
|
}
|
||||||
|
|
||||||
async getModelFieldNames(modelName) {
|
async getModelFieldNames(modelName) {
|
||||||
await this.checkVersion();
|
if (!this._enabled) { return []; }
|
||||||
return await this.ankiInvoke('modelFieldNames', {modelName});
|
await this._checkVersion();
|
||||||
|
return await this._invoke('modelFieldNames', {modelName});
|
||||||
}
|
}
|
||||||
|
|
||||||
async guiBrowse(query) {
|
async guiBrowse(query) {
|
||||||
await this.checkVersion();
|
if (!this._enabled) { return []; }
|
||||||
return await this.ankiInvoke('guiBrowse', {query});
|
await this._checkVersion();
|
||||||
|
return await this._invoke('guiBrowse', {query});
|
||||||
}
|
}
|
||||||
|
|
||||||
async storeMediaFile(filename, dataBase64) {
|
async storeMediaFile(filename, dataBase64) {
|
||||||
await this.checkVersion();
|
if (!this._enabled) {
|
||||||
return await this.ankiInvoke('storeMediaFile', {filename, data: dataBase64});
|
throw new Error('AnkiConnect not enabled');
|
||||||
|
}
|
||||||
|
await this._checkVersion();
|
||||||
|
return await this._invoke('storeMediaFile', {filename, data: dataBase64});
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkVersion() {
|
async findNoteIds(notes) {
|
||||||
if (this.remoteVersion < this.localVersion) {
|
if (!this._enabled) { return []; }
|
||||||
this.remoteVersion = await this.ankiInvoke('version');
|
await this._checkVersion();
|
||||||
if (this.remoteVersion < this.localVersion) {
|
const actions = notes.map((note) => ({
|
||||||
|
action: 'findNotes',
|
||||||
|
params: {
|
||||||
|
query: `deck:"${this._escapeQuery(note.deckName)}" ${this._fieldsToQuery(note.fields)}`
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
return await this._invoke('multi', {actions});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private
|
||||||
|
|
||||||
|
async _checkVersion() {
|
||||||
|
if (this._remoteVersion < this._localVersion) {
|
||||||
|
this._remoteVersion = await this._invoke('version');
|
||||||
|
if (this._remoteVersion < this._localVersion) {
|
||||||
throw new Error('Extension and plugin versions incompatible');
|
throw new Error('Extension and plugin versions incompatible');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findNoteIds(notes) {
|
async _invoke(action, params) {
|
||||||
await this.checkVersion();
|
const result = await requestJson(this._server, 'POST', {action, params, version: this._localVersion});
|
||||||
const actions = notes.map((note) => ({
|
if (isObject(result)) {
|
||||||
action: 'findNotes',
|
const error = result.error;
|
||||||
params: {
|
if (typeof error !== 'undefined') {
|
||||||
query: `deck:"${AnkiConnect.escapeQuery(note.deckName)}" ${AnkiConnect.fieldsToQuery(note.fields)}`
|
throw new Error(`AnkiConnect error: ${error}`);
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
return await this.ankiInvoke('multi', {actions});
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ankiInvoke(action, params) {
|
_escapeQuery(text) {
|
||||||
return requestJson(this.server, 'POST', {action, params, version: this.localVersion});
|
|
||||||
}
|
|
||||||
|
|
||||||
static escapeQuery(text) {
|
|
||||||
return text.replace(/"/g, '');
|
return text.replace(/"/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
static fieldsToQuery(fields) {
|
_fieldsToQuery(fields) {
|
||||||
const fieldNames = Object.keys(fields);
|
const fieldNames = Object.keys(fields);
|
||||||
if (fieldNames.length === 0) {
|
if (fieldNames.length === 0) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = fieldNames[0];
|
const key = fieldNames[0];
|
||||||
return `${key.toLowerCase()}:"${AnkiConnect.escapeQuery(fields[key])}"`;
|
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 [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
/* global
|
/* global
|
||||||
* AnkiConnect
|
* AnkiConnect
|
||||||
* AnkiNoteBuilder
|
* AnkiNoteBuilder
|
||||||
* AnkiNull
|
|
||||||
* AudioSystem
|
* AudioSystem
|
||||||
* AudioUriBuilder
|
* AudioUriBuilder
|
||||||
* BackendApiForwarder
|
* BackendApiForwarder
|
||||||
@ -46,7 +45,7 @@ class Backend {
|
|||||||
this.database = new Database();
|
this.database = new Database();
|
||||||
this.dictionaryImporter = new DictionaryImporter();
|
this.dictionaryImporter = new DictionaryImporter();
|
||||||
this.translator = new Translator(this.database);
|
this.translator = new Translator(this.database);
|
||||||
this.anki = new AnkiNull();
|
this.anki = new AnkiConnect();
|
||||||
this.mecab = new Mecab();
|
this.mecab = new Mecab();
|
||||||
this.clipboardMonitor = new ClipboardMonitor({getClipboard: this._onApiClipboardGet.bind(this)});
|
this.clipboardMonitor = new ClipboardMonitor({getClipboard: this._onApiClipboardGet.bind(this)});
|
||||||
this.options = null;
|
this.options = null;
|
||||||
@ -55,6 +54,7 @@ class Backend {
|
|||||||
this.audioSystem = new AudioSystem({getAudioUri: this._getAudioUri.bind(this)});
|
this.audioSystem = new AudioSystem({getAudioUri: this._getAudioUri.bind(this)});
|
||||||
this.audioUriBuilder = new AudioUriBuilder();
|
this.audioUriBuilder = new AudioUriBuilder();
|
||||||
this.ankiNoteBuilder = new AnkiNoteBuilder({
|
this.ankiNoteBuilder = new AnkiNoteBuilder({
|
||||||
|
anki: this.anki,
|
||||||
audioSystem: this.audioSystem,
|
audioSystem: this.audioSystem,
|
||||||
renderTemplate: this._renderTemplate.bind(this)
|
renderTemplate: this._renderTemplate.bind(this)
|
||||||
});
|
});
|
||||||
@ -214,7 +214,8 @@ class Backend {
|
|||||||
this.setExtensionBadgeText('');
|
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) {
|
if (options.parsing.enableMecabParser) {
|
||||||
this.mecab.startListener();
|
this.mecab.startListener();
|
||||||
@ -505,8 +506,7 @@ class Backend {
|
|||||||
await this.ankiNoteBuilder.injectScreenshot(
|
await this.ankiNoteBuilder.injectScreenshot(
|
||||||
definition,
|
definition,
|
||||||
options.anki.terms.fields,
|
options.anki.terms.fields,
|
||||||
details.screenshot,
|
details.screenshot
|
||||||
this.anki
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user