Refactor extension to webpack
This change is the biggest in the history of the project. The entire
project has been refactored so it is built with webpack.
This involves:
- Creating webpack and npm config files.
- Fixing some bugs in the code due to the fact that webpack uses strict
mode.
- Merging some pieces of code which were shared throughout the codebase
(not exhaustive, more work should be done in this direction).
- Splitting the console_inject.js file into separate files (it had 1000+
lines).
- Adapting all the build-related files (Makefile, bash scripts, etc.)
- Changing the docs to explain the new build process.
- Changing the Zuul playbook/roles to adapt to the new build process.
Change-Id: I16476d47825461c3a318b3f1a1eddb06b2df2e89
diff --git a/src/optionsCommon.js b/src/optionsCommon.js
new file mode 100644
index 0000000..afb6bde
--- /dev/null
+++ b/src/optionsCommon.js
@@ -0,0 +1,171 @@
+import {cleanUpOptions, optionsPrototype, specialOptions} from './common/optionsUtils.js';
+import {isFirefox, isReleaseVersion} from './common/extUtils.js';
+
+var savedSuccessfullyTimeout = null;
+
+const exclusiveOptions = [['thread', 'threadall']];
+
+// Get the value of the option set in the options/experiments page
+function getOptionValue(opt) {
+ if (specialOptions.includes(opt)) {
+ switch (opt) {
+ case 'profileindicatoralt_months':
+ return document.getElementById(opt).value || 12;
+
+ case 'ccdarktheme_mode':
+ return document.getElementById(opt).value || 'switch';
+
+ case 'ccdragndropfix':
+ return document.getElementById(opt).checked || false;
+
+ default:
+ console.warn('Unrecognized option: ' + opt);
+ return undefined;
+ }
+ }
+
+ return document.getElementById(opt).checked || false;
+}
+
+// Returns whether the option is included in the current context
+function isOptionShown(opt) {
+ if (!optionsPrototype.hasOwnProperty(opt)) return false;
+ return optionsPrototype[opt].context == window.CONTEXT;
+}
+
+function save(e) {
+ // Validation checks before saving
+ if (isOptionShown('profileindicatoralt_months')) {
+ var months = document.getElementById('profileindicatoralt_months');
+ if (!months.checkValidity()) {
+ console.warn(months.validationMessage);
+ return;
+ }
+ }
+
+ e.preventDefault();
+
+ chrome.storage.sync.get(null, function(items) {
+ var options = cleanUpOptions(items, true);
+
+ // Save
+ Object.keys(options).forEach(function(opt) {
+ if (!isOptionShown(opt)) return;
+ options[opt] = getOptionValue(opt);
+ });
+
+ chrome.storage.sync.set(options, function() {
+ window.close();
+
+ // In browsers like Firefox window.close is not supported:
+ if (savedSuccessfullyTimeout !== null)
+ window.clearTimeout(savedSuccessfullyTimeout);
+
+ document.getElementById('save-indicator').innerText =
+ '✓ ' + chrome.i18n.getMessage('options_saved');
+ savedSuccessfullyTimeout = window.setTimeout(_ => {
+ document.getElementById('save-indicator').innerText = '';
+ }, 3699);
+ });
+ });
+}
+
+function i18n() {
+ document.querySelectorAll('[data-i18n]')
+ .forEach(
+ el => el.innerHTML = chrome.i18n.getMessage(
+ 'options_' + el.getAttribute('data-i18n')));
+}
+
+window.addEventListener('load', function() {
+ i18n();
+
+ if (window.CONTEXT == 'options' && !isReleaseVersion()) {
+ var experimentsLink = document.querySelector('.experiments-link');
+ experimentsLink.removeAttribute('hidden');
+ experimentsLink.addEventListener('click', _ => chrome.tabs.create({
+ url: chrome.runtime.getURL('options/experiments.html'),
+ }));
+ }
+
+ chrome.storage.sync.get(null, function(items) {
+ items = cleanUpOptions(items, false);
+
+ for (var entry of Object.entries(optionsPrototype)) {
+ var opt = entry[0];
+ var optMeta = entry[1];
+
+ if (!isOptionShown(opt)) continue;
+
+ if (specialOptions.includes(opt)) {
+ switch (opt) {
+ case 'profileindicatoralt_months':
+ var input = document.createElement('input');
+ input.type = 'number';
+ input.id = 'profileindicatoralt_months';
+ input.max = '12';
+ input.min = '1';
+ input.value = items[opt];
+ input.required = true;
+ document.getElementById('profileindicatoralt_months--container')
+ .appendChild(input);
+ break;
+
+ case 'ccdarktheme_mode':
+ var select = document.createElement('select');
+ select.id = 'ccdarktheme_mode';
+
+ const modes = ['switch', 'system'];
+ for (const mode of modes) {
+ var modeOption = document.createElement('option');
+ modeOption.value = mode;
+ modeOption.textContent =
+ chrome.i18n.getMessage('options_ccdarktheme_mode_' + mode);
+ if (items.ccdarktheme_mode == mode) modeOption.selected = true;
+ select.appendChild(modeOption);
+ }
+
+ document.getElementById('ccdarktheme_mode--container')
+ .appendChild(select);
+ break;
+
+ // Firefox doesn't support drag and dropping bookmarks into the text
+ // editor while preserving the bookmark title.
+ case 'ccdragndropfix':
+ var showOption = !isFirefox();
+ if (showOption) {
+ document.getElementById('dragndrop-wrapper')
+ .removeAttribute('hidden');
+
+ if (items[opt] === true)
+ document.getElementById(opt).checked = true;
+ }
+ break;
+
+ default:
+ console.warn('Unrecognized option: ' + opt);
+ break;
+ }
+ continue;
+ }
+
+ if (items[opt] === true) document.getElementById(opt).checked = true;
+ }
+
+ exclusiveOptions.forEach(exclusive => {
+ if (!isOptionShown(exclusive[0]) || !isOptionShown(exclusive[1])) return;
+
+ exclusive.forEach(
+ el => document.getElementById(el).addEventListener('change', e => {
+ if (document.getElementById(exclusive[0]).checked &&
+ document.getElementById(exclusive[1]).checked) {
+ document
+ .getElementById(
+ exclusive[(e.currentTarget.id == exclusive[0] ? 1 : 0)])
+ .checked = false;
+ }
+ }));
+ });
+ document.querySelector('#save').addEventListener('click', save);
+ });
+});