UX: Step 4 wieder strikt + Long-Press auf FAB = Status-Modal, SW by-v1093
- Step 4 wieder strikt: alle 3 (expenses + routes + notes) müssen im Cache sein, sonst weiß. 5/5 Braun = wirklich alles bereit. - Long-Press (600ms) auf #worlds-fab öffnet das Status-Modal mit detaillierter 5-Punkte-Checkliste + 'Fehlende nachladen'-Button. Normaler Click bleibt unverändert (FAB-Schnellaktion). Wenn Long-Press feuert, wird nachfolgender Click unterdrückt. - _bindLongPress wird mehrfach gebunden falls FAB neu gerendert wird (data-lpBound verhindert Doppel-Binding).
This commit is contained in:
parent
66d2d96a2f
commit
61af803d99
5 changed files with 43 additions and 18 deletions
|
|
@ -410,7 +410,7 @@ async def serve_media(path: str, request: _Request):
|
|||
raise _HE(404, "Nicht gefunden.")
|
||||
return _media_response(filepath)
|
||||
|
||||
APP_VER = "1092" # muss mit APP_VER in app.js übereinstimmen
|
||||
APP_VER = "1093" # muss mit APP_VER in app.js übereinstimmen
|
||||
|
||||
@app.get("/.well-known/assetlinks.json")
|
||||
async def assetlinks():
|
||||
|
|
|
|||
|
|
@ -101,9 +101,9 @@
|
|||
</script>
|
||||
|
||||
<!-- CSS: Reihenfolge ist wichtig — ?v= zwingt Browser zur Neuladung -->
|
||||
<link rel="stylesheet" href="/css/design-system.css?v=1092">
|
||||
<link rel="stylesheet" href="/css/layout.css?v=1092">
|
||||
<link rel="stylesheet" href="/css/components.css?v=1092">
|
||||
<link rel="stylesheet" href="/css/design-system.css?v=1093">
|
||||
<link rel="stylesheet" href="/css/layout.css?v=1093">
|
||||
<link rel="stylesheet" href="/css/components.css?v=1093">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
@ -625,11 +625,11 @@
|
|||
<div id="modal-container"></div>
|
||||
|
||||
<!-- JS: Reihenfolge ist wichtig — erst Basis, dann Features -->
|
||||
<script src="/js/api.js?v=1092"></script>
|
||||
<script src="/js/ui.js?v=1092"></script>
|
||||
<script src="/js/app.js?v=1092"></script>
|
||||
<script src="/js/worlds.js?v=1092"></script>
|
||||
<script src="/js/offline-indicator.js?v=1092"></script>
|
||||
<script src="/js/api.js?v=1093"></script>
|
||||
<script src="/js/ui.js?v=1093"></script>
|
||||
<script src="/js/app.js?v=1093"></script>
|
||||
<script src="/js/worlds.js?v=1093"></script>
|
||||
<script src="/js/offline-indicator.js?v=1093"></script>
|
||||
|
||||
<!-- Feature-Seiten werden lazy geladen -->
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Router, State-Management, Navigation, Initialisierung.
|
||||
============================================================ */
|
||||
|
||||
const APP_VER = '1092'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VER = '1093'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt
|
||||
window.APP_VER = APP_VER; // global verfügbar für andere Module (z.B. offline-indicator)
|
||||
window.APP_VERSION = APP_VERSION;
|
||||
|
|
|
|||
|
|
@ -63,12 +63,9 @@ window.OfflineIndicator = (() => {
|
|||
const c = await caches.open(CACHE_API).catch(() => null);
|
||||
if (!c) return false;
|
||||
const urls = (await c.keys()).map(r => r.url);
|
||||
const found = [
|
||||
urls.some(u => u.includes('/api/expenses')),
|
||||
urls.some(u => u.includes('/api/routes')),
|
||||
urls.some(u => u.includes('/api/notes')),
|
||||
].filter(Boolean).length;
|
||||
return found >= 2; // 2 von 3 — toleriert wenn z.B. notes 401 lieferte
|
||||
return urls.some(u => u.includes('/api/expenses'))
|
||||
&& urls.some(u => u.includes('/api/routes'))
|
||||
&& urls.some(u => u.includes('/api/notes'));
|
||||
} },
|
||||
|
||||
{ step: 5, title: 'Karten-Kacheln',
|
||||
|
|
@ -257,16 +254,44 @@ window.OfflineIndicator = (() => {
|
|||
}
|
||||
}
|
||||
|
||||
// Long-Press auf #worlds-fab → Status-Modal (normaler Click bleibt = FAB-Aktion)
|
||||
function _bindLongPress() {
|
||||
const fab = document.getElementById('worlds-fab');
|
||||
if (!fab || fab.dataset.lpBound) return;
|
||||
fab.dataset.lpBound = '1';
|
||||
|
||||
let timer = null;
|
||||
let fired = false;
|
||||
const start = () => {
|
||||
fired = false;
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => { fired = true; openStatus(); }, 600);
|
||||
};
|
||||
const cancel = () => clearTimeout(timer);
|
||||
fab.addEventListener('touchstart', start, { passive: true });
|
||||
fab.addEventListener('touchend', cancel);
|
||||
fab.addEventListener('touchmove', cancel);
|
||||
fab.addEventListener('touchcancel',cancel);
|
||||
fab.addEventListener('mousedown', start);
|
||||
fab.addEventListener('mouseup', cancel);
|
||||
fab.addEventListener('mouseleave', cancel);
|
||||
// Wenn Long-Press gefeuert hat, normalen Click verhindern
|
||||
fab.addEventListener('click', e => {
|
||||
if (fired) { e.stopImmediatePropagation(); e.preventDefault(); fired = false; }
|
||||
}, true);
|
||||
}
|
||||
|
||||
function init() {
|
||||
refresh();
|
||||
_prefetchPages();
|
||||
_prefetchTiles();
|
||||
_prefetchData();
|
||||
_bindLongPress();
|
||||
|
||||
// Mehrere Retries für hund-spezifische Daten — _appState.activeDog wird oft
|
||||
// erst nach Login/Hunde-Load gesetzt, manchmal mehrere Sekunden nach Init
|
||||
[2_000, 5_000, 10_000, 20_000].forEach(delay => {
|
||||
setTimeout(() => { _prefetchData(); refresh(); }, delay);
|
||||
setTimeout(() => { _prefetchData(); refresh(); _bindLongPress(); }, delay);
|
||||
});
|
||||
|
||||
if (navigator.serviceWorker) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
============================================================ */
|
||||
|
||||
// ← EINZIGE Stelle für die Version — STATIC_ASSETS und CACHE_VERSION leiten sich ab
|
||||
const VER = '1092';
|
||||
const VER = '1093';
|
||||
const CACHE_VERSION = `by-v${VER}`;
|
||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue