From f574247452f6e99fe33fc977eddff0e2e8ec1637 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Tue, 27 Sep 2022 11:02:57 +0200 Subject: [PATCH] Fix the white/black theme switch in Chrome Chrome doesn't fire twice the load event on a stylesheet when the disabled attribute is toggled (enabled => disabled => enabled) --- src/theme.ts | 56 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/src/theme.ts b/src/theme.ts index 06267b4a9e..f932cfe872 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -279,26 +279,48 @@ export async function setTheme(theme?: string): Promise { resolve(); }; - // turns out that Firefox preloads the CSS for link elements with - // the disabled attribute, but Chrome doesn't. + const isStyleSheetLoaded = () => Boolean( + [...document.styleSheets] + .find(styleSheet => styleSheet?.href === styleElements[stylesheetName].href), + ); - let cssLoaded = false; - - styleElements[stylesheetName].onload = () => { - switchTheme(); - }; - - for (let i = 0; i < document.styleSheets.length; i++) { - const ss = document.styleSheets[i]; - if (ss && ss.href === styleElements[stylesheetName].href) { - cssLoaded = true; - break; + function waitForStyleSheetLoading() { + // turns out that Firefox preloads the CSS for link elements with + // the disabled attribute, but Chrome doesn't. + if (isStyleSheetLoaded()) { + switchTheme(); + return; } + + let counter = 0; + + // In case of theme toggling (white => black => white) + // Chrome doesn't fire the `load` event when the white theme is selected the second times + const intervalId = setInterval(() => { + if (isStyleSheetLoaded()) { + clearInterval(intervalId); + styleElements[stylesheetName].onload = undefined; + styleElements[stylesheetName].onerror = undefined; + switchTheme(); + } + + // Avoid to be stuck in an endless loop if there is an issue in the stylesheet loading + counter++; + if (counter === 5) { + clearInterval(intervalId); + } + }, 100); + + styleElements[stylesheetName].onload = () => { + clearInterval(intervalId); + switchTheme(); + }; + + styleElements[stylesheetName].onerror = () => { + clearInterval(intervalId); + }; } - if (cssLoaded) { - styleElements[stylesheetName].onload = undefined; - switchTheme(); - } + waitForStyleSheetLoading(); }); }