-
-
Notifications
You must be signed in to change notification settings - Fork 164
Description
Remove Flash of Incorrect Style from Wikimedia Vector dark theme
When using Wikimedia vector dark theme, So if we navigate from any page to another or simple reload the page a white flash shows up for 1 - 2 second which creates a jarring effect.
Please refer to this chat for more info PR Chat Link
What i Tried
in app.js file
at line 2156 inside read article function, below this code block
function readArticle (dirEntry) {
if (dirEntry === null || dirEntry === undefined) {
console.error('The directory entry for the requested article was not found (null or undefined)');
uiUtil.spinnerDisplay(false);
return;
}
This code was added
// Hide content during loading if using dark theme
var htmlEl = document.querySelector('html');
var isDark = htmlEl.classList.contains('dark') ||
articleContainer.classList.contains('_invert') ||
articleContainer.classList.contains('_wikiVector');
// Modify iframe directly to prevent white flash
if (isDark) {
// Set background color on the iframe itself
articleContainer.style.backgroundColor = '#e5e5e5';
// Try to inject styles directly into the iframe
try {
if (articleContainer.contentDocument && articleContainer.contentDocument.head) {
var style = articleContainer.contentDocument.createElement('style');
style.textContent = 'html, body { background-color: #e5e5e5 !important; }';
articleContainer.contentDocument.head.appendChild(style);
}
} catch (e) {
console.log('Could not inject styles into iframe yet:', e);
}
// Add listener to handle iframe load events
articleContainer.addEventListener('load', function() {
try {
var iframeDoc = articleContainer.contentDocument;
if (iframeDoc) {
var style = iframeDoc.createElement('style');
style.textContent = 'html, body { background-color: #e5e5e5 !important; }';
if (iframeDoc.head) iframeDoc.head.appendChild(style);
if (iframeDoc.body) iframeDoc.body.style.backgroundColor = '#e5e5e5';
}
} catch (e) {
console.log('Could not access iframe document:', e);
}
}, true);
}
then
at line 2277 under article loader function
this code was added
function articleLoader () {
// Get the currnet theme information
var htmlEl = document.querySelector('html');
var isDark = htmlEl.classList.contains('dark') ||
articleContainer.classList.contains('_invert') ||
articleContainer.classList.contains('_wikiVector');
// Hide content if using dark theme (add content-loading class)
var doc = articleContainer.contentDocument;
if (isDark && doc && doc.body) {
doc.body.classList.add('content-loading');
}
if (selectedArchive.zimType === 'zimit') {
// **var was removed from this line**
doc = articleContainer.contentDocument || null;
if (doc) {
then around 2400 line under articleLoadedSW Function
below this line
// Display the iframe content iframeArticleContent.style.display = ''; articleContainer.style.display = '';
i added this code
// Check if dark theme is being used and remove loading class if present
var htmlEl = document.querySelector('html');
var isDark = htmlEl.classList.contains('dark') ||
articleContainer.classList.contains('_invert') ||
articleContainer.classList.contains('_wikiVector');
if (isDark) {
var doc = iframeArticleContent.contentDocument;
if (doc) {
// Make sure stylesheet is fully loaded first
var kiwixStylesheet = doc.getElementById('kiwixJSTheme');
if (kiwixStylesheet && kiwixStylesheet.sheet) {
// If stylesheet is loaded, show content
setTimeout(function() {
if (doc.body) {
doc.body.classList.remove('content-loading');
}
}, 500);
} else {
// If no stylesheet then wait for it to load
setTimeout(function() {
if (doc.body) {
doc.body.classList.remove('content-loading');
}
}, 1000);
}
}
}
// Deflect drag-and-drop of ZIM file on the iframe to Config
if (!params.disableDragAndDrop) {
// **again here the var was removed**
doc = iframeArticleContent.contentDocument ? iframeArticleContent.contentDocument.documentElement : null;
then in displayArticleContentInIframe function around line 2800 or below
just below this line
if (!isDirEntryExpectedToBeDisplayed(dirEntry)) {
return;
}
this code was added
// Check for dark mode
var iframe = document.getElementById('articleContent');
var htmlEl = document.querySelector('html');
var isDark = htmlEl.classList.contains('dark') ||
iframe.classList.contains('_invert') ||
iframe.classList.contains('_wikiVector');
// Add dark mode style if needed (before injecting content)
if (isDark) {
iframe.style.backgroundColor = '#e5e5e5';
// Add style to the content before injecting it
if (htmlArticle.indexOf('<head>') !== -1) {
htmlArticle = htmlArticle.replace('<head>', '<head><style id="kiwixDarkModeLoader">body { visibility: hidden !important; } html { background-color: #e5e5e5 !important; }</style>');
}
}
then in the same function at last
just above this code
var iframeContentDocument = iframeArticleContent.contentDocument;
if (!iframeContentDocument && window.location.protocol === 'file:') {
uiUtil.systemAlert(translateUI.t('dialog-blocked-fileprotocol') ||
'<p>You seem to be opening kiwix-js with the file:// protocol, which is blocked by your browser for security reasons.</p>' +
'<p>The easiest way to run it is to download and run it as a browser extension (available for free from the vendor store).</p>' +
this code was added
// Remove the dark mode style after a delay
setTimeout(function() {
var doc = iframeArticleContent.contentDocument;
if (doc) {
var style = doc.getElementById('kiwixDarkModeLoader');
if (style) {
style.parentNode.removeChild(style);
}
}
}, 100);
Now for lib/uiutil.js file
in applytheme function
inside this if block
// Note that location.pathname returns the path plus the filename, but is useful because it removes any query string var prefix = (window.location.protocol + '//' + window.location.host + window.location.pathname).replace(/\/[^/]*$/, ''); if (doc) {
this code was added
// Make sure content is hidden while loading if in dark mode
htmlEl = document.querySelector('html');
var isDark = htmlEl.classList.contains('dark') ||
iframe.classList.contains('_invert') ||
iframe.classList.contains('_wikiVector');
// Add a blocking style to prevent content from showing before stylesheet loads
if (isDark && doc) {
// Add inline style to both html and body
if (doc.documentElement) {
doc.documentElement.style.backgroundColor = '#e5e5e5';
}
if (doc.body) {
doc.body.style.backgroundColor = '#e5e5e5';
doc.body.classList.add('content-loading');
}
// Add a style element with higher priority
var blockStyle = doc.createElement('style');
blockStyle.textContent = 'html, body { background-color: #e5e5e5 !important; }';
blockStyle.id = 'temp-dark-style';
doc.head.appendChild(blockStyle);
}
then in same function below this code block
var link = doc.createElement('link');
link.setAttribute('id', 'kiwixJSTheme');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('type', 'text/css');
var safeContentThemeForURL = contentTheme.replace(/[^a-zA-Z0-9_-]/g, '');
link.setAttribute('href', prefix + '/css/kiwixJS' + safeContentThemeForURL + '.css');
this code was added
// To remove loading class
link.onload = function() {
if (isDark && doc && doc.body) {
// Give time for styles to be applied
setTimeout(function() {
// Show content but keep the background color
doc.body.classList.remove('content-loading');
// Remove temporary blocking style only after stylesheet is loaded
var tempStyle = doc.getElementById('temp-dark-style');
if (tempStyle) {
tempStyle.parentNode.removeChild(tempStyle);
}
}, 500);
}
};
and lastly in css/app.css file
this code was added in the very last of the file
/* Prevent white flash in dark mode */
body.content-loading {
visibility: hidden !important;
}
/* Set default dark background for the entire iframe */
.dark iframe,
.dark #articleContainer,
iframe._invert,
iframe._wikiVector {
background-color: #e5e5e5 !important;
}
/* Iframe document should have same background color */
.dark iframe::before,
iframe._invert::before,
iframe._wikiVector::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #e5e5e5 !important;
z-index: 9999;
}