summaryrefslogtreecommitdiff
path: root/ext/bg/js/settings
diff options
context:
space:
mode:
Diffstat (limited to 'ext/bg/js/settings')
-rw-r--r--ext/bg/js/settings/anki-templates.js3
-rw-r--r--ext/bg/js/settings/anki.js28
-rw-r--r--ext/bg/js/settings/audio-ui.js1
-rw-r--r--ext/bg/js/settings/audio.js2
-rw-r--r--ext/bg/js/settings/backup.js5
-rw-r--r--ext/bg/js/settings/conditions-ui.js1
-rw-r--r--ext/bg/js/settings/dictionaries.js125
-rw-r--r--ext/bg/js/settings/main.js35
-rw-r--r--ext/bg/js/settings/popup-preview-frame.js34
-rw-r--r--ext/bg/js/settings/popup-preview.js8
-rw-r--r--ext/bg/js/settings/profiles.js4
-rw-r--r--ext/bg/js/settings/storage.js1
12 files changed, 166 insertions, 81 deletions
diff --git a/ext/bg/js/settings/anki-templates.js b/ext/bg/js/settings/anki-templates.js
index 5e74358f..2e80e334 100644
--- a/ext/bg/js/settings/anki-templates.js
+++ b/ext/bg/js/settings/anki-templates.js
@@ -16,6 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*global getOptionsContext, getOptionsMutable, settingsSaveOptions
+profileOptionsGetDefaultFieldTemplates, ankiGetFieldMarkers, ankiGetFieldMarkersHtml, dictFieldFormat
+apiOptionsGet, apiTermsFind*/
function onAnkiFieldTemplatesReset(e) {
e.preventDefault();
diff --git a/ext/bg/js/settings/anki.js b/ext/bg/js/settings/anki.js
index 9adb2f2a..4263fc51 100644
--- a/ext/bg/js/settings/anki.js
+++ b/ext/bg/js/settings/anki.js
@@ -16,6 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*global getOptionsContext, getOptionsMutable, settingsSaveOptions
+utilBackgroundIsolate, utilAnkiGetDeckNames, utilAnkiGetModelNames, utilAnkiGetModelFieldNames
+onFormOptionsChanged*/
// Private
@@ -33,14 +36,27 @@ function _ankiSpinnerShow(show) {
function _ankiSetError(error) {
const node = document.querySelector('#anki-error');
- if (!node) { return; }
+ const node2 = document.querySelector('#anki-invalid-response-error');
if (error) {
- node.hidden = false;
- node.textContent = `${error}`;
- _ankiSetErrorData(node, error);
+ const errorString = `${error}`;
+ if (node !== null) {
+ node.hidden = false;
+ node.textContent = errorString;
+ _ankiSetErrorData(node, error);
+ }
+
+ if (node2 !== null) {
+ node2.hidden = (errorString.indexOf('Invalid response') < 0);
+ }
} else {
- node.hidden = true;
- node.textContent = '';
+ if (node !== null) {
+ node.hidden = true;
+ node.textContent = '';
+ }
+
+ if (node2 !== null) {
+ node2.hidden = true;
+ }
}
}
diff --git a/ext/bg/js/settings/audio-ui.js b/ext/bg/js/settings/audio-ui.js
index 711c2291..555380b4 100644
--- a/ext/bg/js/settings/audio-ui.js
+++ b/ext/bg/js/settings/audio-ui.js
@@ -16,7 +16,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-
class AudioSourceUI {
static instantiateTemplate(templateSelector) {
const template = document.querySelector(templateSelector);
diff --git a/ext/bg/js/settings/audio.js b/ext/bg/js/settings/audio.js
index cff3f521..588d9a11 100644
--- a/ext/bg/js/settings/audio.js
+++ b/ext/bg/js/settings/audio.js
@@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*global getOptionsContext, getOptionsMutable, settingsSaveOptions
+AudioSourceUI, audioGetTextToSpeechVoice*/
let audioSourceUI = null;
diff --git a/ext/bg/js/settings/backup.js b/ext/bg/js/settings/backup.js
index becdc568..f4d622a4 100644
--- a/ext/bg/js/settings/backup.js
+++ b/ext/bg/js/settings/backup.js
@@ -16,6 +16,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*global apiOptionsGetFull, apiGetEnvironmentInfo
+utilBackend, utilIsolate, utilBackgroundIsolate, utilReadFileArrayBuffer
+optionsGetDefault, optionsUpdateVersion
+profileOptionsGetDefaultFieldTemplates*/
// Exporting
@@ -159,7 +163,6 @@ async function _showSettingsImportWarnings(warnings) {
sanitize: e.currentTarget.dataset.importSanitize === 'true'
});
modalNode.modal('hide');
-
};
const onModalHide = () => {
complete({result: false});
diff --git a/ext/bg/js/settings/conditions-ui.js b/ext/bg/js/settings/conditions-ui.js
index 4d041451..5a271321 100644
--- a/ext/bg/js/settings/conditions-ui.js
+++ b/ext/bg/js/settings/conditions-ui.js
@@ -16,6 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*global conditionsNormalizeOptionValue*/
class ConditionsUI {
static instantiateTemplate(templateSelector) {
diff --git a/ext/bg/js/settings/dictionaries.js b/ext/bg/js/settings/dictionaries.js
index ed171ae9..70a22a16 100644
--- a/ext/bg/js/settings/dictionaries.js
+++ b/ext/bg/js/settings/dictionaries.js
@@ -16,6 +16,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*global getOptionsContext, getOptionsMutable, getOptionsFullMutable, settingsSaveOptions, apiOptionsGetFull, apiOptionsGet
+utilBackgroundIsolate, utilDatabaseDeleteDictionary, utilDatabaseGetDictionaryInfo, utilDatabaseGetDictionaryCounts
+utilDatabasePurge, utilDatabaseImport
+storageUpdateStats, storageEstimate
+PageExitPrevention*/
let dictionaryUI = null;
@@ -161,7 +166,7 @@ class SettingsDictionaryListUI {
delete n.dataset.dict;
$(n).modal('hide');
- const index = this.dictionaryEntries.findIndex((e) => e.dictionaryInfo.title === title);
+ const index = this.dictionaryEntries.findIndex((entry) => entry.dictionaryInfo.title === title);
if (index >= 0) {
this.dictionaryEntries[index].deleteDictionary();
}
@@ -174,7 +179,7 @@ class SettingsDictionaryEntryUI {
this.dictionaryInfo = dictionaryInfo;
this.optionsDictionary = optionsDictionary;
this.counts = null;
- this.eventListeners = [];
+ this.eventListeners = new EventListenerCollection();
this.isDeleting = false;
this.content = content;
@@ -193,10 +198,10 @@ class SettingsDictionaryEntryUI {
this.applyValues();
- this.addEventListener(this.enabledCheckbox, 'change', (e) => this.onEnabledChanged(e), false);
- this.addEventListener(this.allowSecondarySearchesCheckbox, 'change', (e) => this.onAllowSecondarySearchesChanged(e), false);
- this.addEventListener(this.priorityInput, 'change', (e) => this.onPriorityChanged(e), false);
- this.addEventListener(this.deleteButton, 'click', (e) => this.onDeleteButtonClicked(e), false);
+ this.eventListeners.addEventListener(this.enabledCheckbox, 'change', (e) => this.onEnabledChanged(e), false);
+ this.eventListeners.addEventListener(this.allowSecondarySearchesCheckbox, 'change', (e) => this.onAllowSecondarySearchesChanged(e), false);
+ this.eventListeners.addEventListener(this.priorityInput, 'change', (e) => this.onPriorityChanged(e), false);
+ this.eventListeners.addEventListener(this.deleteButton, 'click', (e) => this.onDeleteButtonClicked(e), false);
}
cleanup() {
@@ -207,7 +212,7 @@ class SettingsDictionaryEntryUI {
this.content = null;
}
this.dictionaryInfo = null;
- this.clearEventListeners();
+ this.eventListeners.removeAllEventListeners();
}
setCounts(counts) {
@@ -224,18 +229,6 @@ class SettingsDictionaryEntryUI {
this.parent.save();
}
- addEventListener(node, type, listener, options) {
- node.addEventListener(type, listener, options);
- this.eventListeners.push([node, type, listener, options]);
- }
-
- clearEventListeners() {
- for (const [node, type, listener, options] of this.eventListeners) {
- node.removeEventListener(type, listener, options);
- }
- this.eventListeners = [];
- }
-
applyValues() {
this.enabledCheckbox.checked = this.optionsDictionary.enabled;
this.allowSecondarySearchesCheckbox.checked = this.optionsDictionary.allowSecondarySearches;
@@ -272,9 +265,7 @@ class SettingsDictionaryEntryUI {
this.isDeleting = false;
progress.hidden = true;
- const optionsContext = getOptionsContext();
- const options = await getOptionsMutable(optionsContext);
- onDatabaseUpdated(options);
+ onDatabaseUpdated();
}
}
@@ -359,28 +350,33 @@ async function dictSettingsInitialize() {
document.querySelector('#dict-main').addEventListener('change', (e) => onDictionaryMainChanged(e), false);
document.querySelector('#database-enable-prefix-wildcard-searches').addEventListener('change', (e) => onDatabaseEnablePrefixWildcardSearchesChanged(e), false);
- const optionsContext = getOptionsContext();
- const options = await getOptionsMutable(optionsContext);
- onDictionaryOptionsChanged(options);
- onDatabaseUpdated(options);
+ await onDictionaryOptionsChanged();
+ await onDatabaseUpdated();
}
-async function onDictionaryOptionsChanged(options) {
+async function onDictionaryOptionsChanged() {
if (dictionaryUI === null) { return; }
+
+ const optionsContext = getOptionsContext();
+ const options = await getOptionsMutable(optionsContext);
+
dictionaryUI.setOptionsDictionaries(options.dictionaries);
const optionsFull = await apiOptionsGetFull();
document.querySelector('#database-enable-prefix-wildcard-searches').checked = optionsFull.global.database.prefixWildcardsSupported;
+
+ await updateMainDictionarySelectValue();
}
-async function onDatabaseUpdated(options) {
+async function onDatabaseUpdated() {
try {
const dictionaries = await utilDatabaseGetDictionaryInfo();
dictionaryUI.setDictionaries(dictionaries);
document.querySelector('#dict-warning').hidden = (dictionaries.length > 0);
- updateMainDictionarySelect(options, dictionaries);
+ updateMainDictionarySelectOptions(dictionaries);
+ await updateMainDictionarySelectValue();
const {counts, total} = await utilDatabaseGetDictionaryCounts(dictionaries.map((v) => v.title), true);
dictionaryUI.setCounts(counts, total);
@@ -389,7 +385,7 @@ async function onDatabaseUpdated(options) {
}
}
-async function updateMainDictionarySelect(options, dictionaries) {
+function updateMainDictionarySelectOptions(dictionaries) {
const select = document.querySelector('#dict-main');
select.textContent = ''; // Empty
@@ -399,8 +395,6 @@ async function updateMainDictionarySelect(options, dictionaries) {
option.textContent = 'Not selected';
select.appendChild(option);
- let value = '';
- const currentValue = options.general.mainDictionary;
for (const {title, sequenced} of toIterable(dictionaries)) {
if (!sequenced) { continue; }
@@ -408,26 +402,56 @@ async function updateMainDictionarySelect(options, dictionaries) {
option.value = title;
option.textContent = title;
select.appendChild(option);
+ }
+}
+
+async function updateMainDictionarySelectValue() {
+ const optionsContext = getOptionsContext();
+ const options = await apiOptionsGet(optionsContext);
- if (title === currentValue) {
- value = title;
+ const value = options.general.mainDictionary;
+
+ const select = document.querySelector('#dict-main');
+ let selectValue = null;
+ for (const child of select.children) {
+ if (child.nodeName.toUpperCase() === 'OPTION' && child.value === value) {
+ selectValue = value;
+ break;
}
}
- select.value = value;
-
- if (options.general.mainDictionary !== value) {
- options.general.mainDictionary = value;
- settingsSaveOptions();
+ let missingNodeOption = select.querySelector('option[data-not-installed=true]');
+ if (selectValue === null) {
+ if (missingNodeOption === null) {
+ missingNodeOption = document.createElement('option');
+ missingNodeOption.className = 'text-muted';
+ missingNodeOption.value = value;
+ missingNodeOption.textContent = `${value} (Not installed)`;
+ missingNodeOption.dataset.notInstalled = 'true';
+ select.appendChild(missingNodeOption);
+ }
+ } else {
+ if (missingNodeOption !== null) {
+ missingNodeOption.parentNode.removeChild(missingNodeOption);
+ }
}
+
+ select.value = value;
}
async function onDictionaryMainChanged(e) {
- const value = e.target.value;
+ const select = e.target;
+ const value = select.value;
+
+ const missingNodeOption = select.querySelector('option[data-not-installed=true]');
+ if (missingNodeOption !== null && missingNodeOption.value !== value) {
+ missingNodeOption.parentNode.removeChild(missingNodeOption);
+ }
+
const optionsContext = getOptionsContext();
const options = await getOptionsMutable(optionsContext);
options.general.mainDictionary = value;
- settingsSaveOptions();
+ await settingsSaveOptions();
}
@@ -467,15 +491,18 @@ function dictionaryErrorsShow(errors) {
dialog.textContent = '';
if (errors !== null && errors.length > 0) {
- const uniqueErrors = {};
+ const uniqueErrors = new Map();
for (let e of errors) {
console.error(e);
e = dictionaryErrorToString(e);
- uniqueErrors[e] = hasOwn(uniqueErrors, e) ? uniqueErrors[e] + 1 : 1;
+ let count = uniqueErrors.get(e);
+ if (typeof count === 'undefined') {
+ count = 0;
+ }
+ uniqueErrors.set(e, count + 1);
}
- for (const e in uniqueErrors) {
- const count = uniqueErrors[e];
+ for (const [e, count] of uniqueErrors.entries()) {
const div = document.createElement('p');
if (count > 1) {
div.textContent = `${e} `;
@@ -537,9 +564,7 @@ async function onDictionaryPurge(e) {
}
await settingsSaveOptions();
- const optionsContext = getOptionsContext();
- const options = await getOptionsMutable(optionsContext);
- onDatabaseUpdated(options);
+ onDatabaseUpdated();
} catch (err) {
dictionaryErrorsShow([err]);
} finally {
@@ -611,9 +636,7 @@ async function onDictionaryImport(e) {
dictionaryErrorsShow(errors);
}
- const optionsContext = getOptionsContext();
- const options = await getOptionsMutable(optionsContext);
- onDatabaseUpdated(options);
+ onDatabaseUpdated();
}
} catch (err) {
dictionaryErrorsShow([err]);
diff --git a/ext/bg/js/settings/main.js b/ext/bg/js/settings/main.js
index 3bf65eda..d1ad2c6b 100644
--- a/ext/bg/js/settings/main.js
+++ b/ext/bg/js/settings/main.js
@@ -16,6 +16,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*global getOptionsContext, apiOptionsSave
+utilBackend, utilIsolate, utilBackgroundIsolate
+ankiErrorShown, ankiFieldsToDict
+ankiTemplatesUpdateValue, onAnkiOptionsChanged, onDictionaryOptionsChanged
+appearanceInitialize, audioSettingsInitialize, profileOptionsSetup, dictSettingsInitialize
+ankiInitialize, ankiTemplatesInitialize, storageInfoInitialize
+*/
+
function getOptionsMutable(optionsContext) {
return utilBackend().getOptions(
utilBackgroundIsolate(optionsContext)
@@ -28,6 +36,22 @@ function getOptionsFullMutable() {
async function formRead(options) {
options.general.enable = $('#enable').prop('checked');
+ const enableClipboardPopups = $('#enable-clipboard-popups').prop('checked');
+ if (enableClipboardPopups) {
+ options.general.enableClipboardPopups = await new Promise((resolve, _reject) => {
+ chrome.permissions.request(
+ {permissions: ['clipboardRead']},
+ (granted) => {
+ if (!granted) {
+ $('#enable-clipboard-popups').prop('checked', false);
+ }
+ resolve(granted);
+ }
+ );
+ });
+ } else {
+ options.general.enableClipboardPopups = false;
+ }
options.general.showGuide = $('#show-usage-guide').prop('checked');
options.general.compactTags = $('#compact-tags').prop('checked');
options.general.compactGlossaries = $('#compact-glossaries').prop('checked');
@@ -44,7 +68,7 @@ async function formRead(options) {
options.general.popupVerticalOffset = parseInt($('#popup-vertical-offset').val(), 10);
options.general.popupHorizontalOffset2 = parseInt($('#popup-horizontal-offset2').val(), 0);
options.general.popupVerticalOffset2 = parseInt($('#popup-vertical-offset2').val(), 10);
- options.general.popupScalingFactor = parseInt($('#popup-scaling-factor').val(), 10);
+ options.general.popupScalingFactor = parseFloat($('#popup-scaling-factor').val());
options.general.popupScaleRelativeToPageZoom = $('#popup-scale-relative-to-page-zoom').prop('checked');
options.general.popupScaleRelativeToVisualViewport = $('#popup-scale-relative-to-visual-viewport').prop('checked');
options.general.popupTheme = $('#popup-theme').val();
@@ -67,6 +91,7 @@ async function formRead(options) {
options.scanning.enablePopupSearch = $('#enable-search-within-first-popup').prop('checked');
options.scanning.enableOnPopupExpressions = $('#enable-scanning-of-popup-expressions').prop('checked');
options.scanning.enableOnSearchPage = $('#enable-scanning-on-search-page').prop('checked');
+ options.scanning.enableSearchTags = $('#enable-search-tags').prop('checked');
options.scanning.delay = parseInt($('#scan-delay').val(), 10);
options.scanning.length = parseInt($('#scan-length').val(), 10);
options.scanning.modifier = $('#scan-modifier-key').val();
@@ -103,6 +128,7 @@ async function formRead(options) {
async function formWrite(options) {
$('#enable').prop('checked', options.general.enable);
+ $('#enable-clipboard-popups').prop('checked', options.general.enableClipboardPopups);
$('#show-usage-guide').prop('checked', options.general.showGuide);
$('#compact-tags').prop('checked', options.general.compactTags);
$('#compact-glossaries').prop('checked', options.general.compactGlossaries);
@@ -142,6 +168,7 @@ async function formWrite(options) {
$('#enable-search-within-first-popup').prop('checked', options.scanning.enablePopupSearch);
$('#enable-scanning-of-popup-expressions').prop('checked', options.scanning.enableOnPopupExpressions);
$('#enable-scanning-on-search-page').prop('checked', options.scanning.enableOnSearchPage);
+ $('#enable-search-tags').prop('checked', options.scanning.enableSearchTags);
$('#scan-delay').val(options.scanning.delay);
$('#scan-length').val(options.scanning.length);
$('#scan-modifier-key').val(options.scanning.modifier);
@@ -167,7 +194,7 @@ async function formWrite(options) {
await ankiTemplatesUpdateValue();
await onAnkiOptionsChanged(options);
- await onDictionaryOptionsChanged(options);
+ await onDictionaryOptionsChanged();
formUpdateVisibility(options);
}
@@ -215,7 +242,7 @@ async function settingsSaveOptions() {
await apiOptionsSave(source);
}
-async function onOptionsUpdate({source}) {
+async function onOptionsUpdated({source}) {
const thisSource = await settingsGetSource();
if (source === thisSource) { return; }
@@ -247,7 +274,7 @@ async function onReady() {
storageInfoInitialize();
- yomichan.on('optionsUpdate', onOptionsUpdate);
+ yomichan.on('optionsUpdated', onOptionsUpdated);
}
$(document).ready(() => onReady());
diff --git a/ext/bg/js/settings/popup-preview-frame.js b/ext/bg/js/settings/popup-preview-frame.js
index 37a4b416..aa2b6100 100644
--- a/ext/bg/js/settings/popup-preview-frame.js
+++ b/ext/bg/js/settings/popup-preview-frame.js
@@ -16,15 +16,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*global apiOptionsGet, Popup, PopupProxyHost, Frontend, TextSourceRange*/
class SettingsPopupPreview {
constructor() {
this.frontend = null;
this.apiOptionsGetOld = apiOptionsGet;
- this.popupInjectOuterStylesheetOld = Popup.injectOuterStylesheet;
+ this.popup = null;
+ this.popupSetCustomOuterCssOld = null;
this.popupShown = false;
this.themeChangeTimeout = null;
this.textSource = null;
+ this._targetOrigin = chrome.runtime.getURL('/').replace(/\/$/, '');
}
static create() {
@@ -49,18 +52,18 @@ class SettingsPopupPreview {
const popupHost = new PopupProxyHost();
await popupHost.prepare();
- const popup = popupHost.createPopup(null, 0);
- popup.setChildrenSupported(false);
+ this.popup = popupHost.getOrCreatePopup();
+ this.popup.setChildrenSupported(false);
- this.frontend = new Frontend(popup);
+ this.popupSetCustomOuterCssOld = this.popup.setCustomOuterCss;
+ this.popup.setCustomOuterCss = (...args) => this.popupSetCustomOuterCss(...args);
- this.frontend.setEnabled = function () {};
- this.frontend.searchClear = function () {};
+ this.frontend = new Frontend(this.popup);
- await this.frontend.prepare();
+ this.frontend.setEnabled = () => {};
+ this.frontend.searchClear = () => {};
- // Overwrite popup
- Popup.injectOuterStylesheet = (...args) => this.popupInjectOuterStylesheet(...args);
+ await this.frontend.prepare();
// Update search
this.updateSearch();
@@ -82,20 +85,21 @@ class SettingsPopupPreview {
return options;
}
- popupInjectOuterStylesheet(...args) {
+ async popupSetCustomOuterCss(...args) {
// This simulates the stylesheet priorities when injecting using the web extension API.
- const result = this.popupInjectOuterStylesheetOld(...args);
+ const result = await this.popupSetCustomOuterCssOld.call(this.popup, ...args);
- const outerStylesheet = Popup.outerStylesheet;
const node = document.querySelector('#client-css');
- if (node !== null && outerStylesheet !== null) {
- node.parentNode.insertBefore(outerStylesheet, node);
+ if (node !== null && result !== null) {
+ node.parentNode.insertBefore(result, node);
}
return result;
}
onMessage(e) {
+ if (e.origin !== this._targetOrigin) { return; }
+
const {action, params} = e.data;
const handler = SettingsPopupPreview._messageHandlers.get(action);
if (typeof handler !== 'function') { return; }
@@ -136,7 +140,7 @@ class SettingsPopupPreview {
setCustomOuterCss(css) {
if (this.frontend === null) { return; }
- this.frontend.popup.setCustomOuterCss(css, true);
+ this.frontend.popup.setCustomOuterCss(css, false);
}
async updateSearch() {
diff --git a/ext/bg/js/settings/popup-preview.js b/ext/bg/js/settings/popup-preview.js
index 0d20471e..d1d2ff5e 100644
--- a/ext/bg/js/settings/popup-preview.js
+++ b/ext/bg/js/settings/popup-preview.js
@@ -40,20 +40,22 @@ function showAppearancePreview() {
window.wanakana.bind(text[0]);
+ const targetOrigin = chrome.runtime.getURL('/').replace(/\/$/, '');
+
text.on('input', () => {
const action = 'setText';
const params = {text: text.val()};
- frame.contentWindow.postMessage({action, params}, '*');
+ frame.contentWindow.postMessage({action, params}, targetOrigin);
});
customCss.on('input', () => {
const action = 'setCustomCss';
const params = {css: customCss.val()};
- frame.contentWindow.postMessage({action, params}, '*');
+ frame.contentWindow.postMessage({action, params}, targetOrigin);
});
customOuterCss.on('input', () => {
const action = 'setCustomOuterCss';
const params = {css: customOuterCss.val()};
- frame.contentWindow.postMessage({action, params}, '*');
+ frame.contentWindow.postMessage({action, params}, targetOrigin);
});
container.append(frame);
diff --git a/ext/bg/js/settings/profiles.js b/ext/bg/js/settings/profiles.js
index c4e68b53..3e589809 100644
--- a/ext/bg/js/settings/profiles.js
+++ b/ext/bg/js/settings/profiles.js
@@ -16,6 +16,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*global getOptionsMutable, getOptionsFullMutable, settingsSaveOptions, apiOptionsGetFull
+utilBackgroundIsolate, formWrite
+conditionsClearCaches, ConditionsUI, profileConditionsDescriptor*/
+
let currentProfileIndex = 0;
let profileConditionsContainer = null;
diff --git a/ext/bg/js/settings/storage.js b/ext/bg/js/settings/storage.js
index 6c10f665..cbe1bb4d 100644
--- a/ext/bg/js/settings/storage.js
+++ b/ext/bg/js/settings/storage.js
@@ -16,6 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/*global apiGetEnvironmentInfo*/
function storageBytesToLabeledString(size) {
const base = 1000;