From a01ca1f17c056179ab9040bf702429fdd97742d6 Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Thu, 2 Mar 2017 21:01:49 -0800 Subject: renaming things to make more sense --- ext/bg/background.html | 29 ++- ext/bg/js/anki-connect.js | 84 +++++++++ ext/bg/js/anki-null.js | 40 ++++ ext/bg/js/ankiconnect.js | 83 --------- ext/bg/js/ankinull.js | 39 ---- ext/bg/js/database.js | 14 +- ext/bg/js/gecko.js | 1 + ext/bg/js/options-form.js | 366 ------------------------------------- ext/bg/js/options.js | 451 +++++++++++++++++++++++++++++++++------------- ext/bg/js/popup.js | 3 +- ext/bg/js/translator.js | 24 +-- ext/bg/js/util.js | 268 ++++++++++++++++++++++----- ext/bg/js/yomichan.js | 8 +- ext/bg/options.html | 1 - 14 files changed, 713 insertions(+), 698 deletions(-) create mode 100644 ext/bg/js/anki-connect.js create mode 100644 ext/bg/js/anki-null.js delete mode 100644 ext/bg/js/ankiconnect.js delete mode 100644 ext/bg/js/ankinull.js delete mode 100644 ext/bg/js/options-form.js (limited to 'ext/bg') diff --git a/ext/bg/background.html b/ext/bg/background.html index 625917ef..eecadf1e 100644 --- a/ext/bg/background.html +++ b/ext/bg/background.html @@ -1,18 +1,17 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/ext/bg/js/anki-connect.js b/ext/bg/js/anki-connect.js new file mode 100644 index 00000000..9759c8f5 --- /dev/null +++ b/ext/bg/js/anki-connect.js @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2016 Alex Yatskov + * Author: Alex Yatskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +class AnkiConnect { + constructor(server) { + this.server = server; + this.asyncPools = {}; + this.localVersion = 2; + this.remoteVersion = null; + } + + addNote(note) { + return this.checkVersion().then(() => this.ankiInvoke('addNote', {note}, null)); + } + + canAddNotes(notes) { + return this.checkVersion().then(() => this.ankiInvoke('canAddNotes', {notes}, 'notes')); + } + + getDeckNames() { + return this.checkVersion().then(() => this.ankiInvoke('deckNames', {}, null)); + } + + getModelNames() { + return this.checkVersion().then(() => this.ankiInvoke('modelNames', {}, null)); + } + + getModelFieldNames(modelName) { + return this.checkVersion().then(() => this.ankiInvoke('modelFieldNames', {modelName}, null)); + } + + checkVersion() { + if (this.localVersion === this.remoteVersion) { + return Promise.resolve(true); + } + + return this.ankiInvoke('version', {}, null).then(version => { + this.remoteVersion = version; + if (this.remoteVersion < this.localVersion) { + return Promise.reject('extension and plugin versions incompatible'); + } + }); + } + + ankiInvoke(action, params, pool) { + return new Promise((resolve, reject) => { + if (pool !== null && this.asyncPools.hasOwnProperty(pool)) { + this.asyncPools[pool].abort(); + } + + const xhr = new XMLHttpRequest(); + xhr.addEventListener('loadend', () => { + if (pool !== null) { + delete this.asyncPools[pool]; + } + + if (xhr.responseText) { + resolve(JSON.parse(xhr.responseText)); + } else { + reject('unable to connect to plugin'); + } + }); + + xhr.open('POST', this.server); + xhr.send(JSON.stringify({action, params})); + }); + } +} diff --git a/ext/bg/js/anki-null.js b/ext/bg/js/anki-null.js new file mode 100644 index 00000000..99dc2f30 --- /dev/null +++ b/ext/bg/js/anki-null.js @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2016 Alex Yatskov + * Author: Alex Yatskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +class AnkiNull { + addNote(note) { + return Promise.reject('unsupported action'); + } + + canAddNotes(notes) { + return Promise.resolve([]); + } + + getDeckNames() { + return Promise.resolve([]); + } + + getModelNames() { + return Promise.resolve([]); + } + + getModelFieldNames(modelName) { + return Promise.resolve([]); + } +} diff --git a/ext/bg/js/ankiconnect.js b/ext/bg/js/ankiconnect.js deleted file mode 100644 index 3a6e3690..00000000 --- a/ext/bg/js/ankiconnect.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2016 Alex Yatskov - * Author: Alex Yatskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -class AnkiConnect { - constructor(server) { - this.server = server; - this.asyncPools = {}; - this.localVersion = 2; - this.remoteVersion = null; - } - - addNote(note) { - return this.checkVersion().then(() => this.ankiInvoke('addNote', {note}, null)); - } - - canAddNotes(notes) { - return this.checkVersion().then(() => this.ankiInvoke('canAddNotes', {notes}, 'notes')); - } - - getDeckNames() { - return this.checkVersion().then(() => this.ankiInvoke('deckNames', {}, null)); - } - - getModelNames() { - return this.checkVersion().then(() => this.ankiInvoke('modelNames', {}, null)); - } - - getModelFieldNames(modelName) { - return this.checkVersion().then(() => this.ankiInvoke('modelFieldNames', {modelName}, null)); - } - - checkVersion() { - if (this.localVersion === this.remoteVersion) { - return Promise.resolve(true); - } - - return this.ankiInvoke('version', {}, null).then(version => { - this.remoteVersion = version; - if (this.remoteVersion < this.localVersion) { - return Promise.reject('extension and plugin versions incompatible'); - } - }); - } - - ankiInvoke(action, params, pool) { - return new Promise((resolve, reject) => { - if (pool !== null && this.asyncPools.hasOwnProperty(pool)) { - this.asyncPools[pool].abort(); - } - - const xhr = new XMLHttpRequest(); - xhr.addEventListener('loadend', () => { - if (pool !== null) { - delete this.asyncPools[pool]; - } - - if (xhr.responseText) { - resolve(JSON.parse(xhr.responseText)); - } else { - reject('unable to connect to plugin'); - } - }); - - xhr.open('POST', this.server); - xhr.send(JSON.stringify({action, params})); - }); - } -} diff --git a/ext/bg/js/ankinull.js b/ext/bg/js/ankinull.js deleted file mode 100644 index 0d0ed903..00000000 --- a/ext/bg/js/ankinull.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2016 Alex Yatskov - * Author: Alex Yatskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -class AnkiNull { - addNote(note) { - return Promise.reject('unsupported action'); - } - - canAddNotes(notes) { - return Promise.resolve([]); - } - - getDeckNames() { - return Promise.resolve([]); - } - - getModelNames() { - return Promise.resolve([]); - } - - getModelFieldNames(modelName) { - return Promise.resolve([]); - } -} diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index 31573065..51f639d9 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -76,8 +76,8 @@ class Database { results.push({ expression: row.expression, reading: row.reading, - tags: splitField(row.tags), - rules: splitField(row.rules), + tags: dictFieldSplit(row.tags), + rules: dictFieldSplit(row.rules), glossary: row.glossary, score: row.score, dictionary: row.dictionary, @@ -105,9 +105,9 @@ class Database { if (dictionaries.includes(row.dictionary)) { results.push({ character: row.character, - onyomi: splitField(row.onyomi), - kunyomi: splitField(row.kunyomi), - tags: splitField(row.tags), + onyomi: dictFieldSplit(row.onyomi), + kunyomi: dictFieldSplit(row.kunyomi), + tags: dictFieldSplit(row.tags), glossary: row.meanings, dictionary: row.dictionary }); @@ -172,7 +172,7 @@ class Database { const rows = []; for (const tag in tagMeta || {}) { const meta = tagMeta[tag]; - const row = sanitizeTag({ + const row = dictTagSanitize({ name: tag, category: meta.category, notes: meta.notes, @@ -229,6 +229,6 @@ class Database { }); }; - return importJsonDb(indexUrl, indexLoaded, termsLoaded, kanjiLoaded).then(() => summary); + return jsonLoadDb(indexUrl, indexLoaded, termsLoaded, kanjiLoaded).then(() => summary); } } diff --git a/ext/bg/js/gecko.js b/ext/bg/js/gecko.js index f195fffc..3df07f0b 100644 --- a/ext/bg/js/gecko.js +++ b/ext/bg/js/gecko.js @@ -20,6 +20,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + if (!chrome.storage.sync) { // https://bugzilla.mozilla.org/show_bug.cgi?id=1220494 chrome.storage.sync = chrome.storage.local; diff --git a/ext/bg/js/options-form.js b/ext/bg/js/options-form.js deleted file mode 100644 index c53c0c5e..00000000 --- a/ext/bg/js/options-form.js +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (C) 2016 Alex Yatskov - * Author: Alex Yatskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// -// General -// - -function getFormData() { - return optionsLoad().then(optionsOld => { - const optionsNew = $.extend(true, {}, optionsOld); - - optionsNew.general.audioPlayback = $('#audio-playback-buttons').prop('checked'); - optionsNew.general.groupResults = $('#group-terms-results').prop('checked'); - optionsNew.general.softKatakana = $('#soft-katakana-search').prop('checked'); - optionsNew.general.showAdvanced = $('#show-advanced-options').prop('checked'); - optionsNew.general.maxResults = parseInt($('#max-displayed-results').val(), 10); - - optionsNew.scanning.requireShift = $('#hold-shift-to-scan').prop('checked'); - optionsNew.scanning.selectText = $('#select-matched-text').prop('checked'); - optionsNew.scanning.imposter = $('#search-form-text-fields').prop('checked'); - optionsNew.scanning.delay = parseInt($('#scan-delay').val(), 10); - optionsNew.scanning.length = parseInt($('#scan-length').val(), 10); - - optionsNew.anki.enable = $('#anki-enable').prop('checked'); - optionsNew.anki.tags = $('#card-tags').val().split(/[,; ]+/); - optionsNew.anki.htmlCards = $('#generate-html-cards').prop('checked'); - optionsNew.anki.sentenceExt = parseInt($('#sentence-detection-extent').val(), 10); - optionsNew.anki.server = $('#interface-server').val(); - if (optionsOld.anki.enable) { - optionsNew.anki.terms.deck = $('#anki-terms-deck').val(); - optionsNew.anki.terms.model = $('#anki-terms-model').val(); - optionsNew.anki.terms.fields = ankiFieldsToDict($('#terms .anki-field-value')); - optionsNew.anki.kanji.deck = $('#anki-kanji-deck').val(); - optionsNew.anki.kanji.model = $('#anki-kanji-model').val(); - optionsNew.anki.kanji.fields = ankiFieldsToDict($('#kanji .anki-field-value')); - } - - $('.dict-group').each((index, element) => { - const dictionary = $(element); - const title = dictionary.data('title'); - const priority = parseInt(dictionary.find('.dict-priority').val(), 10); - const enabled = dictionary.find('.dict-enabled').prop('checked'); - optionsNew.dictionaries[title] = {priority, enabled}; - }); - - return {optionsNew, optionsOld}; - }); -} - -function updateVisibility(options) { - const general = $('#anki-general'); - if (options.anki.enable) { - general.show(); - } else { - general.hide(); - } - - const advanced = $('.options-advanced'); - if (options.general.showAdvanced) { - advanced.show(); - } else { - advanced.hide(); - } -} - -$(document).ready(() => { - Handlebars.partials = Handlebars.templates; - - optionsLoad().then(options => { - $('#audio-playback-buttons').prop('checked', options.general.audioPlayback); - $('#group-terms-results').prop('checked', options.general.groupResults); - $('#soft-katakana-search').prop('checked', options.general.softKatakana); - $('#show-advanced-options').prop('checked', options.general.showAdvanced); - $('#max-displayed-results').val(options.general.maxResults); - - $('#hold-shift-to-scan').prop('checked', options.scanning.requireShift); - $('#select-matched-text').prop('checked', options.scanning.selectText); - $('#search-form-text-fields').prop('checked', options.scanning.imposter); - $('#scan-delay').val(options.scanning.delay); - $('#scan-length').val(options.scanning.length); - - $('#dict-purge').click(onDictionaryPurge); - $('#dict-importer a').click(onDictionarySetUrl); - $('#dict-import').click(onDictionaryImport); - $('#dict-url').on('input', onDictionaryUpdateUrl); - - $('#anki-enable').prop('checked', options.anki.enable); - $('#card-tags').val(options.anki.tags.join(' ')); - $('#generate-html-cards').prop('checked', options.anki.htmlCards); - $('#sentence-detection-extent').val(options.anki.sentenceExt); - $('#interface-server').val(options.anki.server); - $('input, select').not('.anki-model').change(onOptionsChanged); - $('.anki-model').change(onAnkiModelChanged); - - populateDictionaries(options); - populateAnkiDeckAndModel(options); - updateVisibility(options); - }); -}); - -// -// Dictionary -// - -function showDictionaryError(error) { - const dialog = $('#dict-error'); - if (error) { - dialog.show().find('span').text(error); - } else { - dialog.hide(); - } -} - -function showDictionarySpinner(show) { - const spinner = $('#dict-spinner'); - if (show) { - spinner.show(); - } else { - spinner.hide(); - } -} - -function populateDictionaries(options) { - showDictionaryError(null); - showDictionarySpinner(true); - - const dictGroups = $('#dict-groups').empty(); - const dictWarning = $('#dict-warning').hide(); - - let dictCount = 0; - return getDatabase().getDictionaries().then(rows => { - rows.forEach(row => { - const dictOptions = options.dictionaries[row.title] || {enableTerms: false, enableKanji: false, priority: 0}; - const html = Handlebars.templates['dictionary.html']({ - title: row.title, - version: row.version, - revision: row.revision, - priority: dictOptions.priority, - enabled: dictOptions.enabled - }); - - dictGroups.append($(html)); - ++dictCount; - }); - - updateVisibility(options); - - $('.dict-enabled, .dict-priority').change(onOptionsChanged); - }).catch(showDictionaryError).then(() => { - showDictionarySpinner(false); - if (dictCount === 0) { - dictWarning.show(); - } - }); -} - -function onDictionaryPurge(e) { - e.preventDefault(); - - showDictionaryError(null); - showDictionarySpinner(true); - - const dictControls = $('#dict-importer, #dict-groups').hide(); - const dictProgress = $('#dict-purge-progress').show(); - - return getDatabase().purge().catch(showDictionaryError).then(() => { - showDictionarySpinner(false); - dictControls.show(); - dictProgress.hide(); - return optionsLoad(); - }).then(options => { - options.dictionaries = {}; - return optionsSave(options).then(() => { - populateDictionaries(options); - getYomichan().setOptions(options); - }); - }); -} - -function onDictionaryImport() { - showDictionaryError(null); - showDictionarySpinner(true); - - const dictUrl = $('#dict-url'); - const dictImporter = $('#dict-importer').hide(); - const dictProgress = $('#dict-import-progress').show(); - const setProgress = percent => dictProgress.find('.progress-bar').css('width', `${percent}%`); - - setProgress(0.0); - - optionsLoad().then(options => { - getDatabase().importDictionary(dictUrl.val(), (total, current) => setProgress(current / total * 100.0)).then(summary => { - options.dictionaries[summary.title] = {enabled: true, priority: 0}; - return optionsSave(options).then(() => getYomichan().setOptions(options)); - }).then(() => populateDictionaries(options)).catch(showDictionaryError).then(() => { - showDictionarySpinner(false); - dictProgress.hide(); - dictImporter.show(); - dictUrl.val(''); - dictUrl.trigger('input'); - }); - }); -} - -function onDictionarySetUrl(e) { - e.preventDefault(); - - const dictUrl = $('#dict-url'); - const url = $(this).data('url'); - if (url.includes('/')) { - dictUrl.val(url); - } else { - dictUrl.val(chrome.extension.getURL(`bg/lang/data/${url}/index.json`)); - } - - dictUrl.trigger('input'); -} - -function onDictionaryUpdateUrl() { - $('#dict-import').prop('disabled', $(this).val().length === 0); -} - -// -// Anki -// - -function showAnkiSpinner(show) { - const spinner = $('#anki-spinner'); - if (show) { - spinner.show(); - } else { - spinner.hide(); - } -} - -function showAnkiError(error) { - const dialog = $('#anki-error'); - if (error) { - dialog.show().find('span').text(error); - } - else { - dialog.hide(); - } -} - -function ankiFieldsToDict(selection) { - const result = {}; - selection.each((index, element) => { - result[$(element).data('field')] = $(element).val(); - }); - - return result; -} - -function populateAnkiDeckAndModel(options) { - showAnkiError(null); - showAnkiSpinner(true); - - const ankiFormat = $('#anki-format').hide(); - return Promise.all([getAnki().getDeckNames(), getAnki().getModelNames()]).then(([deckNames, modelNames]) => { - const ankiDeck = $('.anki-deck'); - ankiDeck.find('option').remove(); - deckNames.sort().forEach(name => ankiDeck.append($('