import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.jsx' // ── Auto-Reload bei neuem Build ─────────────────────────────────────────────── // __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; function isUserTyping() { const el = document.activeElement; if (!el) return false; const tag = el.tagName; return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable; } function hasUnsavedInput() { const fields = document.querySelectorAll('input, textarea'); for (const f of fields) { const isText = f.tagName === 'TEXTAREA' || ['text','search','url','email','number','password','tel'].includes(f.type); if (isText && f.value && f.value.trim() !== '') return true; } return false; } async function getBuildTime() { try { const r = await fetch('/api/build-time', { cache: 'no-store' }); const { buildTime } = await r.json(); return buildTime; } catch { return null; } } // 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 bei Seitenwechsel (aufgerufen aus App.jsx setActive) window.__safeReloadIfNewBuild = function () { if (!window.__newBuildAvailable) return false; if (isUserTyping() || hasUnsavedInput()) return false; window.location.reload(); return true; }; // Beim Start prüfen (kein sofortiger Reload – Seite lädt gerade erst) checkBuild(); // Im Hintergrund alle 60s setInterval(() => checkBuild(), 60_000); // 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') { checkBuild({ reloadNow: true }); } }); // ── Service Worker ──────────────────────────────────────────────────────────── if ('serviceWorker' in navigator) { navigator.serviceWorker.addEventListener('message', (e) => { if (e.data?.type === 'SW_ACTIVATED') window.__newBuildAvailable = true; }); navigator.serviceWorker.register('/sw.js').then(reg => { setInterval(() => reg.update().catch(()=>{}), 60_000); if (reg.waiting) reg.waiting.postMessage('SKIP_WAITING'); reg.addEventListener('updatefound', () => { const nw = reg.installing; nw?.addEventListener('statechange', () => { if (nw.state === 'installed') nw.postMessage('SKIP_WAITING'); }); }); }).catch(()=>{}); } ReactDOM.createRoot(document.getElementById('root')).render( )