Refactor display anki functions (#1224)

* Refactor note adding/viewing functions

* Move _addDefinition

* Update where anki field templates are assigned

* Update _createNote to not include options/templates arguments

* Simplify getAnkiNoteInfo to not require duplicateScope
This commit is contained in:
toasted-nutbread 2021-01-11 18:37:07 -05:00 committed by GitHub
parent 4ed9493645
commit 5e87a490f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 66 deletions

View File

@ -103,12 +103,12 @@ class AnkiConnect {
return await this._invoke('storeMediaFile', {filename: fileName, data: dataBase64}); return await this._invoke('storeMediaFile', {filename: fileName, data: dataBase64});
} }
async findNoteIds(notes, duplicateScope) { async findNoteIds(notes) {
if (!this._enabled) { return []; } if (!this._enabled) { return []; }
await this._checkVersion(); await this._checkVersion();
const actions = notes.map((note) => { const actions = notes.map((note) => {
let query = ''; let query = '';
switch (duplicateScope) { switch (this._getDuplicateScopeFromNote(note)) {
case 'deck': case 'deck':
query = `"deck:${this._escapeQuery(note.deckName)}" `; query = `"deck:${this._escapeQuery(note.deckName)}" `;
break; break;
@ -178,4 +178,15 @@ class AnkiConnect {
const key = fieldNames[0]; const key = fieldNames[0];
return `"${key.toLowerCase()}:${this._escapeQuery(fields[key])}"`; return `"${key.toLowerCase()}:${this._escapeQuery(fields[key])}"`;
} }
_getDuplicateScopeFromNote(note) {
const {options} = note;
if (typeof options === 'object' && options !== null) {
const {duplicateScope} = options;
if (typeof duplicateScope !== 'undefined') {
return duplicateScope;
}
}
return null;
}
} }

View File

@ -447,7 +447,7 @@ class Backend {
return await this._anki.addNote(note); return await this._anki.addNote(note);
} }
async _onApiGetAnkiNoteInfo({notes, duplicateScope}) { async _onApiGetAnkiNoteInfo({notes}) {
const results = []; const results = [];
const cannotAdd = []; const cannotAdd = [];
const canAddArray = await this._anki.canAddNotes(notes); const canAddArray = await this._anki.canAddNotes(notes);
@ -464,7 +464,7 @@ class Backend {
if (cannotAdd.length > 0) { if (cannotAdd.length > 0) {
const cannotAddNotes = cannotAdd.map(({note}) => note); const cannotAddNotes = cannotAdd.map(({note}) => note);
const noteIdsArray = await this._anki.findNoteIds(cannotAddNotes, duplicateScope); const noteIdsArray = await this._anki.findNoteIds(cannotAddNotes);
for (let i = 0, ii = Math.min(cannotAdd.length, noteIdsArray.length); i < ii; ++i) { for (let i = 0, ii = Math.min(cannotAdd.length, noteIdsArray.length); i < ii; ++i) {
const noteIds = noteIdsArray[i]; const noteIds = noteIdsArray[i];
if (noteIds.length > 0) { if (noteIds.length > 0) {

View File

@ -81,8 +81,8 @@ const api = (() => {
return this._invoke('addAnkiNote', {note}); return this._invoke('addAnkiNote', {note});
} }
getAnkiNoteInfo(notes, duplicateScope) { getAnkiNoteInfo(notes) {
return this._invoke('getAnkiNoteInfo', {notes, duplicateScope}); return this._invoke('getAnkiNoteInfo', {notes});
} }
injectAnkiNoteMedia(timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails) { injectAnkiNoteMedia(timestamp, definitionDetails, audioDetails, screenshotDetails, clipboardDetails) {

View File

@ -86,8 +86,8 @@ class Display extends EventDispatcher {
documentUtil: this._documentUtil documentUtil: this._documentUtil
}); });
this._mode = null; this._mode = null;
this._defaultAnkiFieldTemplates = null; this._ankiFieldTemplates = null;
this._defaultAnkiFieldTemplatesPromise = null; this._ankiFieldTemplatesDefault = null;
this._ankiNoteBuilder = new AnkiNoteBuilder(true); this._ankiNoteBuilder = new AnkiNoteBuilder(true);
this._updateAdderButtonsPromise = Promise.resolve(); this._updateAdderButtonsPromise = Promise.resolve();
this._contentScrollElement = document.querySelector('#content-scroll'); this._contentScrollElement = document.querySelector('#content-scroll');
@ -125,10 +125,10 @@ class Display extends EventDispatcher {
['firstEntry', () => { this._focusEntry(0, true); }], ['firstEntry', () => { this._focusEntry(0, true); }],
['historyBackward', () => { this._sourceTermView(); }], ['historyBackward', () => { this._sourceTermView(); }],
['historyForward', () => { this._nextTermView(); }], ['historyForward', () => { this._nextTermView(); }],
['addNoteKanji', () => { this._noteTryAdd('kanji'); }], ['addNoteKanji', () => { this._tryAddAnkiNoteForSelectedDefinition('kanji'); }],
['addNoteTermKanji', () => { this._noteTryAdd('term-kanji'); }], ['addNoteTermKanji', () => { this._tryAddAnkiNoteForSelectedDefinition('term-kanji'); }],
['addNoteTermKana', () => { this._noteTryAdd('term-kana'); }], ['addNoteTermKana', () => { this._tryAddAnkiNoteForSelectedDefinition('term-kana'); }],
['viewNote', () => { this._noteTryView(); }], ['viewNote', () => { this._tryViewAnkiNoteForSelectedDefinition(); }],
['playAudio', () => { this._playAudioCurrent(); }], ['playAudio', () => { this._playAudioCurrent(); }],
['copyHostSelection', () => this._copyHostSelection()] ['copyHostSelection', () => this._copyHostSelection()]
]); ]);
@ -304,8 +304,10 @@ class Display extends EventDispatcher {
async updateOptions() { async updateOptions() {
const options = await api.optionsGet(this.getOptionsContext()); const options = await api.optionsGet(this.getOptionsContext());
const templates = await this._getAnkiFieldTemplates(options);
const {scanning: scanningOptions, sentenceParsing: sentenceParsingOptions} = options; const {scanning: scanningOptions, sentenceParsing: sentenceParsingOptions} = options;
this._options = options; this._options = options;
this._ankiFieldTemplates = templates;
this._updateDocumentOptions(options); this._updateDocumentOptions(options);
this._updateTheme(options.general.popupTheme); this._updateTheme(options.general.popupTheme);
@ -747,9 +749,7 @@ class Display extends EventDispatcher {
e.preventDefault(); e.preventDefault();
const link = e.currentTarget; const link = e.currentTarget;
const index = this._getClosestDefinitionIndex(link); const index = this._getClosestDefinitionIndex(link);
if (index < 0 || index >= this._definitions.length) { return; } this._addAnkiNote(index, link.dataset.mode);
this._noteAdd(this._definitions[index], link.dataset.mode);
} }
_onNoteView(e) { _onNoteView(e) {
@ -1188,43 +1188,42 @@ class Display extends EventDispatcher {
} }
} }
_noteTryAdd(mode) { _tryAddAnkiNoteForSelectedDefinition(mode) {
const index = this._index; this._addAnkiNote(this._index, mode);
if (index < 0 || index >= this._definitions.length) { return; }
const button = this._adderButtonFind(index, mode);
if (button !== null && !button.disabled) {
this._noteAdd(this._definitions[index], mode);
}
} }
_noteTryView() { _tryViewAnkiNoteForSelectedDefinition() {
const button = this._viewerButtonFind(this._index); const button = this._viewerButtonFind(this._index);
if (button !== null && !button.disabled) { if (button !== null && !button.disabled) {
api.noteView(button.dataset.noteId); api.noteView(button.dataset.noteId);
} }
} }
async _noteAdd(definition, mode) { async _addAnkiNote(definitionIndex, mode) {
if (definitionIndex < 0 || definitionIndex >= this._definitions.length) { return false; }
const definition = this._definitions[definitionIndex];
const button = this._adderButtonFind(definitionIndex, mode);
if (button === null || button.disabled) { return false; }
const overrideToken = this._progressIndicatorVisible.setOverride(true); const overrideToken = this._progressIndicatorVisible.setOverride(true);
try { try {
const noteContext = await this._getNoteContext(); const noteContext = await this._getNoteContext();
const noteId = await this._addDefinition(definition, mode, noteContext); const note = await this._createNote(definition, mode, noteContext, true);
const noteId = await api.addAnkiNote(note);
if (noteId) { if (noteId) {
const index = this._definitions.indexOf(definition); button.disabled = true;
const adderButton = this._adderButtonFind(index, mode); this._viewerButtonShow(definitionIndex, noteId);
if (adderButton !== null) {
adderButton.disabled = true;
}
this._viewerButtonShow(index, noteId);
} else { } else {
throw new Error('Note could not be added'); throw new Error('Note could not be added');
} }
} catch (e) { } catch (e) {
this.onError(e); this.onError(e);
return false;
} finally { } finally {
this._progressIndicatorVisible.clearOverride(overrideToken); this._progressIndicatorVisible.clearOverride(overrideToken);
} }
return true;
} }
async _playAudio(definitionIndex, expressionIndex) { async _playAudio(definitionIndex, expressionIndex) {
@ -1462,56 +1461,30 @@ class Display extends EventDispatcher {
this.trigger('modeChange', {mode}); this.trigger('modeChange', {mode});
} }
async _getTemplates(options) { async _getAnkiFieldTemplates(options) {
let templates = options.anki.fieldTemplates; let templates = options.anki.fieldTemplates;
if (typeof templates === 'string') { return templates; } if (typeof templates === 'string') { return templates; }
templates = this._defaultAnkiFieldTemplates; templates = this._ankiFieldTemplatesDefault;
if (typeof templates === 'string') { return templates; } if (typeof templates === 'string') { return templates; }
return await this._getDefaultTemplatesPromise(); templates = await api.getDefaultAnkiFieldTemplates();
} this._ankiFieldTemplatesDefault = templates;
return templates;
_getDefaultTemplatesPromise() {
if (this._defaultAnkiFieldTemplatesPromise === null) {
this._defaultAnkiFieldTemplatesPromise = this._getDefaultTemplates();
this._defaultAnkiFieldTemplatesPromise.then(
() => { this._defaultAnkiFieldTemplatesPromise = null; },
() => {} // NOP
);
}
return this._defaultAnkiFieldTemplatesPromise;
}
async _getDefaultTemplates() {
const value = await api.getDefaultAnkiFieldTemplates();
this._defaultAnkiFieldTemplates = value;
return value;
}
async _addDefinition(definition, mode, context) {
const options = this._options;
const templates = await this._getTemplates(options);
const note = await this._createNote(definition, mode, context, options, templates, true);
return await api.addAnkiNote(note);
} }
async _areDefinitionsAddable(definitions, modes, context) { async _areDefinitionsAddable(definitions, modes, context) {
const options = this._options;
const templates = await this._getTemplates(options);
const modeCount = modes.length; const modeCount = modes.length;
const {duplicateScope} = options.anki;
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._createNote(definition, mode, context, options, templates, false); const notePromise = this._createNote(definition, mode, context, false);
notePromises.push(notePromise); notePromises.push(notePromise);
} }
} }
const notes = await Promise.all(notePromises); const notes = await Promise.all(notePromises);
const infos = await api.getAnkiNoteInfo(notes, duplicateScope); const infos = await api.getAnkiNoteInfo(notes);
const results = []; const results = [];
for (let i = 0, ii = infos.length; i < ii; i += modeCount) { for (let i = 0, ii = infos.length; i < ii; i += modeCount) {
results.push(infos.slice(i, i + modeCount)); results.push(infos.slice(i, i + modeCount));
@ -1533,7 +1506,9 @@ class Display extends EventDispatcher {
return results; return results;
} }
async _createNote(definition, mode, context, options, templates, injectMedia) { async _createNote(definition, mode, context, injectMedia) {
const options = this._options;
const templates = this._ankiFieldTemplates;
const { const {
general: {resultOutputMode, glossaryLayoutMode, compactTags}, general: {resultOutputMode, glossaryLayoutMode, compactTags},
anki: ankiOptions anki: ankiOptions