diff --git a/web/index.html b/web/index.html index 0267263e..a2293b49 100644 --- a/web/index.html +++ b/web/index.html @@ -14,7 +14,7 @@ - + @@ -54,7 +54,7 @@ background-color: #f5f5f5; } - html.ntfy-dark { + html.dark { background-color: #212121; } @@ -71,11 +71,11 @@ transition: opacity 0.1s ease-out; } - html.ntfy-dark #splash { + html.dark #splash { background-color: #212121; } - #splash.ntfy-splash-hidden { + #splash.splash-hidden { opacity: 0; pointer-events: none; } @@ -84,10 +84,10 @@ width: 112px; height: 112px; /* Gently pulse while loading; src/app/splash.js stops this and fades the logo out. */ - animation: ntfy-splash-pulse 1.4s ease-in-out infinite; + animation: splash-pulse 1.4s ease-in-out infinite; } - @keyframes ntfy-splash-pulse { + @keyframes splash-pulse { 0%, 100% { opacity: 1; @@ -117,7 +117,7 @@ var prefersDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; var dark = stored === "dark" || ((!stored || stored === "system") && prefersDark); if (dark) { - document.documentElement.classList.add("ntfy-dark"); + document.documentElement.classList.add("dark"); } } catch (e) { /* localStorage/matchMedia unavailable -- fall back to the default light splash */ @@ -135,7 +135,7 @@
diff --git a/web/public/static/images/main_list_icon.svg b/web/public/static/images/main_list_icon.svg deleted file mode 100644 index 12adf157..00000000 --- a/web/public/static/images/main_list_icon.svg +++ /dev/null @@ -1,171 +0,0 @@ - - - - diff --git a/web/public/static/images/mask-icon.svg b/web/public/static/images/ntfy-mask.svg similarity index 100% rename from web/public/static/images/mask-icon.svg rename to web/public/static/images/ntfy-mask.svg diff --git a/web/public/static/images/ntfy-splash.svg b/web/public/static/images/ntfy-splash.svg new file mode 100644 index 00000000..a2815598 --- /dev/null +++ b/web/public/static/images/ntfy-splash.svg @@ -0,0 +1,13 @@ + diff --git a/web/src/app/notificationUtils.js b/web/src/app/notificationUtils.js index 2453075a..0fb1ef96 100644 --- a/web/src/app/notificationUtils.js +++ b/web/src/app/notificationUtils.js @@ -49,7 +49,7 @@ export const isImage = (attachment) => { }; export const icon = "/static/images/ntfy.png"; -export const badge = "/static/images/mask-icon.svg"; +export const badge = "/static/images/ntfy-mask.svg"; /** * Computes a unique notification tag scoped by baseUrl, topic, and sequence ID. diff --git a/web/src/app/splash.js b/web/src/app/splash.js index 11af12e8..85d9fffe 100644 --- a/web/src/app/splash.js +++ b/web/src/app/splash.js @@ -35,7 +35,7 @@ const fadeOutAndRemove = () => { // Phase 2: once the logo is gone, lift the background to fade the app in, then remove the node. setTimeout(() => { - splash.classList.add("ntfy-splash-hidden"); + splash.classList.add("splash-hidden"); const remove = () => splash.remove(); // Only react to the background's own opacity transition -- the logo's transitionend bubbles up // here too, and would otherwise remove the splash before the app has finished fading in. diff --git a/web/src/app/transition.js b/web/src/app/transition.js index 314ea218..641d22a7 100644 --- a/web/src/app/transition.js +++ b/web/src/app/transition.js @@ -14,20 +14,32 @@ const fadeOutRoot = () => { return node; }; +// Fade #root back in, then remove the inline styles we added so nothing is left behind on the +// element -- otherwise the lingering `transition` would silently animate any future opacity change +// to #root. Uses setTimeout (not requestAnimationFrame) so a backgrounded tab can't strand #root +// at opacity 0; rAF can be paused entirely in background tabs, while timers still fire. +const fadeInRoot = () => { + const node = document.getElementById("root"); + if (!node) { + return; + } + node.style.opacity = "1"; + setTimeout(() => { + node.style.transition = ""; + node.style.opacity = ""; + }, FADE_MS); +}; + // Fade the app out, run a client-side navigation, then fade the new page back in. Used for // app -> login/signup, which stay within the same document (no reload). export const fadeNavigate = (navigate, to) => { - const node = fadeOutRoot(); - if (!node) { + if (!fadeOutRoot()) { navigate(to); return; } setTimeout(() => { navigate(to); - // Fade back in on the next frame, once the new page has rendered. - requestAnimationFrame(() => { - node.style.opacity = "1"; - }); + fadeInRoot(); }, FADE_MS); }; diff --git a/web/src/components/App.jsx b/web/src/components/App.jsx index 0bc8c3c4..cf22158e 100644 --- a/web/src/components/App.jsx +++ b/web/src/components/App.jsx @@ -54,7 +54,7 @@ const App = () => { if (themePreference === undefined) { return; } - document.documentElement.classList.toggle("ntfy-dark", isDark); + document.documentElement.classList.toggle("dark", isDark); }, [isDark, themePreference]); // Safety net: never let the splash trap the UI if no route hides it (e.g. an unmatched path).