blob: c76cd6c6e748a3a263b7fc93a6ac5494e018dd7a [file] [log] [blame]
Adrià Vilanova Martínez09f35be2021-09-06 19:50:09 +02001import {getExtVersion, isFirefox, isReleaseVersion} from '../common/extUtils.js';
2import {cleanUpOptions, optionsPrototype, specialOptions} from '../common/optionsUtils.js';
3import optionsPage from './optionsPage.json5';
Adrià Vilanova Martínez3465e772021-07-11 19:18:41 +02004
avm99963bf8eece2021-04-22 00:27:03 +02005var savedSuccessfullyTimeout = null;
6
7const exclusiveOptions = [['thread', 'threadall']];
8
Adrià Vilanova Martíneze32adc42021-08-30 17:16:49 +02009// Get a URL to a document which is part of the extension documentation (using
10// |ref| as the Git ref).
11function getDocURLWithRef(doc, ref) {
12 return 'https://gerrit.avm99963.com/plugins/gitiles/infinitegforums/+/' +
13 ref + '/docs/' + doc;
14}
15
16// Get a URL to a document which is part of the extension documentation
17// (autodetect the appropriate Git ref)
18function getDocURL(doc) {
19 if (!isReleaseVersion()) return getDocURLWithRef(doc, 'HEAD');
20
21 var version = getExtVersion();
22 return getDocURLWithRef(doc, 'refs/tags/v' + version);
23}
24
avm99963bf8eece2021-04-22 00:27:03 +020025// Get the value of the option set in the options/experiments page
26function getOptionValue(opt) {
27 if (specialOptions.includes(opt)) {
28 switch (opt) {
29 case 'profileindicatoralt_months':
30 return document.getElementById(opt).value || 12;
31
32 case 'ccdarktheme_mode':
33 return document.getElementById(opt).value || 'switch';
34
35 case 'ccdragndropfix':
36 return document.getElementById(opt).checked || false;
37
38 default:
39 console.warn('Unrecognized option: ' + opt);
40 return undefined;
41 }
42 }
43
44 return document.getElementById(opt).checked || false;
45}
46
47// Returns whether the option is included in the current context
48function isOptionShown(opt) {
49 if (!optionsPrototype.hasOwnProperty(opt)) return false;
50 return optionsPrototype[opt].context == window.CONTEXT;
51}
52
53function save(e) {
54 // Validation checks before saving
55 if (isOptionShown('profileindicatoralt_months')) {
56 var months = document.getElementById('profileindicatoralt_months');
57 if (!months.checkValidity()) {
58 console.warn(months.validationMessage);
59 return;
60 }
61 }
62
63 e.preventDefault();
64
65 chrome.storage.sync.get(null, function(items) {
66 var options = cleanUpOptions(items, true);
67
68 // Save
69 Object.keys(options).forEach(function(opt) {
70 if (!isOptionShown(opt)) return;
71 options[opt] = getOptionValue(opt);
72 });
73
74 chrome.storage.sync.set(options, function() {
75 window.close();
76
77 // In browsers like Firefox window.close is not supported:
78 if (savedSuccessfullyTimeout !== null)
79 window.clearTimeout(savedSuccessfullyTimeout);
80
81 document.getElementById('save-indicator').innerText =
82 '✓ ' + chrome.i18n.getMessage('options_saved');
83 savedSuccessfullyTimeout = window.setTimeout(_ => {
84 document.getElementById('save-indicator').innerText = '';
85 }, 3699);
86 });
87 });
88}
89
90function i18n() {
91 document.querySelectorAll('[data-i18n]')
92 .forEach(
93 el => el.innerHTML = chrome.i18n.getMessage(
94 'options_' + el.getAttribute('data-i18n')));
95}
96
97window.addEventListener('load', function() {
Adrià Vilanova Martíneze32adc42021-08-30 17:16:49 +020098 if (window.CONTEXT == 'options') {
99 if (!isReleaseVersion()) {
100 var experimentsLink = document.querySelector('.experiments-link');
101 experimentsLink.removeAttribute('hidden');
102 experimentsLink.addEventListener('click', _ => chrome.tabs.create({
103 url: chrome.runtime.getURL('options/experiments.html'),
104 }));
105 }
106
Adrià Vilanova Martínez09f35be2021-09-06 19:50:09 +0200107 // Add options to page
108 let optionsContainer = document.getElementById('options-container');
109 for (let section of optionsPage.sections) {
110 if (section?.name) {
111 let sectionHeader = document.createElement('h4');
112 sectionHeader.setAttribute('data-i18n', section.name);
113 optionsContainer.append(sectionHeader);
114 }
115
116 if (section?.options) {
117 for (let option of section.options) {
118 if (option?.customHTML) {
119 optionsContainer.insertAdjacentHTML('beforeend', option.customHTML);
Adrià Vilanova Martínezc591bf72021-09-06 20:23:06 +0200120 } else {
121 let optionEl = document.createElement('div');
122 optionEl.classList.add('option');
123
124 let checkbox = document.createElement('input');
125 checkbox.setAttribute('type', 'checkbox');
126 checkbox.id = option.codename;
127
128 let label = document.createElement('label');
129 label.setAttribute('for', checkbox.id);
130 label.setAttribute('data-i18n', option.codename);
131
132 optionEl.append(checkbox, ' ', label);
133
134 if (option?.experimental) {
135 let experimental = document.createElement('span');
136 experimental.classList.add('experimental-label');
137 experimental.setAttribute('data-i18n', 'experimental_label');
138
139 optionEl.append(' ', experimental);
140 }
141
142 optionsContainer.append(optionEl);
Adrià Vilanova Martínez09f35be2021-09-06 19:50:09 +0200143 }
144
Adrià Vilanova Martínezc591bf72021-09-06 20:23:06 +0200145 // Add kill switch component after each option.
146 let killSwitchComponent = document.createElement('div');
147 killSwitchComponent.classList.add('kill-switch-label');
148 killSwitchComponent.setAttribute('hidden', '');
149 killSwitchComponent.setAttribute('data-feature', option.codename);
150 killSwitchComponent.setAttribute('data-i18n', 'killswitchenabled');
Adrià Vilanova Martínez09f35be2021-09-06 19:50:09 +0200151
Adrià Vilanova Martínezc591bf72021-09-06 20:23:06 +0200152 optionsContainer.append(killSwitchComponent);
Adrià Vilanova Martínez09f35be2021-09-06 19:50:09 +0200153 }
154 }
155
156 if (section?.footerHTML) {
157 optionsContainer.insertAdjacentHTML('beforeend', section.footerHTML);
158 }
159 }
160
Adrià Vilanova Martíneze32adc42021-08-30 17:16:49 +0200161 var featuresLink = document.querySelector('.features-link');
162 featuresLink.href = getDocURL('features.md');
163
Adrià Vilanova Martínez413cb442021-09-06 00:30:45 +0200164 var profileIndicatorLink =
165 document.getElementById('profileIndicatorMoreInfo');
Adrià Vilanova Martíneze32adc42021-08-30 17:16:49 +0200166 profileIndicatorLink.href = getDocURL('op_indicator.md');
avm999637309b062021-04-22 12:41:08 +0200167 }
168
Adrià Vilanova Martínez09f35be2021-09-06 19:50:09 +0200169 i18n();
170
avm99963bf8eece2021-04-22 00:27:03 +0200171 chrome.storage.sync.get(null, function(items) {
172 items = cleanUpOptions(items, false);
173
Adrià Vilanova Martínez413cb442021-09-06 00:30:45 +0200174 // If some features have been force disabled, communicate this to the user.
175 if (items?._forceDisabledFeatures &&
176 items._forceDisabledFeatures.length > 0) {
177 if (window.CONTEXT == 'options') {
178 document.getElementById('kill-switch-warning')
179 .removeAttribute('hidden');
180 }
181
182 // TODO(avm99963): show a message above each option that has been force
183 // disabled
184 }
185
Adrià Vilanova Martínez3465e772021-07-11 19:18:41 +0200186 for (var entry of Object.entries(optionsPrototype)) {
187 var opt = entry[0];
188 var optMeta = entry[1];
189
avm99963bf8eece2021-04-22 00:27:03 +0200190 if (!isOptionShown(opt)) continue;
191
192 if (specialOptions.includes(opt)) {
193 switch (opt) {
194 case 'profileindicatoralt_months':
195 var input = document.createElement('input');
196 input.type = 'number';
197 input.id = 'profileindicatoralt_months';
198 input.max = '12';
199 input.min = '1';
200 input.value = items[opt];
201 input.required = true;
202 document.getElementById('profileindicatoralt_months--container')
203 .appendChild(input);
204 break;
205
206 case 'ccdarktheme_mode':
207 var select = document.createElement('select');
208 select.id = 'ccdarktheme_mode';
209
210 const modes = ['switch', 'system'];
211 for (const mode of modes) {
212 var modeOption = document.createElement('option');
213 modeOption.value = mode;
214 modeOption.textContent =
215 chrome.i18n.getMessage('options_ccdarktheme_mode_' + mode);
216 if (items.ccdarktheme_mode == mode) modeOption.selected = true;
217 select.appendChild(modeOption);
218 }
219
220 document.getElementById('ccdarktheme_mode--container')
221 .appendChild(select);
222 break;
223
224 // Firefox doesn't support drag and dropping bookmarks into the text
225 // editor while preserving the bookmark title.
226 case 'ccdragndropfix':
227 var showOption = !isFirefox();
228 if (showOption) {
229 document.getElementById('dragndrop-wrapper')
230 .removeAttribute('hidden');
231
232 if (items[opt] === true)
233 document.getElementById(opt).checked = true;
234 }
235 break;
236
237 default:
238 console.warn('Unrecognized option: ' + opt);
239 break;
240 }
241 continue;
242 }
243
244 if (items[opt] === true) document.getElementById(opt).checked = true;
Adrià Vilanova Martínezc591bf72021-09-06 20:23:06 +0200245 if (window.CONTEXT == 'options' &&
246 items?._forceDisabledFeatures?.includes?.(opt))
247 document.querySelector('.kill-switch-label[data-feature="' + opt + '"]')
248 .removeAttribute('hidden');
avm99963bf8eece2021-04-22 00:27:03 +0200249 }
250
251 exclusiveOptions.forEach(exclusive => {
252 if (!isOptionShown(exclusive[0]) || !isOptionShown(exclusive[1])) return;
253
254 exclusive.forEach(
255 el => document.getElementById(el).addEventListener('change', e => {
256 if (document.getElementById(exclusive[0]).checked &&
257 document.getElementById(exclusive[1]).checked) {
258 document
259 .getElementById(
260 exclusive[(e.currentTarget.id == exclusive[0] ? 1 : 0)])
261 .checked = false;
262 }
263 }));
264 });
265 document.querySelector('#save').addEventListener('click', save);
266 });
267});