Anki API refactor (#790)

* Add function guiBrowseNote

* Assign default server as null

* Use get/set properties for server/enabled

* Refactor option values

* Refactor createNote/Data functions to not use options format directly

* Use createNote for testing

* Add errors
This commit is contained in:
toasted-nutbread 2020-09-09 11:54:40 -04:00 committed by GitHub
parent b687870a55
commit 2aa86cc5f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 40 deletions

View File

@ -27,41 +27,46 @@ class AnkiNoteBuilder {
this._getClipboardImage = getClipboardImage; this._getClipboardImage = getClipboardImage;
} }
async createNote(definition, mode, context, options, templates) { async createNote({
const isKanji = (mode === 'kanji'); definition,
const tags = options.anki.tags; mode,
const modeOptions = isKanji ? options.anki.kanji : options.anki.terms; context,
const modeOptionsFieldEntries = Object.entries(modeOptions.fields); templates,
tags=[],
const fields = {}; duplicateScope='collection',
resultOutputMode='split',
compactGlossaries=false,
modeOptions: {fields, deck, model},
errors=null
}) {
const fieldEntries = Object.entries(fields);
const noteFields = {};
const note = { const note = {
fields, fields: noteFields,
tags, tags,
deckName: modeOptions.deck, deckName: deck,
modelName: modeOptions.model, modelName: model,
options: { options: {duplicateScope}
duplicateScope: options.anki.duplicateScope
}
}; };
const data = this.createNoteData(definition, mode, context, options); const data = this.createNoteData(definition, mode, context, resultOutputMode, compactGlossaries);
const formattedFieldValuePromises = []; const formattedFieldValuePromises = [];
for (const [, fieldValue] of modeOptionsFieldEntries) { for (const [, fieldValue] of fieldEntries) {
const formattedFieldValuePromise = this.formatField(fieldValue, data, templates, null); const formattedFieldValuePromise = this.formatField(fieldValue, data, templates, errors);
formattedFieldValuePromises.push(formattedFieldValuePromise); formattedFieldValuePromises.push(formattedFieldValuePromise);
} }
const formattedFieldValues = await Promise.all(formattedFieldValuePromises); const formattedFieldValues = await Promise.all(formattedFieldValuePromises);
for (let i = 0, ii = modeOptionsFieldEntries.length; i < ii; ++i) { for (let i = 0, ii = fieldEntries.length; i < ii; ++i) {
const fieldName = modeOptionsFieldEntries[i][0]; const fieldName = fieldEntries[i][0];
const formattedFieldValue = formattedFieldValues[i]; const formattedFieldValue = formattedFieldValues[i];
fields[fieldName] = formattedFieldValue; noteFields[fieldName] = formattedFieldValue;
} }
return note; return note;
} }
createNoteData(definition, mode, context, options) { createNoteData(definition, mode, context, resultOutputMode, compactGlossaries) {
const pitches = DictionaryDataUtil.getPitchAccentInfos(definition); const pitches = DictionaryDataUtil.getPitchAccentInfos(definition);
const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0); const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0);
return { return {
@ -69,12 +74,12 @@ class AnkiNoteBuilder {
definition, definition,
pitches, pitches,
pitchCount, pitchCount,
group: options.general.resultOutputMode === 'group', group: resultOutputMode === 'group',
merge: options.general.resultOutputMode === 'merge', merge: resultOutputMode === 'merge',
modeTermKanji: mode === 'term-kanji', modeTermKanji: mode === 'term-kanji',
modeTermKana: mode === 'term-kana', modeTermKana: mode === 'term-kana',
modeKanji: mode === 'kanji', modeKanji: mode === 'kanji',
compactGlossaries: options.general.compactGlossaries, compactGlossaries,
context context
}; };
} }

View File

