diff --git a/README.md b/README.md index 3971dd97..6a5c8671 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,11 @@ support and feedback encourages continued development of this tool. ## Basic Functionality ## -1. Left-click on the ![](https://foosoft.net/projects/yomichan-chrome/img/logo.png) icon to enable or disable Yomichan for the current browser instance. -2. Right-click on the ![](https://foosoft.net/projects/yomichan-chrome/img/logo.png) icon and select Options to open the Yomichan options page. -3. Import any dictionaries (bundled or custom) you wish to use for Kanji and term searches; none are imported by default. -4. Hold down Shift (or the middle mouse button) as you hover over text to see term definitions. -5. Resize the definitions window by dragging the bottom-left corner inwards or outwards to make it smaller or larger. -6. Click on Kanji in the definition window to view additional information about that character. -7. Click on the ![](https://foosoft.net/projects/yomichan-chrome/img/play-audio.png) icon to hear the term pronounced by a native speaker. +1. Click on the ![](https://foosoft.net/projects/yomichan-chrome/img/logo.png) icon in the browser toolbar to open the Yomichan options page. +2. Import the dictionaries (bundled or custom) you wish to use for term and Kanji searches. +3. Hold down Shift (or the middle mouse button) as you hover over text to see term definitions. +4. Click on the ![](https://foosoft.net/projects/yomichan-chrome/img/play-audio.png) icon to hear the term pronounced by a native speaker (if audio is available). +5. Click on Kanji in the definition window to view additional information about that character. ## Custom Dictionaries ## diff --git a/ext/bg/guide.html b/ext/bg/guide.html index 23704934..4b0835b8 100644 --- a/ext/bg/guide.html +++ b/ext/bg/guide.html @@ -3,8 +3,8 @@ Welcome to Yomichan! - - + +
@@ -23,11 +23,10 @@

    -
  1. Left-click on the icon to enable or disable Yomichan for the current browser instance.
  2. -
  3. Right-click on the icon and select Options to open the Yomichan options page.
  4. -
  5. Import any dictionaries (bundled or custom) you wish to use for Kanji and term searches; none are imported by default.
  6. +
  7. Click on the icon in the browser toolbar to open the Yomichan options page.
  8. +
  9. Import the dictionaries (bundled or custom) you wish to use for term and Kanji searches.
  10. Hold down Shift (or the middle mouse button) as you hover over text to see term definitions.
  11. -
  12. Resize the definitions window by dragging the bottom-left corner inwards or outwards to make it smaller or larger.
  13. +
  14. Click on the icon to hear the term pronounced by a native speaker (if audio is available).
  15. Click on Kanji in the definition window to view additional information about that character.
