diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index b8ef4362..9839aef5 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -17,16 +17,16 @@ */ -async function apiOptionsSet(options) { - utilBackend().onOptionsUpdated(options); -} - -async function apiOptionsGet() { +function apiOptionsGetSync() { return utilBackend().options; } +async function apiOptionsGet() { + return apiOptionsGetSync(); +} + async function apiTermsFind(text) { - const options = utilBackend().options; + const options = apiOptionsGetSync(); const translator = utilBackend().translator; const searcher = { @@ -48,13 +48,13 @@ async function apiTermsFind(text) { } async function apiKanjiFind(text) { - const options = utilBackend().options; + const options = apiOptionsGetSync(); const definitions = await utilBackend().translator.findKanji(text, dictEnabledSet(options)); return definitions.slice(0, options.general.maxResults); } async function apiDefinitionAdd(definition, mode, context) { - const options = utilBackend().options; + const options = apiOptionsGetSync(); if (mode !== 'kanji') { await audioInject( @@ -83,7 +83,7 @@ async function apiDefinitionsAddable(definitions, modes) { const notes = []; for (const definition of definitions) { for (const mode of modes) { - const note = await dictNoteFormat(definition, mode, utilBackend().options); + const note = await dictNoteFormat(definition, mode, apiOptionsGetSync()); notes.push(note); } } @@ -131,10 +131,9 @@ async function apiCommandExec(command) { }, toggle: async () => { - const options = utilBackend().options; + const options = apiOptionsGetSync(); options.general.enable = !options.general.enable; await optionsSave(options); - await apiOptionsSet(options); } }; diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 39fd4288..b3e737da 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -28,7 +28,7 @@ class Backend { async prepare() { await this.translator.prepare(); - await apiOptionsSet(await optionsLoad()); + this.onOptionsUpdated(await optionsLoad()); if (chrome.commands !== null && typeof chrome.commands === 'object') { chrome.commands.onCommand.addListener(this.onCommand.bind(this)); @@ -41,7 +41,8 @@ class Backend { } onOptionsUpdated(options) { - this.options = utilIsolate(options); + options = utilIsolate(options); + this.options = options; if (!options.general.enable) { this.setExtensionBadgeBackgroundColor('#555555'); @@ -53,16 +54,12 @@ class Backend { this.setExtensionBadgeText(''); } - if (options.anki.enable) { - this.anki = new AnkiConnect(options.anki.server); - } else { - this.anki = new AnkiNull(); - } + this.anki = options.anki.enable ? new AnkiConnect(options.anki.server) : new AnkiNull(); const callback = () => this.checkLastError(chrome.runtime.lastError); chrome.tabs.query({}, tabs => { for (const tab of tabs) { - chrome.tabs.sendMessage(tab.id, {action: 'optionsSet', params: options}, callback); + chrome.tabs.sendMessage(tab.id, {action: 'optionsSet', params: {options}}, callback); } }); } @@ -85,10 +82,6 @@ class Backend { forward(apiOptionsGet(), callback); }, - optionsSet: ({options, callback}) => { - forward(apiOptionsSet(options), callback); - }, - kanjiFind: ({text, callback}) => { forward(apiKanjiFind(text), callback); }, @@ -148,7 +141,7 @@ class Backend { chrome.browserAction.setBadgeBackgroundColor({color}); } } - + setExtensionBadgeText(text) { if (typeof chrome.browserAction.setBadgeText === 'function') { chrome.browserAction.setBadgeText({text}); diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index df95aae9..69c662e6 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -17,6 +17,57 @@ */ +function optionsApplyUpdates(options, updates) { + const targetVersion = updates.length; + const currentVersion = options.version; + if (typeof currentVersion === 'number' && Number.isFinite(currentVersion)) { + for (let i = Math.max(0, Math.floor(currentVersion)); i < targetVersion; ++i) { + const update = updates[i]; + if (update !== null) { + update(options); + } + } + } + + options.version = targetVersion; + return options; +} + +const optionsVersionUpdates = [ + null, + null, + null, + null, + (options) => { + options.general.audioSource = options.general.audioPlayback ? 'jpod101' : 'disabled'; + }, + (options) => { + options.general.showGuide = false; + }, + (options) => { + options.scanning.modifier = options.scanning.requireShift ? 'shift' : 'none'; + }, + (options) => { + const fieldTemplatesDefault = profileCreateDefaultFieldTemplates(); + options.general.resultOutputMode = options.general.groupResults ? 'group' : 'split'; + options.anki.fieldTemplates = ( + (utilStringHashCode(options.anki.fieldTemplates) !== -805327496) ? + `{{#if merge}}${fieldTemplatesDefault}{{else}}${options.anki.fieldTemplates}{{/if}}` : + fieldTemplatesDefault + ); + }, + (options) => { + if (utilStringHashCode(options.anki.fieldTemplates) === 1285806040) { + options.anki.fieldTemplates = profileCreateDefaultFieldTemplates(); + } + }, + (options) => { + if (utilStringHashCode(options.anki.fieldTemplates) === -250091611) { + options.anki.fieldTemplates = profileCreateDefaultFieldTemplates(); + } + } +]; + function optionsFieldTemplates() { return ` {{#*inline "glossary-single"}} @@ -183,8 +234,8 @@ function optionsFieldTemplates() { `.trim(); } -function optionsSetDefaults(options) { - const defaults = { +function optionsCreateDefaults() { + return { general: { enable: true, audioSource: 'jpod101', @@ -238,6 +289,10 @@ function optionsSetDefaults(options) { fieldTemplates: optionsFieldTemplates() } }; +} + +function optionsSetDefaults(options) { + const defaults = optionsCreateDefaults(); const combine = (target, source) => { for (const key in source) { @@ -258,70 +313,29 @@ function optionsSetDefaults(options) { } function optionsVersion(options) { - const fixups = [ - () => {}, - () => {}, - () => {}, - () => {}, - () => { - if (options.general.audioPlayback) { - options.general.audioSource = 'jpod101'; - } else { - options.general.audioSource = 'disabled'; - } - }, - () => { - options.general.showGuide = false; - }, - () => { - if (options.scanning.requireShift) { - options.scanning.modifier = 'shift'; - } else { - options.scanning.modifier = 'none'; - } - }, - () => { - if (options.general.groupResults) { - options.general.resultOutputMode = 'group'; - } else { - options.general.resultOutputMode = 'split'; - } - if (utilStringHashCode(options.anki.fieldTemplates) !== -805327496) { - options.anki.fieldTemplates = `{{#if merge}}${optionsFieldTemplates()}{{else}}${options.anki.fieldTemplates}{{/if}}`; - } else { - options.anki.fieldTemplates = optionsFieldTemplates(); - } - }, - () => { - if (utilStringHashCode(options.anki.fieldTemplates) === 1285806040) { - options.anki.fieldTemplates = optionsFieldTemplates(); - } - }, - () => { - if (utilStringHashCode(options.anki.fieldTemplates) === -250091611) { - options.anki.fieldTemplates = optionsFieldTemplates(); - } - } - ]; - optionsSetDefaults(options); - if (!options.hasOwnProperty('version')) { - options.version = fixups.length; - } - - while (options.version < fixups.length) { - fixups[options.version++](); - } - - return options; + return optionsApplyUpdates(options, optionsVersionUpdates); } function optionsLoad() { return new Promise((resolve, reject) => { - chrome.storage.local.get(null, store => resolve(store.options)); + chrome.storage.local.get(['options'], store => { + const error = chrome.runtime.lastError; + if (error) { + reject(error); + } else { + resolve(store.options); + } + }); }).then(optionsStr => { - return optionsStr ? JSON.parse(optionsStr) : {}; - }).catch(error => { + if (typeof optionsStr === 'string') { + const options = JSON.parse(optionsStr); + if (typeof options === 'object' && options !== null && !Array.isArray(options)) { + return options; + } + } + return {}; + }).catch(() => { return {}; }).then(options => { return optionsVersion(options); @@ -329,9 +343,9 @@ function optionsLoad() { } function optionsSave(options) { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { chrome.storage.local.set({options: JSON.stringify(options)}, resolve); }).then(() => { - apiOptionsSet(options); + utilBackend().onOptionsUpdated(options); }); } diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 85b7ee5f..ddda8303 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -30,6 +30,10 @@ padding-bottom: 1em; } + .label-light { + font-weight: normal; + } + #custom-popup-css { width: 100%; min-height: 34px; @@ -49,6 +53,16 @@ [data-browser=firefox-mobile] [data-show-for-browser~=firefox-mobile] { display: initial; } + + @media screen and (max-width: 740px) { + .col-xs-6 { + float: none; + width: 100%; + } + .col-xs-6+.col-xs-6 { + margin-top: 15px; + } + } @@ -107,6 +121,16 @@ +
+ + +
+ +
+ + +
+
@@ -130,36 +154,41 @@
- - -
- -
- - -
- -
-
-
-
+
+ + +
+
+ + +
-
-
-
+
+ + +
+
+ + +
-
-
-
+
+ + +
+
+ + +
@@ -205,12 +234,12 @@
- +
- +
@@ -326,12 +355,12 @@
- +
- +
@@ -349,7 +378,7 @@
- +
@@ -413,7 +442,7 @@ their Anki cards. If you encounter problems with your changes you can always reset to default template settings.

- +
diff --git a/ext/fg/js/api.js b/ext/fg/js/api.js index 6bcb0dbb..aa3b2629 100644 --- a/ext/fg/js/api.js +++ b/ext/fg/js/api.js @@ -17,10 +17,6 @@ */ -function apiOptionsSet(options) { - return utilInvoke('optionsSet', {options}); -} - function apiOptionsGet() { return utilInvoke('optionsGet'); } diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 079a7ef2..52620933 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -261,7 +261,7 @@ class Frontend { onBgMessage({action, params}, sender, callback) { const handlers = { - optionsSet: options => { + optionsSet: ({options}) => { this.options = options; if (!this.options.enable) { this.searchClear();