This commit is contained in:
Alex Yatskov 2016-10-15 19:05:53 -07:00
parent ef25ad144e
commit 7aa6d6feee
6 changed files with 95 additions and 31 deletions

View File

@ -2,6 +2,7 @@
<html lang="en"> <html lang="en">
<body> <body>
<script src="../lib/handlebars.min.js"></script> <script src="../lib/handlebars.min.js"></script>
<script src="../lib/jquery-2.2.2.min.js"></script>
<script src="../lib/dexie.min.js"></script> <script src="../lib/dexie.min.js"></script>
<script src="js/ankiweb.js"></script> <script src="js/ankiweb.js"></script>
<script src="js/ankiconnect.js"></script> <script src="js/ankiconnect.js"></script>

View File

@ -115,7 +115,7 @@ class AnkiWeb {
static login(username, password) { static login(username, password) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
$.post('https://ankiweb.net/account/login', {username, password, submitted: 1}, (data, status) => { $.post('https://ankiweb.net/account/login', {username, password, submitted: 1}, (data, status) => {
if (status !== 'success') { if (status === 'success') {
if (data.includes('class="mitem"')) { if (data.includes('class="mitem"')) {
resolve(); resolve();
} else { } else {

View File

@ -85,6 +85,9 @@ function getAnkiOptions() {
return loadOptions().then(optsOld => { return loadOptions().then(optsOld => {
const optsNew = $.extend({}, 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.ankiCardTags = $('#anki-card-tags').val().split(/[,; ]+/);
optsNew.sentenceExtent = parseInt($('#sentence-extent').val(), 10); optsNew.sentenceExtent = parseInt($('#sentence-extent').val(), 10);
optsNew.ankiTermDeck = $('#anki-term-deck').val(); optsNew.ankiTermDeck = $('#anki-term-deck').val();
@ -219,13 +222,11 @@ function onOptionsBasicChanged(e) {
} }
function onOptionsAnkiChanged(e) { function onOptionsAnkiChanged(e) {
if (!e.originalEvent && !e.isTrigger) { if (e.originalEvent || e.isTrigger) {
return; getAnkiOptions().then(({optsNew, optsOld}) => {
saveOptions(optsNew).then(() => yomichan().setOptions(optsNew));
});
} }
getAnkiOptions().then(({optsNew, optsOld}) => {
saveOptions(optsNew).then(() => yomichan().setOptions(optsNew));
});
} }
function onAnkiModelChanged(e) { function onAnkiModelChanged(e) {
@ -248,9 +249,14 @@ $(document).ready(() => {
$('#select-matched-text').prop('checked', opts.selectMatchedText); $('#select-matched-text').prop('checked', opts.selectMatchedText);
$('#scan-delay').val(opts.scanDelay); $('#scan-delay').val(opts.scanDelay);
$('#scan-length').val(opts.scanLength); $('#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(' ')); $('#anki-card-tags').val(opts.ankiCardTags.join(' '));
$('#sentence-extent').val(opts.sentenceExtent); $('#sentence-extent').val(opts.sentenceExtent);
$('#anki-method').change(onOptionsAnkiChanged);
$('.options-basic input').change(onOptionsBasicChanged); $('.options-basic input').change(onOptionsBasicChanged);
$('.options-anki input').change(onOptionsAnkiChanged); $('.options-anki input').change(onOptionsAnkiChanged);
$('.anki-deck').change(onOptionsAnkiChanged); $('.anki-deck').change(onOptionsAnkiChanged);

View File

@ -27,6 +27,10 @@ function sanitizeOptions(options) {
holdShiftToScan: true, holdShiftToScan: true,
scanDelay: 15, scanDelay: 15,
scanLength: 20, scanLength: 20,
ankiMethod: 'none',
ankiUsername: '',
ankiPassword: '',
ankiCardTags: ['yomichan'], ankiCardTags: ['yomichan'],
sentenceExtent: 200, sentenceExtent: 200,

View File

@ -23,7 +23,7 @@ class Yomichan {
Handlebars.registerHelper('kanjiLinks', kanjiLinks); Handlebars.registerHelper('kanjiLinks', kanjiLinks);
this.translator = new Translator(); this.translator = new Translator();
this.anki = new AnkiConnect(); this.anki = null;
this.options = null; this.options = null;
this.importTabId = null; this.importTabId = null;
this.setState('disabled'); this.setState('disabled');
@ -100,6 +100,19 @@ class Yomichan {
setOptions(options) { setOptions(options) {
this.options = options; this.options = options;
switch (options.ankiMethod) {
case 'ankiweb':
this.anki = new AnkiWeb(options.ankiUsername, options.ankiPassword);
break;
case 'ankiconnect':
this.anki = new AnkiConnect();
break;
default:
this.anki = null;
break;
}
this.tabInvokeAll('setOptions', this.options); this.tabInvokeAll('setOptions', this.options);
} }
@ -238,45 +251,66 @@ class Yomichan {
} }
api_addDefinition({definition, mode, callback}) { api_addDefinition({definition, mode, callback}) {
const note = this.formatNote(definition, mode); if (this.anki === null) {
this.anki.addNote(note).then(callback); callback(null);
} else {
const note = this.formatNote(definition, mode);
this.anki.addNote(note).then(callback);
}
} }
api_canAddDefinitions({definitions, modes, callback}) { api_canAddDefinitions({definitions, modes, callback}) {
const notes = []; if (this.anki === null) {
for (const definition of definitions) { callback(null);
for (const mode of modes) {
notes.push(this.formatNote(definition, mode));
}
} }
else {
this.anki.canAddNotes(notes).then(results => { const notes = [];
const states = []; for (const definition of definitions) {
if (results !== null) { for (const mode of modes) {
for (let resultBase = 0; resultBase < results.length; resultBase += modes.length) { notes.push(this.formatNote(definition, mode));
const state = {};
for (let modeOffset = 0; modeOffset < modes.length; ++modeOffset) {
state[modes[modeOffset]] = results[resultBase + modeOffset];
}
states.push(state);
} }
} }
callback(states); this.anki.canAddNotes(notes).then(results => {
}); const states = [];
if (results !== null) {
for (let resultBase = 0; resultBase < results.length; resultBase += modes.length) {
const state = {};
for (let modeOffset = 0; modeOffset < modes.length; ++modeOffset) {
state[modes[modeOffset]] = results[resultBase + modeOffset];
}
states.push(state);
}
}
callback(states);
});
}
} }
api_getDeckNames({callback}) { api_getDeckNames({callback}) {
this.anki.getDeckNames().then(callback); if (this.anki === null) {
callback(null);
} else {
this.anki.getDeckNames().then(callback);
}
} }
api_getModelNames({callback}) { api_getModelNames({callback}) {
this.anki.getModelNames().then(callback); if (this.anki === null) {
callback(null);
} else {
this.anki.getModelNames().then(callback);
}
} }
api_getModelFieldNames({modelName, callback}) { api_getModelFieldNames({modelName, callback}) {
this.anki.getModelFieldNames(modelName).then(callback); if (this.anki === null) {
callback(null);
} else {
this.anki.getModelFieldNames(modelName).then(callback);
}
} }
} }

View File

@ -97,6 +97,15 @@
<div class="options-anki"> <div class="options-anki">
<h3>Anki Options</h3> <h3>Anki Options</h3>
<div class="form-group">
<label class="control-label" for="anki-method">Integration method</label>
<select class="form-control" id="anki-method">
<option value="none">None</option>
<option value="ankiweb">AnkiWeb</option>
<option value="ankiconnect">AnkiConnect</option>
</select>
</div>
<div class="alert alert-danger error-dlg error-dlg-connection"> <div class="alert alert-danger error-dlg error-dlg-connection">
<strong>Unable to Connect</strong><br> <strong>Unable to Connect</strong><br>
Is the <a href="https://foosoft.net/projects/anki-connect">AnkiConnect</a> extension for <a href="http://ankisrs.net/">Anki</a> installed and running? This software is required for Anki-related features. Is the <a href="https://foosoft.net/projects/anki-connect">AnkiConnect</a> extension for <a href="http://ankisrs.net/">Anki</a> installed and running? This software is required for Anki-related features.
@ -107,6 +116,16 @@
</div> </div>
<form class="form-horizontal options-anki-controls"> <form class="form-horizontal options-anki-controls">
<div class="form-group">
<label for="anki-username" class="control-label col-sm-2">Username</label>
<div class="col-sm-10"><input type="text" id="anki-username" class="form-control"></div>
</div>
<div class="form-group">
<label for="anki-password" class="control-label col-sm-2">Password</label>
<div class="col-sm-10"><input type="password" id="anki-password" class="form-control"></div>
</div>
<div class="form-group"> <div class="form-group">
<label for="anki-card-tags" class="control-label col-sm-2">Card tags</label> <label for="anki-card-tags" class="control-label col-sm-2">Card tags</label>
<div class="col-sm-10"><input type="text" id="anki-card-tags" class="form-control"></div> <div class="col-sm-10"><input type="text" id="anki-card-tags" class="form-control"></div>