MediaWiki:Gadget-skinTogglesNew.js: Difference between revisions

From Old School Near-Reality Wiki
Jump to navigation Jump to search
(try and set the body class manually to emulate whatever extension powers the other wikis dark mode)
(remove wg.darkmode load that doesn't exist.)
 
(2 intermediate revisions by the same user not shown)
Line 98: Line 98:


if (currentReader) {
if (currentReader) {
                $('body').addClass('wgl-readermode');
mw.util.addPortletLink(
mw.util.addPortletLink(
'p-namespaces',
'p-namespaces',
Line 116: Line 117:
}
}


if (CurrentDark ) {
if (currentDark) {
$('body').addClass('wgl-darkmode');
$('body').addClass('wgl-darkmode');
}
}
Line 317: Line 318:


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

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