MediaWiki:Gadget-skinTogglesNew.js: Difference between revisions

From Old School Near-Reality Wiki
Jump to navigation Jump to search
(not sure if this will work)
(try and set the body class manually to emulate whatever extension powers the other wikis dark mode)
Line 116: Line 116:
}
}


if (CurrentDark ) {
$('body').addClass('wgl-darkmode');
}
if (currentDarkConditional) {
if (currentDarkConditional) {
var reloadRequired = (conditionalCheck != currentDark)
var reloadRequired = (conditionalCheck != currentDark)
Line 314: Line 317:


if (darkc === true) {
if (darkc === true) {
mw.loader.using(['ext.gadget.darkmode']).then(function() {
mw.loader.using(['wg.darkmode']).then(function() {
  $('body').addClass('wgl-darkmode')
  $('body').addClass('wgl-darkmode')
  $('body').removeClass('wgl-lightmode')
  $('body').removeClass('wgl-lightmode')

Revision as of 20:04, 4 October 2022

  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 (CurrentDark ) {
119 				$('body').addClass('wgl-darkmode');
120 			}
121 			if (currentDarkConditional) {
122 				var reloadRequired = (conditionalCheck != currentDark)
123 				$.cookie(DARK_COOKIE, conditionalCheck, {expires: 365, path: '/'});
124 				if (reloadRequired === true) {
125 					window.location.reload(true);
126 				}
127 			}
128 
129 			if (currentSticky) {
130 				window.addEventListener("scroll", function() {
131 					var personal = $('#p-personal');
132 				    if (mw.config.get('wgAction') === 'edit' || window.location.search.includes('veaction')) {
133 				  		// We're on an edit page, do nothing and reset all the stuff
134 						if (personal.is(":hidden")) {
135 							personal.show();
136 							head.removeClass('sticky-hidden');
137 						}
138 				    } else {
139 					  	var targetEle = document.getElementById("mw-head");
140 					  	var head = $('#mw-head');
141 					  	if (window.scrollY > (targetEle.offsetTop + targetEle.offsetHeight)) {
142 							if (personal.is(":visible")) {
143 								personal.hide();
144 								head.addClass('sticky-hidden');
145 							}
146 					  	} else {
147 							if (personal.is(":hidden")) {
148 								personal.show();
149 								head.removeClass('sticky-hidden');
150 							}
151 					  	}
152 				  	}
153 				});
154 				// hidden by css when sticky-hidden is not on
155 				if (mw.config.get('wgIsMainPage') !== true) {
156 					mw.util.addPortletLink(
157 						'p-namespaces',
158 						'/',
159 						'Main Page',
160 						'ca-nstab-mainpage',
161 						'Visit the main page'
162 					);
163 				}
164 			}
165 			
166 			/**
167 			 * Used for prompting users who have prefers-color-scheme set to dark
168 			 * to switch to dark mode (because doing this automatically would
169 			 * require setting a cookie, prompting this is best for privacy/
170 			 * legal reasons)
171 			 **/
172 			 
173 			if (rs.hasLocalStorage()) {
174 			 // This should always be true anyway because browsers that
175 			 // support prefers-color-scheme have LocalStorage API support
176 				if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
177 					if (!currentDark) {
178 						// Only show if they're not currently using dark mode
179 						var alreadyPrompted = localStorage.getItem(prompt)
180 						if (alreadyPrompted === null) {
181 							// Only show if the localStorage key doesn't exist
182 							mw.loader.load( 'ext.gadget.skinTogglesNew-prompt' )
183 						}
184 					}
185 				}
186 			}
187 		},
188 		initForm: function() {
189 			// Treat opening the form as having seen the dark mode prompt.
190 			if (rs.hasLocalStorage() && localStorage.getItem(prompt) === null) {
191 				localStorage.setItem(prompt, 'true')
192 			}
193 
194 			readerSwitch = new OO.ui.ToggleSwitchWidget({
195 				value: currentReader,
196 				classes: ['reader-toggle'],
197 				align: 'right'
198 			});
199 
200 			stickySwitch = new OO.ui.ToggleSwitchWidget({
201 				value: currentSticky,
202 				classes: ['reader-toggle'],
203 				align: 'right'
204 			});
205 
206 			darkConditionalSwitch = new OO.ui.ToggleSwitchWidget({
207 				value: currentDarkConditional,
208 				classes: ['reader-toggle'],
209 				align: 'right'
210 			})
211 
212 			darkSwitch = new OO.ui.ButtonSelectWidget({
213 				classes: ['appearance-buttons'],
214 				items: [
215 					new OO.ui.ButtonOptionWidget({
216 						classes: ['light-mode-button'],
217 						data: false,
218 						label: new OO.ui.HtmlSnippet('<div class="button-img"></div><div class="button-text">Light</div><div class="button-text-selected"></div>'),
219 					}),
220 					new OO.ui.ButtonOptionWidget({
221 						classes: ['dark-mode-button'],
222 						data: true,
223 						label:new OO.ui.HtmlSnippet('<div class="button-img"></div><div class="button-text">Dark</div><div class="button-text-selected"></div>'),
224 						//disabled: true
225 					}),
226 				]
227 			});
228 			
229 			floorSelectAuto = new OO.ui.RadioOptionWidget({
230 						data: '_auto',
231 						label: 'Auto-detect: '+userLocale
232 					});
233 			floorSelectUK = new OO.ui.RadioOptionWidget({
234 						data: 'UK',
235 						label: 'UK'
236 					});
237 			floorSelectUS = new OO.ui.RadioOptionWidget({
238 						data: 'US',
239 						label: 'US'
240 					});
241 			
242 			floorSelect = new OO.ui.RadioSelectWidget({
243 				classes: ['floornumber-select'],
244 				items: [
245 					floorSelectAuto,
246 					floorSelectUK,
247 					floorSelectUS
248 					]
249 			});
250 			floorSelect.selectItemByData(currentFloornumber);
251 			floorSelectHelp = 'Changes how floor numbers are displayed on the wiki - whether the numbering begins at 0 (ground) or 1.';
252 			if (!rs.hasLocalStorage()) {
253 				floorSelect.setDisabled(true);
254 				floorSelectHelp = 'This option requires local storage to be supported and enabled in your browser.';
255 			}
256 			floorSelectAuto.$element.attr('title', 'Automatically detect the type to use from your browser.');
257 			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.');
258 			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.');
259 
260 			darkSwitch.setDisabled(darkConditionalSwitch.getValue())
261 
262 			darkConditionalSwitch.on('change', function() {
263 				darkSwitch.setDisabled(darkConditionalSwitch.getValue())
264 			})
265 
266 			stickySwitch.setDisabled(readerSwitch.getValue())
267 			readerSwitch.setDisabled(stickySwitch.getValue())
268 
269 			readerSwitch.on('change', function() {
270 				if (readerSwitch.getValue() === true) {
271 					stickySwitch.setValue(false)
272 				}
273 				stickySwitch.setDisabled(readerSwitch.getValue())
274 			})
275 
276 			stickySwitch.on('change', function() {
277 				if (stickySwitch.getValue() === true) {
278 					readerSwitch.setValue(false)
279 				}
280 				readerSwitch.setDisabled(stickySwitch.getValue())
281 			})
282 
283 			darkSwitch.selectItemByData(currentDark);
284 
285 			applyButton = new OO.ui.ButtonInputWidget({
286 				label: 'Save',
287 				flags: ['primary', 'progressive'],
288 				classes: ['skin-save-button']
289 			});
290 
291 			applyButton.on('click', function(){
292 				$.cookie(READER_COOKIE, readerSwitch.getValue(), {expires: 365, path: '/'});
293 				$.cookie(DARK_COOKIE_CONDITIONAL, darkConditionalSwitch.getValue(), {expires: 365, path: '/'});
294 				$.cookie(STICKY_HEADER_COOKIE, stickySwitch.getValue(), {expires: 365, path: '/'});
295 				
296 				var darkval = darkSwitch.findSelectedItem(),
297 					darkc = false,
298 					requireReload = false;
299 					
300 				if ((readerSwitch.getValue() !== currentReader) || (stickySwitch.getValue() !== currentSticky)) {
301 					requireReload = true;
302 				}
303 
304 				if (darkConditionalSwitch.getValue() === false) {
305 					if (darkval !== null) {
306 						darkc = darkval.getData();
307 					}
308 				} else if (darkConditionalSwitch.getValue() === true) {
309 					darkc = conditionalCheck
310 				}
311 				
312 				$.cookie(DARK_COOKIE, darkc, {expires: 365, path: '/'});
313 				
314 				if (rs.hasLocalStorage()) {
315 					window.localStorage.setItem(FLOORNUMBER_LS, floorSelect.findSelectedItem().getData());
316 				}
317 
318 				if (darkc === true) {
319 					mw.loader.using(['wg.darkmode']).then(function() {
320 					  $('body').addClass('wgl-darkmode')
321 					  $('body').removeClass('wgl-lightmode')
322 					});
323 				} else {
324 					$('body').addClass('wgl-lightmode')
325 					$('body').removeClass('wgl-darkmode')
326 				}
327 				
328 				if (requireReload === true) {
329 					window.location.reload(true);
330 				} else {
331 					window.OOUIWindowManager.closeWindow('skin')
332 				}
333 			});
334 
335 			cancelButton = new OO.ui.ButtonInputWidget({ label: 'Cancel', flags: 'destructive'});
336 			
337 			$content = $('<div>');
338 			$content
339 				.addClass('appearance-modal tile')
340 				.append(
341 					$('<h2>').text('Appearance'),
342 					$('<div>')
343 						.addClass('appearance-buttons')
344 						.append(darkSwitch.$element),
345 					$('<div>')
346 						.addClass('reader-mode')
347 						.append(
348 							darkConditionalSwitch.$element,
349 							$('<div>').addClass('setting-header dark-conditional-header').text('Automatic dark mode'),
350 							$('<p>').addClass('dark-conditional-desc').text('Automatically switch to dark mode from 19:00 to 7:00 local time. Disables the manual setting above.'),
351 							readerSwitch.$element,
352 							$('<div>').addClass('setting-header reader-mode-header').text('Reader mode'),
353 							$('<p>').addClass('reader-mode-desc').text('Increase the font size and switch the wiki to a fixed-width layout. Incompatible with sticky headers.'),
354 							stickySwitch.$element,
355 							$('<div>').addClass('setting-header sticky-header-header').text('Sticky header'),
356 							$('<p>').addClass('sticky-header-desc').text('Pin the navigation bar and search to the top when scrolling. Incompatible with reader mode.'),
357 							floorSelect.$element,
358 							$('<div>').addClass('setting-header floornumber-header').text('Floor numbering'),
359 							$('<p>').addClass('floornumber-desc').text(floorSelectHelp)
360 						),
361 					$('<div>')
362 						.addClass('appearance-save')
363 						.append(
364 							$('<p>').addClass('save-button-desc').html('Saving these changes will reload the page and set <a href="https://weirdgloop.org/privacy">personalisation cookies</a>.'),
365 							$('<div>').addClass('save-button-container')
366 								.append(applyButton.$element)
367 								.append(cancelButton.$element)
368 						)
369 				);
370 
371 			var initModal = function (modal) {
372 				modal.$body.append( $content );
373 				cancelButton.on('click', function(modal){window.OOUIWindowManager.closeWindow(modal);}, [modal]);
374 			};
375 
376 			rs.createOOUIWindow('skin', 'Appearance settings', {size: 'large', classes: ['rsw-skin-toggle-popup']}, initModal, true);
377 			
378 			formMade = true;
379 		}
380 	}
381 
382 	mw.loader.using(['ext.gadget.rsw-util'], function () {
383 		$(self.init);
384 	})
385 
386 }(jQuery, mediaWiki, rswiki));