Skip to content

Remove Flash of Incorrect Theme from Wikimedia Vector dark theme #1351

@THEBOSS0369

Description

@THEBOSS0369

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;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug-non-criticalFor bugs that it would be nice to fix rather than critical to fixuser interface

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions