MediaWiki:Gadget-skinTogglesNew.js

From Old School Near-Reality Wiki
Revision as of 19:49, 4 October 2022 by Bawolff (talk | contribs) (not sure if this will work)
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
  1 /**
  2  * Toggles for skin cookies
  3  * 
  4  * @author Gaz Lloyd
  5  * @author JaydenKieran
  6  * 
  7  */
  8 ;(function($, mw, rs){
  9 	var READER_COOKIE = 'readermode',
 10 		DARK_COOKIE = 'darkmode',
 11 		DARK_COOKIE_CONDITIONAL = 'darkmode_conditional',
 12 		STICKY_HEADER_COOKIE = 'stickyheader',
 13 		FLOORNUMBER_LS = 'floornumber_display',
 14 		currentReader = $.cookie(READER_COOKIE) === 'true',
 15 		currentDark = $.cookie(DARK_COOKIE) === 'true',
 16 		currentDarkConditional = $.cookie(DARK_COOKIE_CONDITIONAL) === 'true',
 17 		currentSticky = $.cookie(STICKY_HEADER_COOKIE) === 'true',
 18 		currentFloornumber = '_auto',
 19 		prompt = 'dark_prompt',
 20 		now = new Date(),
 21 		hour = now.getHours(),
 22 		conditionalCheck = (hour >= 19 || hour < 7),
 23 		popupButton,
 24 		readerSwitch,
 25 		darkConditionalSwitch,
 26 		darkSwitch,
 27 		stickySwitch,
 28 		floorSelect,
 29 		floorSelectAuto,
 30 		floorSelectUK,
 31 		floorSelectUS,
 32 		applyButton,
 33 		cancelButton,
 34 		portletLink,
 35 		$content,
 36 		formMade = false,
 37 		userLocale = 'UK',
 38 		flsetting,
 39 		browserLocale,
 40 		floorSelectHelp;
 41 
 42 	var self = {
 43 		init: function () {
 44 			if (rs.hasLocalStorage()) {
 45 				currentFloornumber = window.localStorage.getItem(FLOORNUMBER_LS);
 46 				if (currentFloornumber == null) {
 47 					currentFloornumber = '_auto';
 48 				}
 49 			}
 50 			flsetting = currentFloornumber;
 51 			if (window.navigator.languages && window.navigator.languages.length) {
 52 				browserLocale = window.navigator.languages[0];
 53 			} else {
 54 				browserLocale = navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en';
 55 			}
 56 			switch (browserLocale) {
 57 				// all langs in -US or -CA
 58 				case 'en-US':
 59 				case 'es-US':
 60 				case 'en-CA':
 61 				case 'fr-CA':
 62 					userLocale = 'US';
 63 					break;
 64 			}
 65 			if (currentFloornumber == '_auto') {
 66 				flsetting = userLocale;
 67 			}
 68 			switch (flsetting) {
 69 				case 'US':
 70 					flsetting = 'floornumber-setting-us';
 71 					break;
 72 				case 'UK':
 73 				default:
 74 					flsetting = 'floornumber-setting-gb';
 75 					break;
 76 			}
 77 			$('body').addClass(flsetting);
 78 			
 79 			portletLink = mw.util.addPortletLink(
 80 				'p-personal',
 81 				'',
 82 				'',
 83 				'pt-skin-toggles',
 84 				'Your appearance settings',
 85 				null,
 86 				$('#pt-userpage, #pt-anonuserpage')
 87 			);
 88 			
 89 			$(portletLink).find('a').addClass('oo-ui-icon-advanced').add('.floor-convention').click(function(e) {
 90 				e.preventDefault();
 91 				if (!formMade) {
 92 					mw.loader.using(['oojs-ui-core','oojs-ui-windows','oojs-ui-widgets']).then(self.initForm);
 93 				} else {
 94 					window.OOUIWindowManager.openWindow('skin');
 95 				}
 96 			});
 97 			
 98 
 99 			if (currentReader) {
100 				mw.util.addPortletLink(
101 					'p-namespaces',
102 					'/',
103 					'Menu',
104 					'ca-reader-menu'
105 				);
106 
107 				// can't use the nextnode parameter in addPortletLink
108 				// because the id of the first tab varies
109 				$('#ca-reader-menu')
110 					.prependTo('#p-namespaces ul');
111 
112 				// move sidebar
113 				$('#mw-panel')
114 					.attr('id', 'ca-reader-dropdown')
115 					.appendTo('#ca-reader-menu');
116 			}
117 
118 			if (currentDarkConditional) {
119 				var reloadRequired = (conditionalCheck != currentDark)
120 				$.cookie(DARK_COOKIE, conditionalCheck, {expires: 365, path: '/'});
121 				if (reloadRequired === true) {
122 					window.location.reload(true);
123 				}
124 			}
125 
126 			if (currentSticky) {
127 				window.addEventListener("scroll", function() {
128 					var personal = $('#p-personal');
129 				    if (mw.config.get('wgAction') === 'edit' || window.location.search.includes('veaction')) {
130 				  		// We're on an edit page, do nothing and reset all the stuff
131 						if (personal.is(":hidden")) {
132 							personal.show();
133 							head.removeClass('sticky-hidden');
134 						}
135 				    } else {
136 					  	var targetEle = document.getElementById("mw-head");
137 					  	var head = $('#mw-head');
138 					  	if (window.scrollY > (targetEle.offsetTop + targetEle.offsetHeight)) {
139 							if (personal.is(":visible")) {
140 								personal.hide();
141 								head.addClass('sticky-hidden');
142 							}
143 					  	} else {
144 							if (personal.is(":hidden")) {
145 								personal.show();
146 								head.removeClass('sticky-hidden');
147 							}
148 					  	}
149 				  	}
150 				});
151 				// hidden by css when sticky-hidden is not on
152 				if (mw.config.get('wgIsMainPage') !== true) {
153 					mw.util.addPortletLink(
154 						'p-namespaces',
155 						'/',
156 						'Main Page',
157 						'ca-nstab-mainpage',
158 						'Visit the main page'
159 					);
160 				}
161 			}
162 			
163 			/**
164 			 * Used for prompting users who have prefers-color-scheme set to dark
165 			 * to switch to dark mode (because doing this automatically would
166 			 * require setting a cookie, prompting this is best for privacy/
167 			 * legal reasons)
168 			 **/
169 			 
170 			if (rs.hasLocalStorage()) {
171 			 // This should always be true anyway because browsers that
172 			 // support prefers-color-scheme have LocalStorage API support
173 				if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
174 					if (!currentDark) {
175 						// Only show if they're not currently using dark mode
176 						var alreadyPrompted = localStorage.getItem(prompt)
177 						if (alreadyPrompted === null) {
178 							// Only show if the localStorage key doesn't exist
179 							mw.loader.load( 'ext.gadget.skinTogglesNew-prompt' )
180 						}
181 					}
182 				}
183 			}
184 		},
185 		initForm: function() {
186 			// Treat opening the form as having seen the dark mode prompt.
187 			if (rs.hasLocalStorage() && localStorage.getItem(prompt) === null) {
188 				localStorage.setItem(prompt, 'true')
189 			}
190 
191 			readerSwitch = new OO.ui.ToggleSwitchWidget({
192 				value: currentReader,
193 				classes: ['reader-toggle'],
194 				align: 'right'
195 			});
196 
197 			stickySwitch = new OO.ui.ToggleSwitchWidget({
198 				value: currentSticky,
199 				classes: ['reader-toggle'],
200 				align: 'right'
201 			});
202 
203 			darkConditionalSwitch = new OO.ui.ToggleSwitchWidget({
204 				value: currentDarkConditional,
205 				classes: ['reader-toggle'],
206 				align: 'right'
207 			})
208 
209 			darkSwitch = new OO.ui.ButtonSelectWidget({
210 				classes: ['appearance-buttons'],
211 				items: [
212 					new OO.ui.ButtonOptionWidget({
213 						classes: ['light-mode-button'],
214 						data: false,
215 						label: new OO.ui.HtmlSnippet('<div class="button-img"></div><div class="button-text">Light</div><div class="button-text-selected"></div>'),
216 					}),
217 					new OO.ui.ButtonOptionWidget({
218 						classes: ['dark-mode-button'],
219 						data: true,
220 						label:new OO.ui.HtmlSnippet('<div class="button-img"></div><div class="button-text">Dark</div><div class="button-text-selected"></div>'),
221 						//disabled: true
222 					}),
223 				]
224 			});
225 			
226 			floorSelectAuto = new OO.ui.RadioOptionWidget({
227 						data: '_auto',
228 						label: 'Auto-detect: '+userLocale
229 					});
230 			floorSelectUK = new OO.ui.RadioOptionWidget({
231 						data: 'UK',
232 						label: 'UK'
233 					});
234 			floorSelectUS = new OO.ui.RadioOptionWidget({
235 						data: 'US',
236 						label: 'US'
237 					});
238 			
239 			floorSelect = new OO.ui.RadioSelectWidget({
240 				classes: ['floornumber-select'],
241 				items: [
242 					floorSelectAuto,
243 					floorSelectUK,
244 					floorSelectUS
245 					]
246 			});
247 			floorSelect.selectItemByData(currentFloornumber);
248 			floorSelectHelp = 'Changes how floor numbers are displayed on the wiki - whether the numbering begins at 0 (ground) or 1.';
249 			if (!rs.hasLocalStorage()) {
250 				floorSelect.setDisabled(true);
251 				floorSelectHelp = 'This option requires local storage to be supported and enabled in your browser.';
252 			}
253 			floorSelectAuto.$element.attr('title', 'Automatically detect the type to use from your browser.');
254 			floorSelectUK.$element.attr('title', 'The numbering used in the UK, Europe, and many Commonwealth countries: entrance on the ground floor, then above that is 1st floor, 2nd floor, etc.');
255 			floorSelectUS.$element.attr('title', 'The numbering used in the US and Canada: entrance on the 1st floor, then above that is 2nd floor, 3rd floor, etc.');
256 
257 			darkSwitch.setDisabled(darkConditionalSwitch.getValue())
258 
259 			darkConditionalSwitch.on('change', function() {
260 				darkSwitch.setDisabled(darkConditionalSwitch.getValue())
261 			})
262 
263 			stickySwitch.setDisabled(readerSwitch.getValue())
264 			readerSwitch.setDisabled(stickySwitch.getValue())
265 
266 			readerSwitch.on('change', function() {
267 				if (readerSwitch.getValue() === true) {
268 					stickySwitch.setValue(false)
269 				}
270 				stickySwitch.setDisabled(readerSwitch.getValue())
271 			})
272 
273 			stickySwitch.on('change', function() {
274 				if (stickySwitch.getValue() === true) {
275 					readerSwitch.setValue(false)
276 				}
277 				readerSwitch.setDisabled(stickySwitch.getValue())
278 			})
279 
280 			darkSwitch.selectItemByData(currentDark);
281 
282 			applyButton = new OO.ui.ButtonInputWidget({
283 				label: 'Save',
284 				flags: ['primary', 'progressive'],
285 				classes: ['skin-save-button']
286 			});
287 
288 			applyButton.on('click', function(){
289 				$.cookie(READER_COOKIE, readerSwitch.getValue(), {expires: 365, path: '/'});
290 				$.cookie(DARK_COOKIE_CONDITIONAL, darkConditionalSwitch.getValue(), {expires: 365, path: '/'});
291 				$.cookie(STICKY_HEADER_COOKIE, stickySwitch.getValue(), {expires: 365, path: '/'});
292 				
293 				var darkval = darkSwitch.findSelectedItem(),
294 					darkc = false,
295 					requireReload = false;
296 					
297 				if ((readerSwitch.getValue() !== currentReader) || (stickySwitch.getValue() !== currentSticky)) {
298 					requireReload = true;
299 				}
300 
301 				if (darkConditionalSwitch.getValue() === false) {
302 					if (darkval !== null) {
303 						darkc = darkval.getData();
304 					}
305 				} else if (darkConditionalSwitch.getValue() === true) {
306 					darkc = conditionalCheck
307 				}
308 				
309 				$.cookie(DARK_COOKIE, darkc, {expires: 365, path: '/'});
310 				
311 				if (rs.hasLocalStorage()) {
312 					window.localStorage.setItem(FLOORNUMBER_LS, floorSelect.findSelectedItem().getData());
313 				}
314 
315 				if (darkc === true) {
316 					mw.loader.using(['ext.gadget.darkmode']).then(function() {
317 					  $('body').addClass('wgl-darkmode')
318 					  $('body').removeClass('wgl-lightmode')
319 					});
320 				} else {
321 					$('body').addClass('wgl-lightmode')
322 					$('body').removeClass('wgl-darkmode')
323 				}
324 				
325 				if (requireReload === true) {
326 					window.location.reload(true);
327 				} else {
328 					window.OOUIWindowManager.closeWindow('skin')
329 				}
330 			});
331 
332 			cancelButton = new OO.ui.ButtonInputWidget({ label: 'Cancel', flags: 'destructive'});
333 			
334 			$content = $('<div>');
335 			$content
336 				.addClass('appearance-modal tile')
337 				.append(
338 					$('<h2>').text('Appearance'),
339 					$('<div>')
340 						.addClass('appearance-buttons')
341 						.append(darkSwitch.$element),
342 					$('<div>')
343 						.addClass('reader-mode')
344 						.append(
345 							darkConditionalSwitch.$element,
346 							$('<div>').addClass('setting-header dark-conditional-header').text('Automatic dark mode'),
347 							$('<p>').addClass('dark-conditional-desc').text('Automatically switch to dark mode from 19:00 to 7:00 local time. Disables the manual setting above.'),
348 							readerSwitch.$element,
349 							$('<div>').addClass('setting-header reader-mode-header').text('Reader mode'),
350 							$('<p>').addClass('reader-mode-desc').text('Increase the font size and switch the wiki to a fixed-width layout. Incompatible with sticky headers.'),
351 							stickySwitch.$element,
352 							$('<div>').addClass('setting-header sticky-header-header').text('Sticky header'),
353 							$('<p>').addClass('sticky-header-desc').text('Pin the navigation bar and search to the top when scrolling. Incompatible with reader mode.'),
354 							floorSelect.$element,
355 							$('<div>').addClass('setting-header floornumber-header').text('Floor numbering'),
356 							$('<p>').addClass('floornumber-desc').text(floorSelectHelp)
357 						),
358 					$('<div>')
359 						.addClass('appearance-save')
360 						.append(
361 							$('<p>').addClass('save-button-desc').html('Saving these changes will reload the page and set <a href="https://weirdgloop.org/privacy">personalisation cookies</a>.'),
362 							$('<div>').addClass('save-button-container')
363 								.append(applyButton.$element)
364 								.append(cancelButton.$element)
365 						)
366 				);
367 
368 			var initModal = function (modal) {
369 				modal.$body.append( $content );
370 				cancelButton.on('click', function(modal){window.OOUIWindowManager.closeWindow(modal);}, [modal]);
371 			};
372 
373 			rs.createOOUIWindow('skin', 'Appearance settings', {size: 'large', classes: ['rsw-skin-toggle-popup']}, initModal, true);
374 			
375 			formMade = true;
376 		}
377 	}
378 
379 	mw.loader.using(['ext.gadget.rsw-util'], function () {
380 		$(self.init);
381 	})
382 
383 }(jQuery, mediaWiki, rswiki));