workaround for a race condition between dojo.parse() and tt-rss loading proper day/night css on startup because of firefox async CSS loader

This commit is contained in:
Andrew Dolgov 2019-12-15 11:57:26 +03:00
parent 0d6add5d7f
commit 07f4878d59
5 changed files with 92 additions and 52 deletions

View File

@ -48,8 +48,6 @@
$theme = get_pref("USER_CSS_THEME", false, false); $theme = get_pref("USER_CSS_THEME", false, false);
if ($theme && theme_exists("$theme")) { if ($theme && theme_exists("$theme")) {
echo stylesheet_tag(get_theme_path($theme), 'theme_css'); echo stylesheet_tag(get_theme_path($theme), 'theme_css');
} else {
echo stylesheet_tag("css/default.css", 'theme_css');
} }
} }
?> ?>
@ -116,11 +114,23 @@
?> ?>
</script> </script>
<style type="text/css">
@media (prefers-color-scheme: dark) {
body {
background : #303030;
}
}
body.css_loading * {
display : none;
}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="referrer" content="no-referrer"/> <meta name="referrer" content="no-referrer"/>
</head> </head>
<body class="flat ttrss_main ttrss_index"> <body class="flat ttrss_main ttrss_index css_loading">
<div id="overlay" style="display : block"> <div id="overlay" style="display : block">
<div id="overlay_inner"> <div id="overlay_inner">

View File

@ -9,7 +9,6 @@ define(["dojo/_base/declare"], function (declare) {
hotkey_prefix_timeout: 0, hotkey_prefix_timeout: 0,
constructor: function() { constructor: function() {
window.onerror = this.Error.onWindowError; window.onerror = this.Error.onWindowError;
this.setupNightModeDetection();
}, },
getInitParam: function(k) { getInitParam: function(k) {
return this._initParams[k]; return this._initParams[k];
@ -17,30 +16,47 @@ define(["dojo/_base/declare"], function (declare) {
setInitParam: function(k, v) { setInitParam: function(k, v) {
this._initParams[k] = v; this._initParams[k] = v;
}, },
nightModeChanged: function(is_night) { nightModeChanged: function(is_night, link) {
console.log("night mode changed to", is_night); console.log("night mode changed to", is_night);
const link = $("theme_css");
if (link) { if (link) {
const css_override = is_night ? "themes/night.css" : "css/default.css";
if (link.getAttribute("data-orig-href").indexOf("css/default.css") !== -1) { link.setAttribute("href", css_override + "?" + Date.now());
const css_override = is_night ? "themes/night.css" : "css/default.css";
link.setAttribute("href", css_override + "?" + Date.now());
}
} }
}, },
setupNightModeDetection: function() { setupNightModeDetection: function(callback) {
if (window.matchMedia) { if (!$("theme_css")) {
const mql = window.matchMedia('(prefers-color-scheme: dark)'); const mql = window.matchMedia('(prefers-color-scheme: dark)');
try { try {
mql.addEventListener("change", () => { mql.addEventListener("change", () => {
this.nightModeChanged(mql.matches); this.nightModeChanged(mql.matches, $("theme_auto_css"));
}); });
} catch (e) {} } catch (e) {
console.warn("exception while trying to set MQL event listener");
}
this.nightModeChanged(mql.matches); const link = new Element("link", {
rel: "stylesheet",
id: "theme_auto_css"
});
if (callback) {
link.onload = function () {
document.querySelector("body").removeClassName("css_loading");
callback();
};
link.onerror = function(event) {
alert("Fatal error while loading application stylesheet: " + link.getAttribute("href"));
}
}
this.nightModeChanged(mql.matches, link);
document.querySelector("head").appendChild(link);
} else {
if (callback) callback();
} }
}, },
enableCsrfSupport: function() { enableCsrfSupport: function() {

View File

@ -63,19 +63,21 @@ require(["dojo/_base/kernel",
try { try {
const _App = declare("fox.App", AppBase, { const _App = declare("fox.App", AppBase, {
constructor: function() { constructor: function() {
parser.parse(); this.setupNightModeDetection(() => {
parser.parse();
this.setLoadingProgress(50); this.setLoadingProgress(50);
const clientTzOffset = new Date().getTimezoneOffset() * 60; const clientTzOffset = new Date().getTimezoneOffset() * 60;
const params = {op: "rpc", method: "sanityCheck", clientTzOffset: clientTzOffset}; const params = {op: "rpc", method: "sanityCheck", clientTzOffset: clientTzOffset};
xhrPost("backend.php", params, (transport) => { xhrPost("backend.php", params, (transport) => {
try { try {
this.backendSanityCallback(transport); this.backendSanityCallback(transport);
} catch (e) { } catch (e) {
this.Error.report(e); this.Error.report(e);
} }
});
}); });
}, },
initSecondStage: function() { initSecondStage: function() {

View File

@ -67,33 +67,35 @@ require(["dojo/_base/kernel",
_widescreen_mode: false, _widescreen_mode: false,
hotkey_actions: {}, hotkey_actions: {},
constructor: function () { constructor: function () {
parser.parse(); this.setupNightModeDetection(() => {
parser.parse();
if (!this.checkBrowserFeatures()) if (!this.checkBrowserFeatures())
return; return;
this.setLoadingProgress(30); this.setLoadingProgress(30);
this.initHotkeyActions(); this.initHotkeyActions();
const a = document.createElement('audio'); const a = document.createElement('audio');
const hasAudio = !!a.canPlayType; const hasAudio = !!a.canPlayType;
const hasSandbox = "sandbox" in document.createElement("iframe"); const hasSandbox = "sandbox" in document.createElement("iframe");
const hasMp3 = !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, '')); const hasMp3 = !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
const clientTzOffset = new Date().getTimezoneOffset() * 60; const clientTzOffset = new Date().getTimezoneOffset() * 60;
const params = { const params = {
op: "rpc", method: "sanityCheck", hasAudio: hasAudio, op: "rpc", method: "sanityCheck", hasAudio: hasAudio,
hasMp3: hasMp3, hasMp3: hasMp3,
clientTzOffset: clientTzOffset, clientTzOffset: clientTzOffset,
hasSandbox: hasSandbox hasSandbox: hasSandbox
}; };
xhrPost("backend.php", params, (transport) => { xhrPost("backend.php", params, (transport) => {
try { try {
App.backendSanityCallback(transport); App.backendSanityCallback(transport);
} catch (e) { } catch (e) {
App.Error.report(e); App.Error.report(e);
} }
});
}); });
}, },
checkBrowserFeatures: function() { checkBrowserFeatures: function() {

View File

@ -40,8 +40,6 @@
$theme = get_pref("USER_CSS_THEME", false, false); $theme = get_pref("USER_CSS_THEME", false, false);
if ($theme && theme_exists("$theme")) { if ($theme && theme_exists("$theme")) {
echo stylesheet_tag(get_theme_path($theme), 'theme_css'); echo stylesheet_tag(get_theme_path($theme), 'theme_css');
} else {
echo stylesheet_tag("css/default.css", 'theme_css');
} }
} }
?> ?>
@ -99,10 +97,22 @@
?> ?>
</script> </script>
<style type="text/css">
@media (prefers-color-scheme: dark) {
body {
background : #303030;
}
}
body.css_loading * {
display : none;
}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head> </head>
<body class="flat ttrss_main ttrss_prefs"> <body class="flat ttrss_main ttrss_prefs css_loading">
<div id="notify" class="notify"></div> <div id="notify" class="notify"></div>
<div id="cmdline" style="display : none"></div> <div id="cmdline" style="display : none"></div>