fix: reduce page transition lag on Android (closes #48)
Two causes of ~1s navigation delay fixed: 1. glass.css Section 19 was extending the page-in animation from 0.20s to 0.30s using spring easing. Reverted to 0.20s in / 0.12s out. 2. During transitions, dozens of backdrop-filter layers (widgets, cards, inputs, toolbars) were composited simultaneously for both the outgoing and incoming page, overloading mid-range Android GPUs. Added html.navigating class: router.js sets it at transition start, glass.css overrides all app-content backdrop-filters to none while active, animationend removes it once the in-animation completes.
This commit is contained in:
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.20.6] - 2026-04-16
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Android PWA: page transitions were taking ~1 second, making navigation feel sluggish. Two root causes addressed: (1) `glass.css` extended the page-in animation duration from `0.20s` to `0.30s` with a spring easing (`ease-glass`) — reverted to `0.20s` in and `0.12s` out to match the layout baseline. (2) During transitions, dozens of `backdrop-filter` composited layers (widgets, task cards, inputs, toolbars) were all rendered simultaneously for both the outgoing and incoming page, overwhelming mid-range Android GPUs. Added `html.navigating` state: `router.js` sets this class for the duration of each page transition, and `glass.css` overrides all `backdrop-filter` in the content area to `none` for that window, then restores them once the animation ends (closes #48).
|
||||||
|
|
||||||
## [0.20.5] - 2026-04-16
|
## [0.20.5] - 2026-04-16
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "oikos",
|
"name": "oikos",
|
||||||
"version": "0.20.5",
|
"version": "0.20.6",
|
||||||
"description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.",
|
"description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.",
|
||||||
"main": "server/index.js",
|
"main": "server/index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -239,6 +239,10 @@ async function renderPage(route, previousPath = null) {
|
|||||||
const outClass = direction === 'right' ? 'page-transition--out-left' : 'page-transition--out-right';
|
const outClass = direction === 'right' ? 'page-transition--out-left' : 'page-transition--out-right';
|
||||||
const inClass = direction === 'right' ? 'page-transition--in-right' : 'page-transition--in-left';
|
const inClass = direction === 'right' ? 'page-transition--in-right' : 'page-transition--in-left';
|
||||||
|
|
||||||
|
// Performance: backdrop-filter während Übergang deaktivieren (Android-Optimierung).
|
||||||
|
// glass.css setzt alle backdrop-filter im app-content auf none solange diese Klasse aktiv ist.
|
||||||
|
document.documentElement.classList.add('navigating');
|
||||||
|
|
||||||
// Alte Seite kurz ausfaden, falls vorhanden
|
// Alte Seite kurz ausfaden, falls vorhanden
|
||||||
const oldPage = content.querySelector('.page-transition');
|
const oldPage = content.querySelector('.page-transition');
|
||||||
if (oldPage) {
|
if (oldPage) {
|
||||||
@@ -259,7 +263,18 @@ async function renderPage(route, previousPath = null) {
|
|||||||
pageWrapper.style.opacity = '';
|
pageWrapper.style.opacity = '';
|
||||||
pageWrapper.classList.add(inClass);
|
pageWrapper.classList.add(inClass);
|
||||||
|
|
||||||
|
// navigating-Klasse nach Ende der Einblend-Animation entfernen.
|
||||||
|
// Fallback-Timeout falls animationend nicht feuert (z.B. prefers-reduced-motion).
|
||||||
|
const navEndTimeout = setTimeout(() => {
|
||||||
|
document.documentElement.classList.remove('navigating');
|
||||||
|
}, 300);
|
||||||
|
pageWrapper.addEventListener('animationend', () => {
|
||||||
|
clearTimeout(navEndTimeout);
|
||||||
|
document.documentElement.classList.remove('navigating');
|
||||||
|
}, { once: true });
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
document.documentElement.classList.remove('navigating');
|
||||||
console.error('[Router] Seiten-Render-Fehler:', err);
|
console.error('[Router] Seiten-Render-Fehler:', err);
|
||||||
renderError(app, err);
|
renderError(app, err);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-2
@@ -400,16 +400,27 @@ textarea.form-input {
|
|||||||
* ================================================================ */
|
* ================================================================ */
|
||||||
.page-transition--in-right,
|
.page-transition--in-right,
|
||||||
.page-transition--in-left {
|
.page-transition--in-left {
|
||||||
animation-duration: 0.30s;
|
animation-duration: 0.20s;
|
||||||
animation-timing-function: var(--ease-glass);
|
animation-timing-function: var(--ease-glass);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-transition--out-left,
|
.page-transition--out-left,
|
||||||
.page-transition--out-right {
|
.page-transition--out-right {
|
||||||
animation-duration: 0.14s;
|
animation-duration: 0.12s;
|
||||||
animation-timing-function: var(--ease-out);
|
animation-timing-function: var(--ease-out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Performance: backdrop-filter deaktivieren während Seitenübergängen.
|
||||||
|
* Auf Android verursachen viele gleichzeitige backdrop-filter-Layer
|
||||||
|
* (Widgets, Cards, Inputs) hohen GPU-Aufwand → Transition wirkt träge.
|
||||||
|
* html.navigating wird von router.js für die Dauer des Übergangs gesetzt. */
|
||||||
|
html.navigating .app-content *,
|
||||||
|
html.navigating .app-content *::before,
|
||||||
|
html.navigating .app-content *::after {
|
||||||
|
backdrop-filter: none !important;
|
||||||
|
-webkit-backdrop-filter: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================================
|
/* ================================================================
|
||||||
* 20. List-Stagger — Spring Timing
|
* 20. List-Stagger — Spring Timing
|
||||||
* ================================================================ */
|
* ================================================================ */
|
||||||
|
|||||||
Reference in New Issue
Block a user