Anki note api functions (#802)
* Assign duplicateScope to a variable * Add api.addAnkiNote * Add api.getAnkiNoteInfo, update returned data format
This commit is contained in:
parent
3dd4822ab3
commit
892f7ed3b8
@ -91,6 +91,8 @@ class Backend {
|
|||||||
['kanjiFind', {async: true, contentScript: true, handler: this._onApiKanjiFind.bind(this)}],
|
['kanjiFind', {async: true, contentScript: true, handler: this._onApiKanjiFind.bind(this)}],
|
||||||
['termsFind', {async: true, contentScript: true, handler: this._onApiTermsFind.bind(this)}],
|
['termsFind', {async: true, contentScript: true, handler: this._onApiTermsFind.bind(this)}],
|
||||||
['textParse', {async: true, contentScript: true, handler: this._onApiTextParse.bind(this)}],
|
['textParse', {async: true, contentScript: true, handler: this._onApiTextParse.bind(this)}],
|
||||||
|
['addAnkiNote', {async: true, contentScript: true, handler: this._onApiAddAnkiNote.bind(this)}],
|
||||||
|
['getAnkiNoteInfo', {async: true, contentScript: true, handler: this._onApiGetAnkiNoteInfo.bind(this)}],
|
||||||
['definitionAdd', {async: true, contentScript: true, handler: this._onApiDefinitionAdd.bind(this)}],
|
['definitionAdd', {async: true, contentScript: true, handler: this._onApiDefinitionAdd.bind(this)}],
|
||||||
['definitionsAddable', {async: true, contentScript: true, handler: this._onApiDefinitionsAddable.bind(this)}],
|
['definitionsAddable', {async: true, contentScript: true, handler: this._onApiDefinitionsAddable.bind(this)}],
|
||||||
['noteView', {async: true, contentScript: true, handler: this._onApiNoteView.bind(this)}],
|
['noteView', {async: true, contentScript: true, handler: this._onApiNoteView.bind(this)}],
|
||||||
@ -437,60 +439,68 @@ class Backend {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _onApiAddAnkiNote({note}) {
|
||||||
|
return await this._anki.addNote(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onApiGetAnkiNoteInfo({notes, duplicateScope}) {
|
||||||
|
const results = [];
|
||||||
|
const cannotAdd = [];
|
||||||
|
const canAddArray = await this._anki.canAddNotes(notes);
|
||||||
|
|
||||||
|
for (let i = 0; i < notes.length; ++i) {
|
||||||
|
const note = notes[i];
|
||||||
|
const canAdd = canAddArray[i];
|
||||||
|
const info = {canAdd, noteIds: null};
|
||||||
|
results.push(info);
|
||||||
|
if (!canAdd) {
|
||||||
|
cannotAdd.push({note, info});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cannotAdd.length > 0) {
|
||||||
|
const cannotAddNotes = cannotAdd.map(({note}) => note);
|
||||||
|
const noteIdsArray = await this._anki.findNoteIds(cannotAddNotes, duplicateScope);
|
||||||
|
for (let i = 0, ii = Math.min(cannotAdd.length, noteIdsArray.length); i < ii; ++i) {
|
||||||
|
const noteIds = noteIdsArray[i];
|
||||||
|
if (noteIds.length > 0) {
|
||||||
|
cannotAdd[i].info.noteIds = noteIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
async _onApiDefinitionAdd({definition, mode, context, ownerFrameId, optionsContext}, sender) {
|
async _onApiDefinitionAdd({definition, mode, context, ownerFrameId, optionsContext}, sender) {
|
||||||
const options = this.getOptions(optionsContext);
|
const options = this.getOptions(optionsContext);
|
||||||
const templates = this._getTemplates(options);
|
const templates = this._getTemplates(options);
|
||||||
const {id: tabId, windowId} = (sender && sender.tab ? sender.tab : {});
|
const {id: tabId, windowId} = (sender && sender.tab ? sender.tab : {});
|
||||||
const note = await this._createNote(definition, mode, context, options, templates, true, {windowId, tabId, ownerFrameId});
|
const note = await this._createNote(definition, mode, context, options, templates, true, {windowId, tabId, ownerFrameId});
|
||||||
return this._anki.addNote(note);
|
return await this._onApiAddAnkiNote({note});
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onApiDefinitionsAddable({definitions, modes, context, optionsContext}) {
|
async _onApiDefinitionsAddable({definitions, modes, context, optionsContext}) {
|
||||||
const options = this.getOptions(optionsContext);
|
const options = this.getOptions(optionsContext);
|
||||||
const templates = this._getTemplates(options);
|
const templates = this._getTemplates(options);
|
||||||
const states = [];
|
|
||||||
|
|
||||||
try {
|
const modeCount = modes.length;
|
||||||
const notePromises = [];
|
const {duplicateScope} = options.anki;
|
||||||
for (const definition of definitions) {
|
const notePromises = [];
|
||||||
for (const mode of modes) {
|
for (const definition of definitions) {
|
||||||
const notePromise = this._createNote(definition, mode, context, options, templates, false, null);
|
for (const mode of modes) {
|
||||||
notePromises.push(notePromise);
|
const notePromise = this._createNote(definition, mode, context, options, templates, false, null);
|
||||||
}
|
notePromises.push(notePromise);
|
||||||
}
|
}
|
||||||
const notes = await Promise.all(notePromises);
|
|
||||||
|
|
||||||
const cannotAdd = [];
|
|
||||||
const results = await this._anki.canAddNotes(notes);
|
|
||||||
for (let resultBase = 0; resultBase < results.length; resultBase += modes.length) {
|
|
||||||
const state = {};
|
|
||||||
for (let modeOffset = 0; modeOffset < modes.length; ++modeOffset) {
|
|
||||||
const index = resultBase + modeOffset;
|
|
||||||
const result = results[index];
|
|
||||||
const info = {canAdd: result};
|
|
||||||
state[modes[modeOffset]] = info;
|
|
||||||
if (!result) {
|
|
||||||
cannotAdd.push([notes[index], info]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
states.push(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cannotAdd.length > 0) {
|
|
||||||
const noteIdsArray = await this._anki.findNoteIds(cannotAdd.map((e) => e[0]), options.anki.duplicateScope);
|
|
||||||
for (let i = 0, ii = Math.min(cannotAdd.length, noteIdsArray.length); i < ii; ++i) {
|
|
||||||
const noteIds = noteIdsArray[i];
|
|
||||||
if (noteIds.length > 0) {
|
|
||||||
cannotAdd[i][1].noteId = noteIds[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// NOP
|
|
||||||
}
|
}
|
||||||
|
const notes = await Promise.all(notePromises);
|
||||||
|
|
||||||
return states;
|
const infos = await this._onApiGetAnkiNoteInfo({notes, duplicateScope});
|
||||||
|
const results = [];
|
||||||
|
for (let i = 0, ii = infos.length; i < ii; i += modeCount) {
|
||||||
|
results.push(infos.slice(i, i + modeCount));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onApiNoteView({noteId}) {
|
async _onApiNoteView({noteId}) {
|
||||||
|
@ -77,6 +77,14 @@ const api = (() => {
|
|||||||
return this._invoke('kanjiFind', {text, optionsContext});
|
return this._invoke('kanjiFind', {text, optionsContext});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addAnkiNote(note) {
|
||||||
|
return this._invoke('addAnkiNote', {note});
|
||||||
|
}
|
||||||
|
|
||||||
|
getAnkiNoteInfo(notes, duplicateScope) {
|
||||||
|
return this._invoke('getAnkiNoteInfo', {notes, duplicateScope});
|
||||||
|
}
|
||||||
|
|
||||||
definitionAdd(definition, mode, context, ownerFrameId, optionsContext) {
|
definitionAdd(definition, mode, context, ownerFrameId, optionsContext) {
|
||||||
return this._invoke('definitionAdd', {definition, mode, context, ownerFrameId, optionsContext});
|
return this._invoke('definitionAdd', {definition, mode, context, ownerFrameId, optionsContext});
|
||||||
}
|
}
|
||||||
|
@ -889,10 +889,15 @@ class Display extends EventDispatcher {
|
|||||||
|
|
||||||
async _setContentTermsOrKanjiUpdateAdderButtons(token, isTerms, definitions) {
|
async _setContentTermsOrKanjiUpdateAdderButtons(token, isTerms, definitions) {
|
||||||
const modes = isTerms ? ['term-kanji', 'term-kana'] : ['kanji'];
|
const modes = isTerms ? ['term-kanji', 'term-kana'] : ['kanji'];
|
||||||
const states = await this._getDefinitionsAddable(definitions, modes);
|
let states;
|
||||||
|
try {
|
||||||
|
states = await this._getDefinitionsAddable(definitions, modes);
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this._setContentToken !== token) { return; }
|
if (this._setContentToken !== token) { return; }
|
||||||
|
|
||||||
this._updateAdderButtons(states);
|
this._updateAdderButtons(states, modes);
|
||||||
}
|
}
|
||||||
|
|
||||||
_setContentExtensionUnloaded() {
|
_setContentExtensionUnloaded() {
|
||||||
@ -953,19 +958,22 @@ class Display extends EventDispatcher {
|
|||||||
this._navigationHeader.dataset.hasNext = `${!!next}`;
|
this._navigationHeader.dataset.hasNext = `${!!next}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateAdderButtons(states) {
|
_updateAdderButtons(states, modes) {
|
||||||
for (let i = 0; i < states.length; ++i) {
|
for (let i = 0, ii = states.length; i < ii; ++i) {
|
||||||
|
const infos = states[i];
|
||||||
let noteId = null;
|
let noteId = null;
|
||||||
for (const [mode, info] of Object.entries(states[i])) {
|
for (let j = 0, jj = infos.length; j < jj; ++j) {
|
||||||
|
const {canAdd, noteIds} = infos[j];
|
||||||
|
const mode = modes[j];
|
||||||
const button = this._adderButtonFind(i, mode);
|
const button = this._adderButtonFind(i, mode);
|
||||||
if (button === null) {
|
if (button === null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info.canAdd && noteId === null && info.noteId) {
|
if (Array.isArray(noteIds) && noteIds.length > 0) {
|
||||||
noteId = info.noteId;
|
noteId = noteIds[0];
|
||||||
}
|
}
|
||||||
button.classList.toggle('disabled', !info.canAdd);
|
button.classList.toggle('disabled', !canAdd);
|
||||||
button.classList.remove('pending');
|
button.classList.remove('pending');
|
||||||
}
|
}
|
||||||
if (noteId !== null) {
|
if (noteId !== null) {
|
||||||
|
Loading…
Reference in New Issue
Block a user