diff options
Diffstat (limited to 'ext/bg/js/settings')
-rw-r--r-- | ext/bg/js/settings/anki.js | 10 | ||||
-rw-r--r-- | ext/bg/js/settings/audio.js | 9 | ||||
-rw-r--r-- | ext/bg/js/settings/backup.js | 2 | ||||
-rw-r--r-- | ext/bg/js/settings/conditions-ui.js | 163 | ||||
-rw-r--r-- | ext/bg/js/settings/dictionaries.js | 32 | ||||
-rw-r--r-- | ext/bg/js/settings/main.js | 23 | ||||
-rw-r--r-- | ext/bg/js/settings/popup-preview-frame-main.js | 26 | ||||
-rw-r--r-- | ext/bg/js/settings/popup-preview-frame.js | 57 | ||||
-rw-r--r-- | ext/bg/js/settings/popup-preview.js | 23 | ||||
-rw-r--r-- | ext/bg/js/settings/profiles.js | 14 |
10 files changed, 285 insertions, 74 deletions
diff --git a/ext/bg/js/settings/anki.js b/ext/bg/js/settings/anki.js index b32a9517..ff1277ed 100644 --- a/ext/bg/js/settings/anki.js +++ b/ext/bg/js/settings/anki.js @@ -16,13 +16,13 @@ */ /* global + * apiGetAnkiDeckNames + * apiGetAnkiModelFieldNames + * apiGetAnkiModelNames * getOptionsContext * getOptionsMutable * onFormOptionsChanged * settingsSaveOptions - * utilAnkiGetDeckNames - * utilAnkiGetModelFieldNames - * utilAnkiGetModelNames * utilBackgroundIsolate */ @@ -107,7 +107,7 @@ async function _ankiDeckAndModelPopulate(options) { const kanjiModel = {value: options.anki.kanji.model, selector: '#anki-kanji-model'}; try { _ankiSpinnerShow(true); - const [deckNames, modelNames] = await Promise.all([utilAnkiGetDeckNames(), utilAnkiGetModelNames()]); + const [deckNames, modelNames] = await Promise.all([apiGetAnkiDeckNames(), apiGetAnkiModelNames()]); deckNames.sort(); modelNames.sort(); termsDeck.values = deckNames; @@ -180,7 +180,7 @@ async function _onAnkiModelChanged(e) { let fieldNames; try { const modelName = node.value; - fieldNames = await utilAnkiGetModelFieldNames(modelName); + fieldNames = await apiGetAnkiModelFieldNames(modelName); _ankiSetError(null); } catch (error) { _ankiSetError(error); diff --git a/ext/bg/js/settings/audio.js b/ext/bg/js/settings/audio.js index 3c6e126c..ac2d82f3 100644 --- a/ext/bg/js/settings/audio.js +++ b/ext/bg/js/settings/audio.js @@ -18,7 +18,6 @@ /* global * AudioSourceUI * AudioSystem - * apiAudioGetUri * getOptionsContext * getOptionsMutable * settingsSaveOptions @@ -29,10 +28,8 @@ let audioSystem = null; async function audioSettingsInitialize() { audioSystem = new AudioSystem({ - getAudioUri: async (definition, source) => { - const optionsContext = getOptionsContext(); - return await apiAudioGetUri(definition, source, optionsContext); - } + audioUriBuilder: null, + useCache: true }); const optionsContext = getOptionsContext(); @@ -115,7 +112,7 @@ function textToSpeechTest() { const text = document.querySelector('#text-to-speech-voice-test').dataset.speechText || ''; const voiceUri = document.querySelector('#text-to-speech-voice').value; - const audio = audioSystem.createTextToSpeechAudio({text, voiceUri}); + const audio = audioSystem.createTextToSpeechAudio(text, voiceUri); audio.volume = 1.0; audio.play(); } catch (e) { diff --git a/ext/bg/js/settings/backup.js b/ext/bg/js/settings/backup.js index bdfef658..faf4e592 100644 --- a/ext/bg/js/settings/backup.js +++ b/ext/bg/js/settings/backup.js @@ -133,7 +133,7 @@ async function _settingsImportSetOptionsFull(optionsFull) { } function _showSettingsImportError(error) { - logError(error); + yomichan.logError(error); document.querySelector('#settings-import-error-modal-message').textContent = `${error}`; $('#settings-import-error-modal').modal('show'); } diff --git a/ext/bg/js/settings/conditions-ui.js b/ext/bg/js/settings/conditions-ui.js index 84498b42..031689a7 100644 --- a/ext/bg/js/settings/conditions-ui.js +++ b/ext/bg/js/settings/conditions-ui.js @@ -16,6 +16,7 @@ */ /* global + * DOM * conditionsNormalizeOptionValue */ @@ -103,11 +104,11 @@ ConditionsUI.Container = class Container { if (hasOwn(conditionDescriptor.operators, operator)) { const operatorDescriptor = conditionDescriptor.operators[operator]; if (hasOwn(operatorDescriptor, 'defaultValue')) { - return {value: operatorDescriptor.defaultValue, fromOperator: true}; + return {value: this.isolate(operatorDescriptor.defaultValue), fromOperator: true}; } } if (hasOwn(conditionDescriptor, 'defaultValue')) { - return {value: conditionDescriptor.defaultValue, fromOperator: false}; + return {value: this.isolate(conditionDescriptor.defaultValue), fromOperator: false}; } } return {fromOperator: false}; @@ -177,7 +178,8 @@ ConditionsUI.Condition = class Condition { this.parent = parent; this.condition = condition; this.container = ConditionsUI.instantiateTemplate('#condition-template').appendTo(parent.container); - this.input = this.container.find('input'); + this.input = this.container.find('.condition-input'); + this.inputInner = null; this.typeSelect = this.container.find('.condition-type'); this.operatorSelect = this.container.find('.condition-operator'); this.removeButton = this.container.find('.condition-remove'); @@ -186,14 +188,13 @@ ConditionsUI.Condition = class Condition { this.updateOperators(); this.updateInput(); - this.input.on('change', this.onInputChanged.bind(this)); this.typeSelect.on('change', this.onConditionTypeChanged.bind(this)); this.operatorSelect.on('change', this.onConditionOperatorChanged.bind(this)); this.removeButton.on('click', this.onRemoveClicked.bind(this)); } cleanup() { - this.input.off('change'); + this.inputInner.off('change'); this.typeSelect.off('change'); this.operatorSelect.off('change'); this.removeButton.off('click'); @@ -204,6 +205,10 @@ ConditionsUI.Condition = class Condition { this.parent.save(); } + isolate(object) { + return this.parent.isolate(object); + } + updateTypes() { const conditionDescriptors = this.parent.parent.conditionDescriptors; const optionGroup = this.typeSelect.find('optgroup'); @@ -236,21 +241,48 @@ ConditionsUI.Condition = class Condition { updateInput() { const conditionDescriptors = this.parent.parent.conditionDescriptors; const {type, operator} = this.condition; - const props = new Map([ - ['placeholder', ''], - ['type', 'text'] - ]); const objects = []; + let inputType = null; if (hasOwn(conditionDescriptors, type)) { const conditionDescriptor = conditionDescriptors[type]; objects.push(conditionDescriptor); + if (hasOwn(conditionDescriptor, 'type')) { + inputType = conditionDescriptor.type; + } if (hasOwn(conditionDescriptor.operators, operator)) { const operatorDescriptor = conditionDescriptor.operators[operator]; objects.push(operatorDescriptor); + if (hasOwn(operatorDescriptor, 'type')) { + inputType = operatorDescriptor.type; + } } } + this.input.empty(); + if (inputType === 'select') { + this.inputInner = this.createSelectElement(objects); + } else if (inputType === 'keyMulti') { + this.inputInner = this.createInputKeyMultiElement(objects); + } else { + this.inputInner = this.createInputElement(objects); + } + this.inputInner.appendTo(this.input); + this.inputInner.on('change', this.onInputChanged.bind(this)); + + const {valid, value} = this.validateValue(this.condition.value); + this.inputInner.toggleClass('is-invalid', !valid); + this.inputInner.val(value); + } + + createInputElement(objects) { + const inputInner = ConditionsUI.instantiateTemplate('#condition-input-text-template'); + + const props = new Map([ + ['placeholder', ''], + ['type', 'text'] + ]); + for (const object of objects) { if (hasOwn(object, 'placeholder')) { props.set('placeholder', object.placeholder); @@ -266,35 +298,124 @@ ConditionsUI.Condition = class Condition { } for (const [prop, value] of props.entries()) { - this.input.prop(prop, value); + inputInner.prop(prop, value); } - const {valid} = this.validateValue(this.condition.value); - this.input.toggleClass('is-invalid', !valid); - this.input.val(this.condition.value); + return inputInner; } - validateValue(value) { + createInputKeyMultiElement(objects) { + const inputInner = this.createInputElement(objects); + + inputInner.prop('readonly', true); + + let values = []; + let keySeparator = ' + '; + for (const object of objects) { + if (hasOwn(object, 'values')) { + values = object.values; + } + if (hasOwn(object, 'keySeparator')) { + keySeparator = object.keySeparator; + } + } + + const pressedKeyIndices = new Set(); + + const onKeyDown = ({originalEvent}) => { + const pressedKeyEventName = DOM.getKeyFromEvent(originalEvent); + if (pressedKeyEventName === 'Escape' || pressedKeyEventName === 'Backspace') { + pressedKeyIndices.clear(); + inputInner.val(''); + inputInner.change(); + return; + } + + const pressedModifiers = DOM.getActiveModifiers(originalEvent); + // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/metaKey + // https://askubuntu.com/questions/567731/why-is-shift-alt-being-mapped-to-meta + // It works with mouse events on some platforms, so try to determine if metaKey is pressed + // hack; only works when Shift and Alt are not pressed + const isMetaKeyChrome = ( + pressedKeyEventName === 'Meta' && + getSetDifference(new Set(['shift', 'alt']), pressedModifiers).size !== 0 + ); + if (isMetaKeyChrome) { + pressedModifiers.add('meta'); + } + + for (const modifier of pressedModifiers) { + const foundIndex = values.findIndex(({optionValue}) => optionValue === modifier); + if (foundIndex !== -1) { + pressedKeyIndices.add(foundIndex); + } + } + + const inputValue = [...pressedKeyIndices].map((i) => values[i].name).join(keySeparator); + inputInner.val(inputValue); + inputInner.change(); + }; + + inputInner.on('keydown', onKeyDown); + + return inputInner; + } + + createSelectElement(objects) { + const inputInner = ConditionsUI.instantiateTemplate('#condition-input-select-template'); + + const data = new Map([ + ['values', []], + ['defaultValue', null] + ]); + + for (const object of objects) { + if (hasOwn(object, 'values')) { + data.set('values', object.values); + } + if (hasOwn(object, 'defaultValue')) { + data.set('defaultValue', this.isolate(object.defaultValue)); + } + } + + for (const {optionValue, name} of data.get('values')) { + const option = ConditionsUI.instantiateTemplate('#condition-input-option-template'); + option.attr('value', optionValue); + option.text(name); + option.appendTo(inputInner); + } + + const defaultValue = data.get('defaultValue'); + if (defaultValue !== null) { + inputInner.val(this.isolate(defaultValue)); + } + + return inputInner; + } + + validateValue(value, isInput=false) { const conditionDescriptors = this.parent.parent.conditionDescriptors; let valid = true; + let inputTransformedValue = null; try { - value = conditionsNormalizeOptionValue( + [value, inputTransformedValue] = conditionsNormalizeOptionValue( conditionDescriptors, this.condition.type, this.condition.operator, - value + value, + isInput ); } catch (e) { valid = false; } - return {valid, value}; + return {valid, value, inputTransformedValue}; } onInputChanged() { - const {valid, value} = this.validateValue(this.input.val()); - this.input.toggleClass('is-invalid', !valid); - this.input.val(value); - this.condition.value = value; + const {valid, value, inputTransformedValue} = this.validateValue(this.inputInner.val(), true); + this.inputInner.toggleClass('is-invalid', !valid); + this.inputInner.val(value); + this.condition.value = inputTransformedValue !== null ? inputTransformedValue : value; this.save(); } diff --git a/ext/bg/js/settings/dictionaries.js b/ext/bg/js/settings/dictionaries.js index 1a6d452b..632c01ea 100644 --- a/ext/bg/js/settings/dictionaries.js +++ b/ext/bg/js/settings/dictionaries.js @@ -17,8 +17,13 @@ /* global * PageExitPrevention + * apiDeleteDictionary + * apiGetDictionaryCounts + * apiGetDictionaryInfo + * apiImportDictionaryArchive * apiOptionsGet * apiOptionsGetFull + * apiPurgeDatabase * getOptionsContext * getOptionsFullMutable * getOptionsMutable @@ -26,11 +31,6 @@ * storageEstimate * storageUpdateStats * utilBackgroundIsolate - * utilDatabaseDeleteDictionary - * utilDatabaseGetDictionaryCounts - * utilDatabaseGetDictionaryInfo - * utilDatabaseImport - * utilDatabasePurge */ let dictionaryUI = null; @@ -312,7 +312,7 @@ class SettingsDictionaryEntryUI { progressBar.style.width = `${percent}%`; }; - await utilDatabaseDeleteDictionary(this.dictionaryInfo.title, onProgress, {rate: 1000}); + await apiDeleteDictionary(this.dictionaryInfo.title, onProgress); } catch (e) { dictionaryErrorsShow([e]); } finally { @@ -431,7 +431,7 @@ async function onDictionaryOptionsChanged() { async function onDatabaseUpdated() { try { - const dictionaries = await utilDatabaseGetDictionaryInfo(); + const dictionaries = await apiGetDictionaryInfo(); dictionaryUI.setDictionaries(dictionaries); document.querySelector('#dict-warning').hidden = (dictionaries.length > 0); @@ -439,7 +439,7 @@ async function onDatabaseUpdated() { updateMainDictionarySelectOptions(dictionaries); await updateMainDictionarySelectValue(); - const {counts, total} = await utilDatabaseGetDictionaryCounts(dictionaries.map((v) => v.title), true); + const {counts, total} = await apiGetDictionaryCounts(dictionaries.map((v) => v.title), true); dictionaryUI.setCounts(counts, total); } catch (e) { dictionaryErrorsShow([e]); @@ -554,7 +554,7 @@ function dictionaryErrorsShow(errors) { if (errors !== null && errors.length > 0) { const uniqueErrors = new Map(); for (let e of errors) { - logError(e); + yomichan.logError(e); e = dictionaryErrorToString(e); let count = uniqueErrors.get(e); if (typeof count === 'undefined') { @@ -618,7 +618,7 @@ async function onDictionaryPurge(e) { dictionaryErrorsShow(null); dictionarySpinnerShow(true); - await utilDatabasePurge(); + await apiPurgeDatabase(); for (const {options} of toIterable((await getOptionsFullMutable()).profiles)) { options.dictionaries = utilBackgroundIsolate({}); options.general.mainDictionary = ''; @@ -679,7 +679,8 @@ async function onDictionaryImport(e) { dictImportInfo.textContent = `(${i + 1} of ${ii})`; } - const {result, errors} = await utilDatabaseImport(files[i], updateProgress, importDetails); + const archiveContent = await dictReadFile(files[i]); + const {result, errors} = await apiImportDictionaryArchive(archiveContent, importDetails, updateProgress); for (const {options} of toIterable((await getOptionsFullMutable()).profiles)) { const dictionaryOptions = SettingsDictionaryListUI.createDictionaryOptions(); dictionaryOptions.enabled = true; @@ -713,6 +714,15 @@ async function onDictionaryImport(e) { } } +function dictReadFile(file) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = () => resolve(reader.result); + reader.onerror = () => reject(reader.error); + reader.readAsBinaryString(file); + }); +} + async function onDatabaseEnablePrefixWildcardSearchesChanged(e) { const optionsFull = await getOptionsFullMutable(); diff --git a/ext/bg/js/settings/main.js b/ext/bg/js/settings/main.js index 308e92eb..61395b1c 100644 --- a/ext/bg/js/settings/main.js +++ b/ext/bg/js/settings/main.js @@ -21,6 +21,8 @@ * ankiInitialize * ankiTemplatesInitialize * ankiTemplatesUpdateValue + * apiForwardLogsToBackend + * apiGetEnvironmentInfo * apiOptionsSave * appearanceInitialize * audioSettingsInitialize @@ -130,6 +132,7 @@ async function formRead(options) { options.anki.tags = utilBackgroundIsolate($('#card-tags').val().split(/[,; ]+/)); options.anki.sentenceExt = parseInt($('#sentence-detection-extent').val(), 10); options.anki.server = $('#interface-server').val(); + options.anki.duplicateScope = $('#duplicate-scope').val(); options.anki.screenshot.format = $('#screenshot-format').val(); options.anki.screenshot.quality = parseInt($('#screenshot-quality').val(), 10); @@ -211,6 +214,7 @@ async function formWrite(options) { $('#card-tags').val(options.anki.tags.join(' ')); $('#sentence-detection-extent').val(options.anki.sentenceExt); $('#interface-server').val(options.anki.server); + $('#duplicate-scope').val(options.anki.duplicateScope); $('#screenshot-format').val(options.anki.screenshot.format); $('#screenshot-quality').val(options.anki.screenshot.quality); @@ -282,12 +286,31 @@ function showExtensionInformation() { node.textContent = `${manifest.name} v${manifest.version}`; } +async function settingsPopulateModifierKeys() { + const scanModifierKeySelect = document.querySelector('#scan-modifier-key'); + scanModifierKeySelect.textContent = ''; + + const environment = await apiGetEnvironmentInfo(); + const modifierKeys = [ + {value: 'none', name: 'None'}, + ...environment.modifiers.keys + ]; + for (const {value, name} of modifierKeys) { + const option = document.createElement('option'); + option.value = value; + option.textContent = name; + scanModifierKeySelect.appendChild(option); + } +} + async function onReady() { + apiForwardLogsToBackend(); await yomichan.prepare(); showExtensionInformation(); + await settingsPopulateModifierKeys(); formSetupEventListeners(); appearanceInitialize(); await audioSettingsInitialize(); diff --git a/ext/bg/js/settings/popup-preview-frame-main.js b/ext/bg/js/settings/popup-preview-frame-main.js new file mode 100644 index 00000000..8228125f --- /dev/null +++ b/ext/bg/js/settings/popup-preview-frame-main.js @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019-2020 Yomichan Authors + * + * 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 <https://www.gnu.org/licenses/>. + */ + +/* global + * SettingsPopupPreview + * apiForwardLogsToBackend + */ + +(() => { + apiForwardLogsToBackend(); + new SettingsPopupPreview(); +})(); diff --git a/ext/bg/js/settings/popup-preview-frame.js b/ext/bg/js/settings/popup-preview-frame.js index fba114e2..8901a0c4 100644 --- a/ext/bg/js/settings/popup-preview-frame.js +++ b/ext/bg/js/settings/popup-preview-frame.js @@ -18,8 +18,9 @@ /* global * Frontend * Popup - * PopupProxyHost + * PopupFactory * TextSourceRange + * apiFrameInformationGet * apiOptionsGet */ @@ -32,46 +33,46 @@ class SettingsPopupPreview { this.popupShown = false; this.themeChangeTimeout = null; this.textSource = null; + this.optionsContext = null; this._targetOrigin = chrome.runtime.getURL('/').replace(/\/$/, ''); this._windowMessageHandlers = new Map([ + ['prepare', ({optionsContext}) => this.prepare(optionsContext)], ['setText', ({text}) => this.setText(text)], ['setCustomCss', ({css}) => this.setCustomCss(css)], - ['setCustomOuterCss', ({css}) => this.setCustomOuterCss(css)] + ['setCustomOuterCss', ({css}) => this.setCustomOuterCss(css)], + ['updateOptionsContext', ({optionsContext}) => this.updateOptionsContext(optionsContext)] ]); - } - static create() { - const instance = new SettingsPopupPreview(); - instance.prepare(); - return instance; + window.addEventListener('message', this.onMessage.bind(this), false); } - async prepare() { - // Setup events - window.addEventListener('message', this.onMessage.bind(this), false); + async prepare(optionsContext) { + this.optionsContext = optionsContext; + // Setup events document.querySelector('#theme-dark-checkbox').addEventListener('change', this.onThemeDarkCheckboxChanged.bind(this), false); // Overwrite API functions window.apiOptionsGet = this.apiOptionsGet.bind(this); // Overwrite frontend - const popupHost = new PopupProxyHost(); - await popupHost.prepare(); + const {frameId} = await apiFrameInformationGet(); + + const popupFactory = new PopupFactory(frameId); + await popupFactory.prepare(); - this.popup = popupHost.getOrCreatePopup(); + this.popup = popupFactory.getOrCreatePopup(); this.popup.setChildrenSupported(false); this.popupSetCustomOuterCssOld = this.popup.setCustomOuterCss; this.popup.setCustomOuterCss = this.popupSetCustomOuterCss.bind(this); this.frontend = new Frontend(this.popup); - - this.frontend.setEnabled = () => {}; - this.frontend.searchClear = () => {}; - + this.frontend.getOptionsContext = async () => this.optionsContext; await this.frontend.prepare(); + this.frontend.setDisabledOverride(true); + this.frontend.canClearSelection = false; // Update search this.updateSearch(); @@ -122,7 +123,7 @@ class SettingsPopupPreview { } this.themeChangeTimeout = setTimeout(() => { this.themeChangeTimeout = null; - this.frontend.popup.updateTheme(); + this.popup.updateTheme(); }, 300); } @@ -143,12 +144,18 @@ class SettingsPopupPreview { setCustomCss(css) { if (this.frontend === null) { return; } - this.frontend.popup.setCustomCss(css); + this.popup.setCustomCss(css); } setCustomOuterCss(css) { if (this.frontend === null) { return; } - this.frontend.popup.setCustomOuterCss(css, false); + this.popup.setCustomOuterCss(css, false); + } + + async updateOptionsContext(optionsContext) { + this.optionsContext = optionsContext; + await this.frontend.updateOptions(); + await this.updateSearch(); } async updateSearch() { @@ -163,23 +170,17 @@ class SettingsPopupPreview { const source = new TextSourceRange(range, range.toString(), null, null); try { - await this.frontend.onSearchSource(source, 'script'); - this.frontend.setCurrentTextSource(source); + await this.frontend.setTextSource(source); } finally { source.cleanup(); } this.textSource = source; await this.frontend.showContentCompleted(); - if (this.frontend.popup.isVisibleSync()) { + if (this.popup.isVisibleSync()) { this.popupShown = true; } this.setInfoVisible(!this.popupShown); } } - -SettingsPopupPreview.instance = SettingsPopupPreview.create(); - - - diff --git a/ext/bg/js/settings/popup-preview.js b/ext/bg/js/settings/popup-preview.js index 091872be..fdc3dd94 100644 --- a/ext/bg/js/settings/popup-preview.js +++ b/ext/bg/js/settings/popup-preview.js @@ -15,6 +15,10 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ +/* global + * getOptionsContext + * wanakana + */ function appearanceInitialize() { let previewVisible = false; @@ -37,7 +41,7 @@ function showAppearancePreview() { frame.src = '/bg/settings-popup-preview.html'; frame.id = 'settings-popup-preview-frame'; - window.wanakana.bind(text[0]); + wanakana.bind(text[0]); const targetOrigin = chrome.runtime.getURL('/').replace(/\/$/, ''); @@ -57,6 +61,23 @@ function showAppearancePreview() { frame.contentWindow.postMessage({action, params}, targetOrigin); }); + const updateOptionsContext = () => { + const action = 'updateOptionsContext'; + const params = { + optionsContext: getOptionsContext() + }; + frame.contentWindow.postMessage({action, params}, targetOrigin); + }; + yomichan.on('modifyingProfileChange', updateOptionsContext); + + frame.addEventListener('load', () => { + const action = 'prepare'; + const params = { + optionsContext: getOptionsContext() + }; + frame.contentWindow.postMessage({action, params}, targetOrigin); + }); + container.append(frame); buttonContainer.remove(); settings.css('display', ''); diff --git a/ext/bg/js/settings/profiles.js b/ext/bg/js/settings/profiles.js index 867b17aa..bdf5a13d 100644 --- a/ext/bg/js/settings/profiles.js +++ b/ext/bg/js/settings/profiles.js @@ -23,6 +23,7 @@ * getOptionsFullMutable * getOptionsMutable * profileConditionsDescriptor + * profileConditionsDescriptorPromise * settingsSaveOptions * utilBackgroundIsolate */ @@ -98,6 +99,7 @@ async function profileFormWrite(optionsFull) { profileConditionsContainer.cleanup(); } + await profileConditionsDescriptorPromise; profileConditionsContainer = new ConditionsUI.Container( profileConditionsDescriptor, 'popupLevel', @@ -128,7 +130,7 @@ function profileOptionsPopulateSelect(select, profiles, currentValue, ignoreIndi } async function profileOptionsUpdateTarget(optionsFull) { - profileFormWrite(optionsFull); + await profileFormWrite(optionsFull); const optionsContext = getOptionsContext(); const options = await getOptionsMutable(optionsContext); @@ -190,6 +192,8 @@ async function onTargetProfileChanged() { currentProfileIndex = index; await profileOptionsUpdateTarget(optionsFull); + + yomichan.trigger('modifyingProfileChange'); } async function onProfileAdd() { @@ -197,9 +201,13 @@ async function onProfileAdd() { const profile = utilBackgroundIsolate(optionsFull.profiles[currentProfileIndex]); profile.name = profileOptionsCreateCopyName(profile.name, optionsFull.profiles, 100); optionsFull.profiles.push(profile); + currentProfileIndex = optionsFull.profiles.length - 1; + await profileOptionsUpdateTarget(optionsFull); await settingsSaveOptions(); + + yomichan.trigger('modifyingProfileChange'); } async function onProfileRemove(e) { @@ -238,6 +246,8 @@ async function onProfileRemoveConfirm() { await profileOptionsUpdateTarget(optionsFull); await settingsSaveOptions(); + + yomichan.trigger('modifyingProfileChange'); } function onProfileNameChanged() { @@ -263,6 +273,8 @@ async function onProfileMove(offset) { await profileOptionsUpdateTarget(optionsFull); await settingsSaveOptions(); + + yomichan.trigger('modifyingProfileChange'); } async function onProfileCopy() { |