blob: c552da2ce477da861ad0378f369dc81559f26039 [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);
120 continue;
121 }
122
123 let optionEl = document.createElement('div');
124 optionEl.classList.add('option');
125
126 let checkbox = document.createElement('input');
127 checkbox.setAttribute('type', 'checkbox');
128 checkbox.id = option.codename;
129
130 let label = document.createElement('label');
131 label.setAttribute('for', checkbox.id);
132 label.setAttribute('data-i18n', option.codename);
133
134 optionEl.append(checkbox, ' ', label);
135
136 if (option?.experimental) {
137 let experimental = document.createElement('span');
138 experimental.classList.add('experimental-label');
139 experimental.setAttribute('data-i18n', 'experimental_label');
140
141 optionEl.append(experimental);
142 }
143
144 optionsContainer.append(optionEl);
145 }
146 }
147
148 if (section?.footerHTML) {
149 optionsContainer.insertAdjacentHTML('beforeend', section.footerHTML);
150 }
151 }
152
Adrià Vilanova Martíneze32adc42021-08-30 17:16:49 +0200153 var featuresLink = document.querySelector('.features-link');
154 featuresLink.href = getDocURL('features.md');
155
Adrià Vilanova Martínez413cb442021-09-06 00:30:45 +0200156 var profileIndicatorLink =
157 document.getElementById('profileIndicatorMoreInfo');
Adrià Vilanova Martíneze32adc42021-08-30 17:16:49 +0200158 profileIndicatorLink.href = getDocURL('op_indicator.md');
avm999637309b062021-04-22 12:41:08 +0200159 }
160
Adrià Vilanova Martínez09f35be2021-09-06 19:50:09 +0200161 i18n();
162
avm99963bf8eece2021-04-22 00:27:03 +0200163 chrome.storage.sync.get(null, function(items) {
164 items = cleanUpOptions(items, false);
165
Adrià Vilanova Martínez413cb442021-09-06 00:30:45 +0200166 // If some features have been force disabled, communicate this to the user.
167 if (items?._forceDisabledFeatures &&
168 items._forceDisabledFeatures.length > 0) {
169 if (window.CONTEXT == 'options') {
170 document.getElementById('kill-switch-warning')
171 .removeAttribute('hidden');
172 }
173
174 // TODO(avm99963): show a message above each option that has been force
175 // disabled
176 }
177
Adrià Vilanova Martínez3465e772021-07-11 19:18:41 +0200178 for (var entry of Object.entries(optionsPrototype)) {
179 var opt = entry[0];
180 var optMeta = entry[1];
181
avm99963bf8eece2021-04-22 00:27:03 +0200182 if (!isOptionShown(opt)) continue;
183
184 if (specialOptions.includes(opt)) {
185 switch (opt) {
186 case 'profileindicatoralt_months':
187 var input = document.createElement('input');
188 input.type = 'number';
189 input.id = 'profileindicatoralt_months';
190 input.max = '12';
191 input.min = '1';
192 input.value = items[opt];
193 input.required = true;
194 document.getElementById('profileindicatoralt_months--container')
195 .appendChild(input);
196 break;
197
198 case 'ccdarktheme_mode':
199 var select = document.createElement('select');
200 select.id = 'ccdarktheme_mode';
201
202 const modes = ['switch', 'system'];
203 for (const mode of modes) {
204 var modeOption = document.createElement('option');
205 modeOption.value = mode;
206 modeOption.textContent =
207 chrome.i18n.getMessage('options_ccdarktheme_mode_' + mode);
208 if (items.ccdarktheme_mode == mode) modeOption.selected = true;
209 select.appendChild(modeOption);
210 }
211
212 document.getElementById('ccdarktheme_mode--container')
213 .appendChild(select);
214 break;
215
216 // Firefox doesn't support drag and dropping bookmarks into the text
217 // editor while preserving the bookmark title.
218 case 'ccdragndropfix':
219 var showOption = !isFirefox();
220 if (showOption) {
221 document.getElementById('dragndrop-wrapper')
222 .removeAttribute('hidden');
223
224 if (items[opt] === true)
225 document.getElementById(opt).checked = true;
226 }
227 break;
228
229 default:
230 console.warn('Unrecognized option: ' + opt);
231 break;
232 }
233 continue;
234 }
235
236 if (items[opt] === true) document.getElementById(opt).checked = true;
237 }
238
239 exclusiveOptions.forEach(exclusive => {
240 if (!isOptionShown(exclusive[0]) || !isOptionShown(exclusive[1])) return;
241
242 exclusive.forEach(
243 el => document.getElementById(el).addEventListener('change', e => {
244 if (document.getElementById(exclusive[0]).checked &&
245 document.getElementById(exclusive[1]).checked) {
246 document
247 .getElementById(
248 exclusive[(e.currentTarget.id == exclusive[0] ? 1 : 0)])
249 .checked = false;
250 }
251 }));
252 });
253 document.querySelector('#save').addEventListener('click', save);
254 });
255});