From 26490f446917ad46acf68b09a30b20d6e427c263 Mon Sep 17 00:00:00 2001
From: Manjit Kaur Khaira <81208462+Maneet-k@users.noreply.github.com>
Date: Mon, 21 Feb 2022 17:16:59 +0530
Subject: [PATCH] Auto Dark mode Theme added (#793)
* Add auto options to index.html
* update app.js
* update uiUtil.js
* testing
* Update app.js
* fixed bug in app.js
* Update app.js
* removed extra spaces
* removed extra spaces
* Fixes autoTheme eventListener in app.js and removed spaced in index.html
* app.js
* removed extra spaces
* updated app,js and uiUtil.js
* fixed bug when browser doesn't support color-schemes
* added removeChild() instead of remove() and renamed class
* parentElement to parentNode
As the parentElement is new to firefox and IE
* parentElement to parentNode
* fixes options for theme and some for wikimedia theme
* fixes help for the wikimedia theme
* update uiUtil.js
* moved code back to previous place
* displays auto theme description
* added auto description
* removed space added again
* Update uiUtil.js
Defined `oldDescription` earlier before using it
* fixes oldDescription
* Update uiUtil.js
Co-authored-by: Mossroy
---
www/index.html | 10 +++++++---
www/js/app.js | 20 ++++++++++++++++++--
www/js/lib/uiUtil.js | 24 +++++++++++++++++-------
3 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/www/index.html b/www/index.html
index 3bf5884b..a008f845 100644
--- a/www/index.html
+++ b/www/index.html
@@ -483,10 +483,14 @@
-
* Implements workarounds specific to Wikimedia ZIMs. Try generic option if there are display errors with recent ZIMs.
+
(Auto themes match the dark/light mode of your device.)
+
* Implements workarounds specific to Wikimedia ZIMs. Try generic option if there are display errors with recent ZIMs.
[ Show article with applied theme ]
diff --git a/www/js/app.js b/www/js/app.js
index 95832549..a78eb38e 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -87,7 +87,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'settingsStore','abstractFilesys
// Turns caching of the PWA's code on or off and deletes the cache (it defaults to true unless the bypass option is set in Expert Settings)
params['appCache'] = settingsStore.getItem('appCache') !== 'false';
// A parameter to set the app theme and, if necessary, the CSS theme for article content (defaults to 'light')
- params['appTheme'] = settingsStore.getItem('appTheme') || 'light'; // Currently implemented: light|dark|dark_invert|dark_mwInvert
+ params['appTheme'] = settingsStore.getItem('appTheme') || 'light'; // Currently implemented: light|dark|dark_invert|dark_mwInvert|auto|auto_invert|auto_mwInvert|
// A global parameter to turn on/off the use of Keyboard HOME Key to focus search bar
params['useHomeKeyToFocusSearchBar'] = settingsStore.getItem('useHomeKeyToFocusSearchBar') === 'true';
// A parameter to access the URL of any extension that this app was launched from
@@ -158,7 +158,6 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'settingsStore','abstractFilesys
document.getElementById('titleSearchRange').value = params.maxSearchResultsSize;
document.getElementById('titleSearchRangeVal').textContent = params.maxSearchResultsSize;
document.getElementById('appThemeSelect').value = params.appTheme;
- uiUtil.applyAppTheme(params.appTheme);
document.getElementById('useHomeKeyToFocusSearchBarCheck').checked = params.useHomeKeyToFocusSearchBar;
switchHomeKeyToFocusSearchBar();
document.getElementById('bypassAppCacheCheck').checked = !params.appCache;
@@ -171,6 +170,23 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'settingsStore','abstractFilesys
// Unique identifier of the article expected to be displayed
var expectedArticleURLToBeDisplayed = "";
+
+ // define and store dark preference for matchMedia
+ var darkPreference = window.matchMedia('(prefers-color-scheme:dark)');
+ // if 'prefers-color-scheme' is not supported in the browser, then the "auto" options are not displayed to the user
+ if (window.matchMedia('(prefers-color-scheme)').media === 'not all') {
+ var optionsToBeRemoved = document.getElementById("appThemeSelect").querySelectorAll('.auto');
+ for (var i = 0; i < optionsToBeRemoved.length; i++) {
+ optionsToBeRemoved[i].parentNode.removeChild(optionsToBeRemoved[i]);
+ }
+ }
+ // Apply previously stored appTheme
+ uiUtil.applyAppTheme(params.appTheme);
+
+ // Whenever the system theme changes, call applyAppTheme function
+ darkPreference.onchange = function() {
+ uiUtil.applyAppTheme(params.appTheme);
+ }
/**
* Resize the IFrame height, so that it fills the whole available height in the window
diff --git a/www/js/lib/uiUtil.js b/www/js/lib/uiUtil.js
index 9e5b3ede..9b147de1 100644
--- a/www/js/lib/uiUtil.js
+++ b/www/js/lib/uiUtil.js
@@ -431,17 +431,20 @@ define(rqDef, function(settingsStore) {
* For each contentTheme, a stylesheet must be provided in www/css that is named 'kiwixJS' + contentTheme
* A rule may additionally be needed in app.css for full implementation of contentTheme
*
- * @param {String} theme The theme to apply (light|dark[_invert|_mwInvert])
+ * @param {String} theme The theme to apply (light|dark[_invert|_mwInvert]|auto[_invert|_mwInvert])
*/
function applyAppTheme(theme) {
+ var darkPreference = window.matchMedia('(prefers-color-scheme:dark)');
+ // Resolve the app theme from the matchMedia preference (for auto themes) or from the theme string
+ var appTheme = /^auto/.test(theme) ? darkPreference.matches ? 'dark' : 'light' : theme.replace(/_.*$/, '');
+ // Get contentTheme from chosen theme
+ var contentTheme = theme.replace(/^[^_]*/, '');
var htmlEl = document.querySelector('html');
var footer = document.querySelector('footer');
var oldTheme = htmlEl.dataset.theme || '';
var iframe = document.getElementById('articleContent');
var doc = iframe.contentDocument;
var kiwixJSSheet = doc ? doc.getElementById('kiwixJSTheme') || null : null;
- var appTheme = theme.replace(/_.*$/, '');
- var contentTheme = theme.replace(/^[^_]*/, '');
var oldAppTheme = oldTheme.replace(/_.*$/, '');
var oldContentTheme = oldTheme.replace(/^[^_]*/, '');
// Remove oldAppTheme and oldContentTheme
@@ -454,14 +457,21 @@ define(rqDef, function(settingsStore) {
// is not dark (but we want it applied when the content is dark or inverted)
footer.classList.add(contentTheme || '_light');
// Embed a reference to applied theme, so we can remove it generically in the future
- htmlEl.dataset.theme = theme;
+ htmlEl.dataset.theme = appTheme + contentTheme;
// Hide any previously displayed help
- var oldHelp = document.getElementById(oldTheme + '-help');
+ var oldHelp = document.getElementById(oldContentTheme.replace(/_/, '') + '-help');
if (oldHelp) oldHelp.style.display = 'none';
// Show any specific help for selected contentTheme
- var help = document.getElementById(theme + '-help');
+ var help = document.getElementById(contentTheme.replace(/_/, '') + '-help');
if (help) help.style.display = 'block';
-
+ // Remove the contentTheme for auto themes whenever system is in light mode
+ if (/^auto/.test(theme) && appTheme === 'light') contentTheme = null;
+ // Hide any previously displayed description for auto themes
+ var oldDescription = document.getElementById('kiwix-auto-description');
+ if (oldDescription) oldDescription.style.display = 'none';
+ // Show description for auto themes
+ var description = document.getElementById('kiwix-' + theme.replace(/_.*$/, '') + '-description');
+ if (description) description.style.display = 'block';
// If there is no ContentTheme or we are applying a different ContentTheme, remove any previously applied ContentTheme
if (oldContentTheme && oldContentTheme !== contentTheme) {
iframe.classList.remove(oldContentTheme);