diff --git a/ext/bg/js/ankiconnect.js b/ext/bg/js/ankiconnect.js index d17f3268..3a6e3690 100644 --- a/ext/bg/js/ankiconnect.js +++ b/ext/bg/js/ankiconnect.js @@ -17,9 +17,10 @@ */ class AnkiConnect { - constructor() { + constructor(server) { + this.server = server; this.asyncPools = {}; - this.localVersion = 1; + this.localVersion = 2; this.remoteVersion = null; } @@ -50,8 +51,8 @@ class AnkiConnect { return this.ankiInvoke('version', {}, null).then(version => { this.remoteVersion = version; - if (this.remoteVersion !== this.localVersion) { - return Promise.reject('extension and plugin version mismatch'); + if (this.remoteVersion < this.localVersion) { + return Promise.reject('extension and plugin versions incompatible'); } }); } @@ -75,7 +76,7 @@ class AnkiConnect { } }); - xhr.open('POST', 'http://127.0.0.1:8765'); + xhr.open('POST', this.server); xhr.send(JSON.stringify({action, params})); }); } diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index cae96306..3b2bcfcb 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -45,7 +45,7 @@ class Database { terms: '++id,dictionary,expression,reading', kanji: '++,dictionary,character', tagMeta: '++,dictionary', - dictionaries: '++,title,version', + dictionaries: '++,title,version' }); return this.db.open(); @@ -155,82 +155,6 @@ class Database { return this.db.dictionaries.toArray(); } - deleteDictionary(title, callback) { - if (this.db === null) { - return Promise.reject('database not initialized'); - } - - return this.db.dictionaries.where('title').equals(title).first(info => { - if (!info) { - return; - } - - let termCounter = Promise.resolve(0); - if (info.hasTerms) { - termCounter = this.db.terms.where('dictionary').equals(title).count(); - } - - let kanjiCounter = Promise.resolve(0); - if (info.hasKanji) { - kanjiCounter = this.db.kanji.where('dictionary').equals(title).count(); - } - - return Promise.all([termCounter, kanjiCounter]).then(([termCount, kanjiCount]) => { - const rowLimit = 500; - const totalCount = termCount + kanjiCount; - let deletedCount = 0; - - let termDeleter = Promise.resolve(); - if (info.hasTerms) { - const termDeleterFunc = () => { - return this.db.terms.where('dictionary').equals(title).limit(rowLimit).delete().then(count => { - if (count === 0) { - return Promise.resolve(); - } - - deletedCount += count; - if (callback) { - callback(totalCount, deletedCount); - } - - return termDeleterFunc(); - }); - }; - - termDeleter = termDeleterFunc(); - } - - let kanjiDeleter = Promise.resolve(); - if (info.hasKanji) { - const kanjiDeleterFunc = () => { - return this.db.kanji.where('dictionary').equals(title).limit(rowLimit).delete().then(count => { - if (count === 0) { - return Promise.resolve(); - } - - deletedCount += count; - if (callback) { - callback(totalCount, deletedCount); - } - - return kanjiDeleterFunc(); - }); - }; - - kanjiDeleter = kanjiDeleterFunc(); - } - - return Promise.all([termDeleter, kanjiDeleter]); - }); - }).then(() => { - return this.db.tagMeta.where('dictionary').equals(title).delete(); - }).then(() => { - return this.db.dictionaries.where('title').equals(title).delete(); - }).then(() => { - delete this.cacheTagMeta[title]; - }); - } - importDictionary(indexUrl, callback) { if (this.db === null) { return Promise.reject('database not initialized'); diff --git a/ext/bg/js/options-form.js b/ext/bg/js/options-form.js index 92596773..ae0491a2 100644 --- a/ext/bg/js/options-form.js +++ b/ext/bg/js/options-form.js @@ -28,7 +28,7 @@ function getFormData() { return optionsLoad().then(optionsOld => { const optionsNew = $.extend(true, {}, optionsOld); - optionsNew.general.autoStart = $('#activate-on-startup').prop('checked'); + optionsNew.general.enable = $('#enable-search').prop('checked'); optionsNew.general.audioPlayback = $('#audio-playback-buttons').prop('checked'); optionsNew.general.groupResults = $('#group-terms-results').prop('checked'); optionsNew.general.softKatakana = $('#soft-katakana-search').prop('checked'); @@ -37,6 +37,7 @@ function getFormData() { 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); @@ -44,6 +45,7 @@ function getFormData() { 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(); @@ -85,7 +87,7 @@ $(document).ready(() => { Handlebars.partials = Handlebars.templates; optionsLoad().then(options => { - $('#activate-on-startup').prop('checked', options.general.autoStart); + $('#enable-search').prop('checked', options.general.enable); $('#audio-playback-buttons').prop('checked', options.general.audioPlayback); $('#group-terms-results').prop('checked', options.general.groupResults); $('#soft-katakana-search').prop('checked', options.general.softKatakana); @@ -94,6 +96,7 @@ $(document).ready(() => { $('#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); @@ -106,6 +109,7 @@ $(document).ready(() => { $('#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); @@ -164,11 +168,10 @@ function populateDictionaries(options) { ++dictCount; }); + updateVisibility(options); + $('.dict-enabled, .dict-priority').change(onOptionsChanged); - $('.dict-delete').click(onDictionaryDelete); - }).catch(error => { - showDictionaryError(error); - }).then(() => { + }).catch(showDictionaryError).then(() => { showDictionarySpinner(false); if (dictCount === 0) { dictWarning.show(); @@ -185,36 +188,17 @@ function onDictionaryPurge(e) { const dictControls = $('#dict-importer, #dict-groups').hide(); const dictProgress = $('#dict-purge-progress').show(); - return database().purge().catch(error => { - showDictionaryError(error); - }).then(() => { + return database().purge().catch(showDictionaryError).then(() => { showDictionarySpinner(false); dictControls.show(); dictProgress.hide(); - return optionsLoad().then(options => populateDictionaries(options)); - }); -} - -function onDictionaryDelete() { - showDictionaryError(null); - showDictionarySpinner(true); - - const dictGroup = $(this).closest('.dict-group'); - const dictProgress = dictGroup.find('.dict-delete-progress').show(); - const dictControls = dictGroup.find('.dict-group-controls').hide(); - const setProgress = percent => { - dictProgress.find('.progress-bar').css('width', `${percent}%`); - }; - - setProgress(0.0); - - database().deleteDictionary(dictGroup.data('title'), (total, current) => setProgress(current / total * 100.0)).catch(error => { - showDictionaryError(error); - }).then(() => { - showDictionarySpinner(false); - dictProgress.hide(); - dictControls.show(); - return optionsLoad().then(options => populateDictionaries(options)); + return optionsLoad(); + }).then(options => { + options.dictionaries = {}; + return optionsSave(options).then(() => { + populateDictionaries(options); + yomichan().setOptions(options); + }); }); } @@ -225,9 +209,7 @@ function onDictionaryImport() { 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}%`); - }; + const setProgress = percent => dictProgress.find('.progress-bar').css('width', `${percent}%`); setProgress(0.0); @@ -235,11 +217,7 @@ function onDictionaryImport() { database().importDictionary(dictUrl.val(), (total, current) => setProgress(current / total * 100.0)).then(summary => { options.dictionaries[summary.title] = {enabled: true, priority: 0}; return optionsSave(options).then(() => yomichan().setOptions(options)); - }).then(() => { - return populateDictionaries(options); - }).catch(error => { - showDictionaryError(error); - }).then(() => { + }).then(() => populateDictionaries(options)).catch(showDictionaryError).then(() => { showDictionarySpinner(false); dictProgress.hide(); dictImporter.show(); @@ -324,13 +302,7 @@ function populateAnkiDeckAndModel(options) { populateAnkiFields($('#anki-terms-model').val(options.anki.terms.model), options), populateAnkiFields($('#anki-kanji-model').val(options.anki.kanji.model), options) ]); - }).then(() => { - ankiFormat.show(); - }).catch(error => { - showAnkiError(error); - }).then(() => { - showAnkiSpinner(false); - }); + }).then(() => ankiFormat.show()).catch(showAnkiError).then(() => showAnkiSpinner(false)); } function populateAnkiFields(element, options) { @@ -345,7 +317,7 @@ function populateAnkiFields(element, options) { const markers = { 'terms': ['audio', 'dictionary', 'expression', 'furigana', 'glossary', 'reading', 'sentence', 'tags', 'url'], - 'kanji': ['character', 'dictionary', 'glossary', 'kunyomi', 'onyomi', 'url'] + 'kanji': ['character', 'dictionary', 'glossary', 'kunyomi', 'onyomi', 'sentence', 'tags', 'url'] }[tabId] || {}; return anki().getModelFieldNames(modelName).then(names => { @@ -380,11 +352,7 @@ function onAnkiModelChanged(e) { optionsNew.anki[tabId].fields = {}; populateAnkiFields(element, optionsNew).then(() => { optionsSave(optionsNew).then(() => yomichan().setOptions(optionsNew)); - }).catch(error => { - showAnkiError(error); - }).then(() => { - showAnkiSpinner(false); - }); + }).catch(showAnkiError).then(() => showAnkiSpinner(false)); }); } @@ -397,15 +365,16 @@ function onOptionsChanged(e) { return optionsSave(optionsNew).then(() => { yomichan().setOptions(optionsNew); updateVisibility(optionsNew); - if (optionsNew.anki.enable !== optionsOld.anki.enable) { + + const ankiUpdated = + optionsNew.anki.enable !== optionsOld.anki.enable || + optionsNew.anki.server !== optionsOld.anki.server; + + if (ankiUpdated) { showAnkiError(null); showAnkiSpinner(true); return populateAnkiDeckAndModel(optionsNew); } }); - }).catch(error => { - showAnkiError(error); - }).then(() => { - showAnkiSpinner(false); - }); + }).catch(showAnkiError).then(() => showAnkiSpinner(false)); } diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 25e0945c..7a47c702 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -20,7 +20,7 @@ function optionsSetDefaults(options) { const defaults = { general: { - autoStart: true, + enable: true, audioPlayback: true, groupResults: true, softKatakana: true, @@ -31,6 +31,7 @@ function optionsSetDefaults(options) { scanning: { requireShift: true, selectText: true, + imposter: true, delay: 15, length: 10 }, @@ -39,6 +40,7 @@ function optionsSetDefaults(options) { anki: { enable: false, + server: 'http://127.0.0.1:8765', tags: ['yomichan'], htmlCards: true, sentenceExt: 200, @@ -48,8 +50,8 @@ function optionsSetDefaults(options) { }; const combine = (target, source) => { - for (let key in source) { - if (!(key in target)) { + for (const key in source) { + if (!target.hasOwnProperty(key)) { target[key] = source[key]; } } @@ -67,14 +69,11 @@ function optionsSetDefaults(options) { function optionsVersion(options) { - const copy = (targetDict, targetKey, sourceDict, sourceKey) => { - targetDict[targetKey] = sourceDict.hasOwnProperty(sourceKey) ? sourceDict[sourceKey] : targetDict[targetKey]; - }; - - options.version = options.version || 0; const fixups = [ () => { - optionsSetDefaults(options); + const copy = (targetDict, targetKey, sourceDict, sourceKey) => { + targetDict[targetKey] = sourceDict.hasOwnProperty(sourceKey) ? sourceDict[sourceKey] : targetDict[targetKey]; + }; copy(options.general, 'autoStart', options, 'activateOnStartup'); copy(options.general, 'audioPlayback', options, 'enableAudioPlayback'); @@ -98,23 +97,7 @@ function optionsVersion(options) { copy(options.anki.kanji, 'model', options, 'ankiKanjiModel'); copy(options.anki.kanji, 'fields', options, 'ankiKanjiFields'); - const fixupFields = fields => { - const fixups = { - '{expression-furigana}': '{furigana}', - '{glossary-list}': '{glossary}' - }; - - for (let name in fields) { - for (let fixup in fixups) { - fields[name] = fields[name].replace(fixup, fixups[fixup]); - } - } - }; - - fixupFields(options.anki.terms.fields); - fixupFields(options.anki.kanji.fields); - - for (let title in options.dictionaries) { + for (const title in options.dictionaries) { const dictionary = options.dictionaries[title]; dictionary.enabled = dictionary.enableTerms || dictionary.enableKanji; dictionary.priority = 0; @@ -127,8 +110,8 @@ function optionsVersion(options) { '{glossary-list}': '{glossary}' }; - for (let name in fields) { - for (let fixup in fixups) { + for (const name in fields) { + for (const fixup in fixups) { fields[name] = fields[name].replace(fixup, fixups[fixup]); } } @@ -139,10 +122,13 @@ function optionsVersion(options) { } ]; - if (options.version < fixups.length) { - fixups[options.version](); - ++options.version; - optionsVersion(options); + optionsSetDefaults(options); + if (!options.hasOwnProperty('version')) { + options.version = fixups.length; + } + + while (options.version < fixups.length) { + fixups[options.version++](); } return options; diff --git a/ext/bg/js/templates.js b/ext/bg/js/templates.js index 01896aa6..5fb894c1 100644 --- a/ext/bg/js/templates.js +++ b/ext/bg/js/templates.js @@ -11,13 +11,9 @@ templates['dictionary.html'] = template({"1":function(container,depth0,helpers,p + alias4(((helper = (helper = helpers.title || (depth0 != null ? depth0.title : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"title","hash":{},"data":data}) : helper))) + " rev." + alias4(((helper = (helper = helpers.revision || (depth0 != null ? depth0.revision : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"revision","hash":{},"data":data}) : helper))) - + "\n\n \n \n \n \n \n \n \n \n\n
\n Dictionary data is being deleted, please be patient...\n
\n
\n
\n
\n\n
\n
"; },"66":function(container,depth0,helpers,partials,data) { var stack1; - return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.html : depth0),{"name":"if","hash":{},"fn":container.program(67, data, 0),"inverse":container.program(69, data, 0),"data":data})) != null ? stack1 : ""); -},"67":function(container,depth0,helpers,partials,data) { + return ((stack1 = helpers.each.call(depth0 != null ? depth0 : {},((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.kunyomi : stack1),{"name":"each","hash":{},"fn":container.program(18, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"68":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = helpers.each.call(depth0 != null ? depth0 : {},((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.onyomi : stack1),{"name":"each","hash":{},"fn":container.program(18, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"70":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.modeTermKana : depth0),{"name":"unless","hash":{},"fn":container.program(28, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"72":function(container,depth0,helpers,partials,data) { + var stack1; + + return container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.sentence : stack1), depth0)); +},"74":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = helpers.each.call(depth0 != null ? depth0 : {},((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.tags : stack1),{"name":"each","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"76":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.html : depth0),{"name":"if","hash":{},"fn":container.program(77, data, 0),"inverse":container.program(79, data, 0),"data":data})) != null ? stack1 : ""); +},"77":function(container,depth0,helpers,partials,data) { var stack1, alias1=container.lambda, alias2=container.escapeExpression; return "" + alias2(alias1(((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.url : stack1), depth0)) + ""; -},"69":function(container,depth0,helpers,partials,data) { +},"79":function(container,depth0,helpers,partials,data) { var stack1; return container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.definition : depth0)) != null ? stack1.url : stack1), depth0)); @@ -245,12 +271,12 @@ templates['fields.html'] = template({"1":function(container,depth0,helpers,parti fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(26, data, 0, blockParams, depths),"inverse":container.noop,"args":["expression"],"data":data}) || fn; fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(32, data, 0, blockParams, depths),"inverse":container.noop,"args":["furigana"],"data":data}) || fn; fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(39, data, 0, blockParams, depths),"inverse":container.noop,"args":["glossary"],"data":data}) || fn; - fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(56, data, 0, blockParams, depths),"inverse":container.noop,"args":["kunyomi"],"data":data}) || fn; - fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(58, data, 0, blockParams, depths),"inverse":container.noop,"args":["onyomi"],"data":data}) || fn; - fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(60, data, 0, blockParams, depths),"inverse":container.noop,"args":["reading"],"data":data}) || fn; - fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(62, data, 0, blockParams, depths),"inverse":container.noop,"args":["sentence"],"data":data}) || fn; - fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(64, data, 0, blockParams, depths),"inverse":container.noop,"args":["tags"],"data":data}) || fn; - fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(66, data, 0, blockParams, depths),"inverse":container.noop,"args":["url"],"data":data}) || fn; + fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(66, data, 0, blockParams, depths),"inverse":container.noop,"args":["kunyomi"],"data":data}) || fn; + fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(68, data, 0, blockParams, depths),"inverse":container.noop,"args":["onyomi"],"data":data}) || fn; + fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(70, data, 0, blockParams, depths),"inverse":container.noop,"args":["reading"],"data":data}) || fn; + fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(72, data, 0, blockParams, depths),"inverse":container.noop,"args":["sentence"],"data":data}) || fn; + fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(74, data, 0, blockParams, depths),"inverse":container.noop,"args":["tags"],"data":data}) || fn; + fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(76, data, 0, blockParams, depths),"inverse":container.noop,"args":["url"],"data":data}) || fn; return fn; } diff --git a/ext/bg/js/yomichan.js b/ext/bg/js/yomichan.js index d7bf0e80..b1bf710f 100644 --- a/ext/bg/js/yomichan.js +++ b/ext/bg/js/yomichan.js @@ -26,18 +26,12 @@ class Yomichan { this.translator = new Translator(); this.anki = new AnkiNull(); this.options = null; - this.setEnabled(false); chrome.runtime.onMessage.addListener(this.onMessage.bind(this)); - chrome.browserAction.onClicked.addListener(this.onBrowserAction.bind(this)); chrome.runtime.onInstalled.addListener(this.onInstalled.bind(this)); + chrome.browserAction.onClicked.addListener(e => chrome.runtime.openOptionsPage()); - this.translator.prepare().then(optionsLoad).then(options => { - this.setOptions(options); - if (this.options.general.autoStart) { - this.setEnabled(true); - } - }); + this.translator.prepare().then(optionsLoad).then(this.setOptions.bind(this)); } onInstalled(details) { @@ -57,21 +51,28 @@ class Yomichan { return true; } - onBrowserAction() { - this.setEnabled(!this.enabled); - } - - setEnabled(enabled) { - this.enabled = enabled; - this.tabInvokeAll('setEnabled', this.enabled); - chrome.browserAction.setBadgeText({text: enabled ? '' : 'off'}); - } + // setEnabled(enabled) { + // this.enabled = enabled; + // this.tabInvokeAll('setEnabled', this.enabled); + // chrome.browserAction.setBadgeText({text: enabled ? '' : 'off'}); + // } setOptions(options) { this.options = options; + let usable = false; + for (const title in options.dictionaries) { + if (options.dictionaries[title].enabled) { + usable = true; + break; + } + } + + chrome.browserAction.setBadgeBackgroundColor({color: '#f0ad4e'}); + chrome.browserAction.setBadgeText({text: usable ? '' : '!'}); + if (options.anki.enable) { - this.anki = new AnkiConnect(); + this.anki = new AnkiConnect(this.options.anki.server); } else { this.anki = new AnkiNull(); } @@ -81,7 +82,7 @@ class Yomichan { tabInvokeAll(action, params) { chrome.tabs.query({}, tabs => { - for (let tab of tabs) { + for (const tab of tabs) { chrome.tabs.sendMessage(tab.id, {action, params}, () => null); } }); @@ -100,24 +101,27 @@ class Yomichan { note.deckName = this.options.anki.terms.deck; note.modelName = this.options.anki.terms.model; - const audio = { - kanji: definition.expression, - kana: definition.reading, - fields: [] - }; + if (definition.audio) { + const audio = { + url: definition.audio.url, + filename: definition.audio.filename, + skipHash: '7e2c2f954ef6051373ba916f000168dc', + fields: [] + }; - for (let name in fields) { - if (fields[name].includes('{audio}')) { - audio.fields.push(name); + for (const name in fields) { + if (fields[name].includes('{audio}')) { + audio.fields.push(name); + } } - } - if (audio.fields.length > 0) { - note.audio = audio; + if (audio.fields.length > 0) { + note.audio = audio; + } } } - for (let name in fields) { + for (const name in fields) { note.fields[name] = formatField( fields[name], definition, @@ -129,10 +133,6 @@ class Yomichan { return note; } - api_getEnabled({callback}) { - callback({result: this.enabled}); - } - api_getOptions({callback}) { promiseCallback(optionsLoad(), callback); } @@ -175,8 +175,8 @@ class Yomichan { api_canAddDefinitions({definitions, modes, callback}) { const notes = []; - for (let definition of definitions) { - for (let mode of modes) { + for (const definition of definitions) { + for (const mode of modes) { notes.push(this.formatNote(definition, mode)); } } diff --git a/ext/bg/legal.html b/ext/bg/legal.html index 16b32578..9be89f72 100644 --- a/ext/bg/legal.html +++ b/ext/bg/legal.html @@ -3,8 +3,8 @@ Yomichan Legal - - + +
diff --git a/ext/bg/options.html b/ext/bg/options.html index e5b0cbca..d6eeb121 100644 --- a/ext/bg/options.html +++ b/ext/bg/options.html @@ -3,11 +3,11 @@ Yomichan Options - - + +