Fix PWA-Reload: __BUILD_TIME__ und version.txt aus selber Quelle; Fix QuickLinkIcon custom icons

This commit is contained in:
2026-06-04 09:36:30 +02:00
parent 8946152012
commit 414fba39c7
4 changed files with 52 additions and 52 deletions

View File

@@ -3,17 +3,13 @@ import ReactDOM from 'react-dom/client'
import App from './App.jsx'
// ── Auto-Reload bei neuem Build ───────────────────────────────────────────────
// Regeln:
// - Neuer Build wird erkannt → nur Flag setzen (window.__newBuildAvailable)
// - Reload passiert NUR:
// a) beim Öffnen der App (App kommt aus Hintergrund in den Vordergrund)
// b) beim Klick auf "Dashboard" (in App.jsx geprüft)
// - NIEMALS während einer Eingabe oder bei ungespeicherten Feldern
// __BUILD_TIME__ wird von Vite zur Build-Zeit aus version.txt gebacken.
// /api/build-time liefert denselben Wert vom Server.
// Wenn sie abweichen → neues Build wurde deployed → Reload.
// Kein localStorage, keine Race-Condition.
const MY_BUILD_TIME = __BUILD_TIME__;
window.__newBuildAvailable = false;
const STORED_KEY = 'dd_build_time';
// Läuft gerade eine Eingabe? (Fokus auf Eingabefeld)
function isUserTyping() {
const el = document.activeElement;
if (!el) return false;
@@ -21,7 +17,6 @@ function isUserTyping() {
return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;
}
// Stehen irgendwo ungespeicherte Eingaben in Textfeldern?
function hasUnsavedInput() {
const fields = document.querySelectorAll('input, textarea');
for (const f of fields) {
@@ -40,21 +35,20 @@ async function getBuildTime() {
} catch { return null; }
}
// Prüft die Build-Zeit und setzt nur das Flag (lädt nie von selbst)
async function checkBuild() {
const bt = await getBuildTime();
if (!bt) return;
const stored = localStorage.getItem(STORED_KEY);
if (!stored) {
localStorage.setItem(STORED_KEY, bt);
} else if (stored !== bt) {
localStorage.setItem(STORED_KEY, bt);
// Prüft ob Server-Build != Bundle-Build → Flag setzen
// reloadNow: sofort laden wenn kein Input aktiv (für App-Fokus)
async function checkBuild({ reloadNow = false } = {}) {
const serverBt = await getBuildTime();
if (!serverBt) return;
if (serverBt !== MY_BUILD_TIME) {
window.__newBuildAvailable = true;
if (reloadNow && !isUserTyping() && !hasUnsavedInput()) {
window.location.reload();
}
}
}
// Sicherer Reload: nur wenn neuer Build da UND keine Eingabe aktiv/ungespeichert
// Wird von App.jsx beim Dashboard-Klick aufgerufen. Gibt true zurück wenn neu geladen wird.
// Sicherer Reload bei Seitenwechsel (aufgerufen aus App.jsx setActive)
window.__safeReloadIfNewBuild = function () {
if (!window.__newBuildAvailable) return false;
if (isUserTyping() || hasUnsavedInput()) return false;
@@ -62,32 +56,26 @@ window.__safeReloadIfNewBuild = function () {
return true;
};
// Beim Start einmal prüfen (App-Öffnen Fall 1: Kaltstart)
// Beim Start prüfen (kein sofortiger Reload Seite lädt gerade erst)
checkBuild();
// Im Hintergrund alle 60s nur das Flag aktualisieren
// Im Hintergrund alle 60s
setInterval(() => checkBuild(), 60_000);
// App-Öffnen Fall 2: App kommt aus dem Hintergrund zurück in den Vordergrund
document.addEventListener('visibilitychange', async () => {
// App kommt in den Vordergrund → prüfen und bei Bedarf sofort laden
// (PWA vom Homescreen öffnen / aus dem Hintergrund holen)
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
await checkBuild();
// Nur laden wenn der User nicht gerade tippt und nichts ungespeichert ist
if (!isUserTyping() && !hasUnsavedInput()) {
window.__safeReloadIfNewBuild();
}
checkBuild({ reloadNow: true });
}
});
// ── Service Worker ────────────────────────────────────────────────────────────
if ('serviceWorker' in navigator) {
navigator.serviceWorker.addEventListener('message', (e) => {
if (e.data?.type === 'SW_ACTIVATED') {
window.__newBuildAvailable = true; // nur merken
}
if (e.data?.type === 'SW_ACTIVATED') window.__newBuildAvailable = true;
});
navigator.serviceWorker.register('/sw.js').then(reg => {
// Browser regelmäßig nach neuem SW suchen lassen
setInterval(() => reg.update().catch(()=>{}), 60_000);
if (reg.waiting) reg.waiting.postMessage('SKIP_WAITING');
reg.addEventListener('updatefound', () => {