@ -16,30 +16,30 @@
*/ */
class AnkiConnect { class AnkiConnect {
constructor(server) { constructor() {
this._enabled = false; this._enabled = false;
this._server = server; this._server = null;
this._localVersion = 2; this._localVersion = 2;
this._remoteVersion = 0; this._remoteVersion = 0;
this._versionCheckPromise = null; this._versionCheckPromise = null;
} }
setServer(server) { get server() {
this._server = server;
}
getServer() {
return this._server; return this._server;
} }
setEnabled(enabled) { set server(value) {
this._enabled = enabled; this._server = value;
} }
isEnabled() { get enabled() {
return this._enabled; return this._enabled;
} }
set enabled(value) {
this._enabled = value;
}
async addNote(note) { async addNote(note) {
if (!this._enabled) { return null; } if (!this._enabled) { return null; }
await this._checkVersion(); await this._checkVersion();
@ -76,6 +76,10 @@ class AnkiConnect {
return await this._invoke('guiBrowse', {query}); return await this._invoke('guiBrowse', {query});
} }
async guiBrowseNote(noteId) {
return await this.guiBrowse(`nid:${noteId}`);
}
async storeMediaFile(fileName, dataBase64) { async storeMediaFile(fileName, dataBase64) {
if (!this._enabled) { if (!this._enabled) {
throw new Error('AnkiConnect not enabled'); throw new Error('AnkiConnect not enabled');

View File

@ -471,7 +471,7 @@ class Backend {
); );
} }
const note = await this._ankiNoteBuilder.createNote(definition, mode, context, options, templates); const note = await this._createNote(definition, mode, context, options, templates);
return this._anki.addNote(note); return this._anki.addNote(note);
} }
@ -484,7 +484,7 @@ class Backend {
const notePromises = []; const notePromises = [];
for (const definition of definitions) { for (const definition of definitions) {
for (const mode of modes) { for (const mode of modes) {
const notePromise = this._ankiNoteBuilder.createNote(definition, mode, context, options, templates); const notePromise = this._createNote(definition, mode, context, options, templates);
notePromises.push(notePromise); notePromises.push(notePromise);
} }
} }
@ -524,7 +524,7 @@ class Backend {
} }
async _onApiNoteView({noteId}) { async _onApiNoteView({noteId}) {
return await this._anki.guiBrowse(`nid:${noteId}`); return await this._anki.guiBrowseNote(noteId);
} }
async _onApiTemplateRender({template, data, marker}) { async _onApiTemplateRender({template, data, marker}) {
@ -1023,8 +1023,8 @@ class Backend {
const options = this.getOptions({current: true}); const options = this.getOptions({current: true});
this._updateBadge(); this._updateBadge();
this._anki.setServer(options.anki.server); this._anki.server = options.anki.server;
this._anki.setEnabled(options.anki.enable); this._anki.enabled = options.anki.enable;
if (options.parsing.enableMecabParser) { if (options.parsing.enableMecabParser) {
this._mecab.startListener(); this._mecab.startListener();
@ -1609,4 +1609,21 @@ class Backend {
reader.readAsDataURL(file); reader.readAsDataURL(file);
}); });
} }
async _createNote(definition, mode, context, options, templates) {
const {general: {resultOutputMode, compactGlossaries}, anki: ankiOptions} = options;
const {tags, duplicateScope} = ankiOptions;
const modeOptions = (mode === 'kanji') ? ankiOptions.kanji : ankiOptions.terms;
return await this._ankiNoteBuilder.createNote({
definition,
mode,
context,
templates,
tags,
duplicateScope,
resultOutputMode,
compactGlossaries,
modeOptions
});
}
} }

View File

@ -147,8 +147,22 @@ class AnkiTemplatesController {
renderTemplate: api.templateRender.bind(api), renderTemplate: api.templateRender.bind(api),
getClipboardImage: api.clipboardGetImage.bind(api) getClipboardImage: api.clipboardGetImage.bind(api)
}); });
const data = ankiNoteBuilder.createNoteData(definition, mode, context, options); const {general: {resultOutputMode, compactGlossaries}} = options;
result = await ankiNoteBuilder.formatField(field, data, templates, exceptions); const note = await ankiNoteBuilder.createNote({
definition,
mode,
context,
templates,
resultOutputMode,
compactGlossaries,
modeOptions: {
fields: {field},
deck: '',
model: ''
},
errors: exceptions
});
result = note.fields.field;
} }
} catch (e) { } catch (e) {
exceptions.push(e); exceptions.push(e);