aboutsummaryrefslogtreecommitdiff
path: root/ext/js/pages
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js/pages')
-rw-r--r--ext/js/pages/action-popup-main.js233
-rw-r--r--ext/js/pages/generic-page-main.js32
-rw-r--r--ext/js/pages/info-main.js127
-rw-r--r--ext/js/pages/permissions-main.js103
-rw-r--r--ext/js/pages/welcome-main.js88
5 files changed, 583 insertions, 0 deletions
diff --git a/ext/js/pages/action-popup-main.js b/ext/js/pages/action-popup-main.js
new file mode 100644
index 00000000..5cc56745
--- /dev/null
+++ b/ext/js/pages/action-popup-main.js
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2017-2021 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
+ * HotkeyHelpController
+ * PermissionsUtil
+ * api
+ */
+
+class DisplayController {
+ constructor() {
+ this._optionsFull = null;
+ this._permissionsUtil = new PermissionsUtil();
+ }
+
+ async prepare() {
+ const manifest = chrome.runtime.getManifest();
+
+ this._showExtensionInfo(manifest);
+ this._setupEnvironment();
+ this._setupButtonEvents('.action-open-search', 'openSearchPage', chrome.runtime.getURL('/search.html'));
+ this._setupButtonEvents('.action-open-info', 'openInfoPage', chrome.runtime.getURL('/info.html'));
+
+ const optionsFull = await api.optionsGetFull();
+ this._optionsFull = optionsFull;
+
+ this._setupHotkeys();
+
+ const optionsPageUrl = optionsFull.global.useSettingsV2 ? manifest.options_ui.page : '/settings-old.html';
+ this._setupButtonEvents('.action-open-settings', 'openSettingsPage', chrome.runtime.getURL(optionsPageUrl));
+ this._setupButtonEvents('.action-open-permissions', null, chrome.runtime.getURL('/permissions.html'));
+
+ const {profiles, profileCurrent} = optionsFull;
+ const primaryProfile = (profileCurrent >= 0 && profileCurrent < profiles.length) ? profiles[profileCurrent] : null;
+ if (primaryProfile !== null) {
+ this._setupOptions(primaryProfile);
+ }
+
+ document.querySelector('.action-select-profile').hidden = (profiles.length <= 1);
+
+ this._updateProfileSelect(profiles, profileCurrent);
+
+ setTimeout(() => {
+ document.body.dataset.loaded = 'true';
+ }, 10);
+ }
+
+ // Private
+
+ _showExtensionInfo(manifest) {
+ const node = document.getElementById('extension-info');
+ if (node === null) { return; }
+
+ node.textContent = `${manifest.name} v${manifest.version}`;
+ }
+
+ _setupButtonEvents(selector, command, url) {
+ const nodes = document.querySelectorAll(selector);
+ for (const node of nodes) {
+ if (typeof command === 'string') {
+ node.addEventListener('click', (e) => {
+ if (e.button !== 0) { return; }
+ api.commandExec(command, {mode: e.ctrlKey ? 'newTab' : 'existingOrNewTab'});
+ e.preventDefault();
+ }, false);
+ node.addEventListener('auxclick', (e) => {
+ if (e.button !== 1) { return; }
+ api.commandExec(command, {mode: 'newTab'});
+ e.preventDefault();
+ }, false);
+ }
+
+ if (typeof url === 'string') {
+ node.href = url;
+ node.target = '_blank';
+ node.rel = 'noopener';
+ }
+ }
+ }
+
+ async _setupEnvironment() {
+ const urlSearchParams = new URLSearchParams(location.search);
+ let mode = urlSearchParams.get('mode');
+ switch (mode) {
+ case 'full':
+ case 'mini':
+ break;
+ default:
+ {
+ let tab;
+ try {
+ tab = await this._getCurrentTab();
+ } catch (e) {
+ // NOP
+ }
+ mode = (tab ? 'full' : 'mini');
+ }
+ break;
+ }
+
+ document.documentElement.dataset.mode = mode;
+ }
+
+ _getCurrentTab() {
+ return new Promise((resolve, reject) => {
+ chrome.tabs.getCurrent((result) => {
+ const e = chrome.runtime.lastError;
+ if (e) {
+ reject(new Error(e.message));
+ } else {
+ resolve(result);
+ }
+ });
+ });
+ }
+
+ _setupOptions({options}) {
+ const extensionEnabled = options.general.enable;
+ const onToggleChanged = () => api.commandExec('toggleTextScanning');
+ for (const toggle of document.querySelectorAll('#enable-search,#enable-search2')) {
+ toggle.checked = extensionEnabled;
+ toggle.addEventListener('change', onToggleChanged, false);
+ }
+ this._updateDictionariesEnabledWarnings(options);
+ this._updatePermissionsWarnings(options);
+ }
+
+ async _setupHotkeys() {
+ const hotkeyHelpController = new HotkeyHelpController();
+ await hotkeyHelpController.prepare();
+
+ const {profiles, profileCurrent} = this._optionsFull;
+ const primaryProfile = (profileCurrent >= 0 && profileCurrent < profiles.length) ? profiles[profileCurrent] : null;
+ if (primaryProfile !== null) {
+ hotkeyHelpController.setOptions(primaryProfile.options);
+ }
+
+ hotkeyHelpController.setupNode(document.documentElement);
+ }
+
+ _updateProfileSelect(profiles, profileCurrent) {
+ const select = document.querySelector('#profile-select');
+ const optionGroup = document.querySelector('#profile-select-option-group');
+ const fragment = document.createDocumentFragment();
+ for (let i = 0, ii = profiles.length; i < ii; ++i) {
+ const {name} = profiles[i];
+ const option = document.createElement('option');
+ option.textContent = name;
+ option.value = `${i}`;
+ fragment.appendChild(option);
+ }
+ optionGroup.textContent = '';
+ optionGroup.appendChild(fragment);
+ select.value = `${profileCurrent}`;
+
+ select.addEventListener('change', this._onProfileSelectChange.bind(this), false);
+ }
+
+ _onProfileSelectChange(e) {
+ const value = parseInt(e.currentTarget.value, 10);
+ if (typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= this._optionsFull.profiles.length) {
+ this._setPrimaryProfileIndex(value);
+ }
+ }
+
+ async _setPrimaryProfileIndex(value) {
+ return await api.modifySettings(
+ [{
+ action: 'set',
+ path: 'profileCurrent',
+ value,
+ scope: 'global'
+ }]
+ );
+ }
+
+ async _updateDictionariesEnabledWarnings(options) {
+ const noDictionariesEnabledWarnings = document.querySelectorAll('.no-dictionaries-enabled-warning');
+ const dictionaries = await api.getDictionaryInfo();
+
+ let enabledCount = 0;
+ for (const {title} of dictionaries) {
+ if (
+ Object.prototype.hasOwnProperty.call(options.dictionaries, title) &&
+ options.dictionaries[title].enabled
+ ) {
+ ++enabledCount;
+ }
+ }
+
+ const hasEnabledDictionary = (enabledCount > 0);
+ for (const node of noDictionariesEnabledWarnings) {
+ node.hidden = hasEnabledDictionary;
+ }
+ }
+
+ async _updatePermissionsWarnings(options) {
+ const permissions = await this._permissionsUtil.getAllPermissions();
+ if (this._permissionsUtil.hasRequiredPermissionsForOptions(permissions, options)) { return; }
+
+ const warnings = document.querySelectorAll('.action-open-permissions,.permissions-required-warning');
+ for (const node of warnings) {
+ console.log(node);
+ node.hidden = false;
+ }
+ }
+}
+
+(async () => {
+ api.forwardLogsToBackend();
+ await yomichan.backendReady();
+
+ api.logIndicatorClear();
+
+ const displayController = new DisplayController();
+ displayController.prepare();
+
+ yomichan.ready();
+})();
diff --git a/ext/js/pages/generic-page-main.js b/ext/js/pages/generic-page-main.js
new file mode 100644
index 00000000..db1a770a
--- /dev/null
+++ b/ext/js/pages/generic-page-main.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020-2021 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
+ * DocumentFocusController
+ */
+
+function setupEnvironmentInfo() {
+ const {manifest_version: manifestVersion} = chrome.runtime.getManifest();
+ document.documentElement.dataset.manifestVersion = `${manifestVersion}`;
+}
+
+(() => {
+ const documentFocusController = new DocumentFocusController();
+ documentFocusController.prepare();
+ document.documentElement.dataset.loaded = 'true';
+ setupEnvironmentInfo();
+})();
diff --git a/ext/js/pages/info-main.js b/ext/js/pages/info-main.js
new file mode 100644
index 00000000..6cf82595
--- /dev/null
+++ b/ext/js/pages/info-main.js
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2020-2021 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
+ * BackupController
+ * DocumentFocusController
+ * SettingsController
+ * api
+ */
+
+function getBrowserDisplayName(browser) {
+ switch (browser) {
+ case 'chrome': return 'Chrome';
+ case 'firefox': return 'Firefox';
+ case 'firefox-mobile': return 'Firefox for Android';
+ case 'edge': return 'Edge';
+ case 'edge-legacy': return 'Edge Legacy';
+ default: return `${browser}`;
+ }
+}
+
+function getOperatingSystemDisplayName(os) {
+ switch (os) {
+ case 'mac': return 'Mac OS';
+ case 'win': return 'Windows';
+ case 'android': return 'Android';
+ case 'cros': return 'Chrome OS';
+ case 'linux': return 'Linux';
+ case 'openbsd': return 'Open BSD';
+ case 'unknown': return 'Unknown';
+ default: return `${os}`;
+ }
+}
+
+(async () => {
+ try {
+ const documentFocusController = new DocumentFocusController();
+ documentFocusController.prepare();
+
+ const manifest = chrome.runtime.getManifest();
+ const language = chrome.i18n.getUILanguage();
+
+ api.forwardLogsToBackend();
+ await yomichan.prepare();
+
+ const {userAgent} = navigator;
+ const {name, version} = manifest;
+ const {browser, platform: {os}} = await api.getEnvironmentInfo();
+
+ const thisVersionLink = document.querySelector('#release-notes-this-version-link');
+ thisVersionLink.href = thisVersionLink.dataset.hrefFormat.replace(/\{version\}/g, version);
+
+ document.querySelector('#version').textContent = `${name} ${version}`;
+ document.querySelector('#browser').textContent = getBrowserDisplayName(browser);
+ document.querySelector('#platform').textContent = getOperatingSystemDisplayName(os);
+ document.querySelector('#language').textContent = `${language}`;
+ document.querySelector('#user-agent').textContent = userAgent;
+
+ (async () => {
+ let ankiConnectVersion = null;
+ try {
+ ankiConnectVersion = await api.getAnkiConnectVersion();
+ } catch (e) {
+ // NOP
+ }
+
+ document.querySelector('#anki-connect-version').textContent = (ankiConnectVersion !== null ? `${ankiConnectVersion}` : 'Unknown');
+ document.querySelector('#anki-connect-version-container').hasError = `${ankiConnectVersion === null}`;
+ document.querySelector('#anki-connect-version-unknown-message').hidden = (ankiConnectVersion !== null);
+ })();
+
+ (async () => {
+ let dictionaryInfos;
+ try {
+ dictionaryInfos = await api.getDictionaryInfo();
+ } catch (e) {
+ return;
+ }
+
+ const fragment = document.createDocumentFragment();
+ let first = true;
+ for (const {title} of dictionaryInfos) {
+ if (first) {
+ first = false;
+ } else {
+ fragment.appendChild(document.createTextNode(', '));
+ }
+
+ const node = document.createElement('span');
+ node.className = 'installed-dictionary';
+ node.textContent = title;
+ fragment.appendChild(node);
+ }
+
+ document.querySelector('#installed-dictionaries-none').hidden = (dictionaryInfos.length !== 0);
+ const container = document.querySelector('#installed-dictionaries');
+ container.textContent = '';
+ container.appendChild(fragment);
+ })();
+
+ const settingsController = new SettingsController();
+ settingsController.prepare();
+
+ const backupController = new BackupController(settingsController, null);
+ await backupController.prepare();
+
+ await promiseTimeout(100);
+
+ document.documentElement.dataset.loaded = 'true';
+ } catch (e) {
+ yomichan.logError(e);
+ }
+})();
diff --git a/ext/js/pages/permissions-main.js b/ext/js/pages/permissions-main.js
new file mode 100644
index 00000000..5b17a5dd
--- /dev/null
+++ b/ext/js/pages/permissions-main.js
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020-2021 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
+ * DocumentFocusController
+ * PermissionsToggleController
+ * SettingsController
+ * api
+ */
+
+async function setupEnvironmentInfo() {
+ const {manifest_version: manifestVersion} = chrome.runtime.getManifest();
+ const {browser, platform} = await api.getEnvironmentInfo();
+ document.documentElement.dataset.browser = browser;
+ document.documentElement.dataset.os = platform.os;
+ document.documentElement.dataset.manifestVersion = `${manifestVersion}`;
+}
+
+async function isAllowedIncognitoAccess() {
+ return await new Promise((resolve) => chrome.extension.isAllowedIncognitoAccess(resolve));
+}
+
+async function isAllowedFileSchemeAccess() {
+ return await new Promise((resolve) => chrome.extension.isAllowedFileSchemeAccess(resolve));
+}
+
+function setupPermissionsToggles() {
+ const manifest = chrome.runtime.getManifest();
+ let optionalPermissions = manifest.optional_permissions;
+ if (!Array.isArray(optionalPermissions)) { optionalPermissions = []; }
+ optionalPermissions = new Set(optionalPermissions);
+
+ const hasAllPermisions = (set, values) => {
+ for (const value of values) {
+ if (!set.has(value)) { return false; }
+ }
+ return true;
+ };
+
+ for (const toggle of document.querySelectorAll('.permissions-toggle')) {
+ let permissions = toggle.dataset.requiredPermissions;
+ permissions = (typeof permissions === 'string' && permissions.length > 0 ? permissions.split(' ') : []);
+ toggle.disabled = !hasAllPermisions(optionalPermissions, permissions);
+ }
+}
+
+(async () => {
+ try {
+ const documentFocusController = new DocumentFocusController();
+ documentFocusController.prepare();
+
+ setupPermissionsToggles();
+
+ for (const node of document.querySelectorAll('.extension-id-example')) {
+ node.textContent = chrome.runtime.getURL('/');
+ }
+
+ api.forwardLogsToBackend();
+ await yomichan.prepare();
+
+ setupEnvironmentInfo();
+
+ const permissionsCheckboxes = [
+ document.querySelector('#permission-checkbox-allow-in-private-windows'),
+ document.querySelector('#permission-checkbox-allow-file-url-access')
+ ];
+
+ const permissions = await Promise.all([
+ isAllowedIncognitoAccess(),
+ isAllowedFileSchemeAccess()
+ ]);
+
+ for (let i = 0, ii = permissions.length; i < ii; ++i) {
+ permissionsCheckboxes[i].checked = permissions[i];
+ }
+
+ const settingsController = new SettingsController(0);
+ settingsController.prepare();
+
+ const permissionsToggleController = new PermissionsToggleController(settingsController);
+ permissionsToggleController.prepare();
+
+ await promiseTimeout(100);
+
+ document.documentElement.dataset.loaded = 'true';
+ } catch (e) {
+ yomichan.logError(e);
+ }
+})();
diff --git a/ext/js/pages/welcome-main.js b/ext/js/pages/welcome-main.js
new file mode 100644
index 00000000..57b265dc
--- /dev/null
+++ b/ext/js/pages/welcome-main.js
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019-2021 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
+ * DictionaryController
+ * DictionaryImportController
+ * DocumentFocusController
+ * GenericSettingController
+ * ModalController
+ * ScanInputsSimpleController
+ * SettingsController
+ * SettingsDisplayController
+ * StatusFooter
+ * api
+ */
+
+async function setupEnvironmentInfo() {
+ const {manifest_version: manifestVersion} = chrome.runtime.getManifest();
+ const {browser, platform} = await api.getEnvironmentInfo();
+ document.documentElement.dataset.browser = browser;
+ document.documentElement.dataset.os = platform.os;
+ document.documentElement.dataset.manifestVersion = `${manifestVersion}`;
+}
+
+async function setupGenericSettingsController(genericSettingController) {
+ await genericSettingController.prepare();
+ await genericSettingController.refresh();
+}
+
+(async () => {
+ try {
+ const documentFocusController = new DocumentFocusController();
+ documentFocusController.prepare();
+
+ const statusFooter = new StatusFooter(document.querySelector('.status-footer-container'));
+ statusFooter.prepare();
+
+ api.forwardLogsToBackend();
+ await yomichan.prepare();
+
+ setupEnvironmentInfo();
+
+ const optionsFull = await api.optionsGetFull();
+
+ const preparePromises = [];
+
+ const modalController = new ModalController();
+ modalController.prepare();
+
+ const settingsController = new SettingsController(optionsFull.profileCurrent);
+ settingsController.prepare();
+
+ const dictionaryController = new DictionaryController(settingsController, modalController, null, statusFooter);
+ dictionaryController.prepare();
+
+ const dictionaryImportController = new DictionaryImportController(settingsController, modalController, null, statusFooter);
+ dictionaryImportController.prepare();
+
+ const genericSettingController = new GenericSettingController(settingsController);
+ preparePromises.push(setupGenericSettingsController(genericSettingController));
+
+ const simpleScanningInputController = new ScanInputsSimpleController(settingsController);
+ simpleScanningInputController.prepare();
+
+ await Promise.all(preparePromises);
+
+ document.documentElement.dataset.loaded = 'true';
+
+ const settingsDisplayController = new SettingsDisplayController(settingsController, modalController);
+ settingsDisplayController.prepare();
+ } catch (e) {
+ yomichan.logError(e);
+ }
+})();