Fix: doppelte SW-Registrierung entfernt, Reload bei App-Fokus; Schnellzugriff gleichgross; Kalender ohne Komma
This commit is contained in:
@@ -17,14 +17,5 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/main.jsx"></script>
|
<script type="module" src="/src/main.jsx"></script>
|
||||||
<script>
|
|
||||||
if ('serviceWorker' in navigator) {
|
|
||||||
window.addEventListener('load', () => {
|
|
||||||
navigator.serviceWorker.register('/sw.js')
|
|
||||||
.then(r => console.log('SW registriert:', r.scope))
|
|
||||||
.catch(e => console.warn('SW Fehler:', e));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -459,7 +459,7 @@ function QuickLinksCarousel({ links }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (pageCount <= 1) return (
|
if (pageCount <= 1) return (
|
||||||
<div style={{ display:'grid', gridTemplateColumns:`repeat(${perRow}, 1fr)`, gap, justifyItems:'center' }}>
|
<div style={{ display:'grid', gridTemplateColumns:`repeat(${perRow}, 1fr)`, gap }}>
|
||||||
{links.map(l => <QuickLinkIcon key={l.id} l={l}/>)}
|
{links.map(l => <QuickLinkIcon key={l.id} l={l}/>)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -476,7 +476,6 @@ function QuickLinksCarousel({ links }) {
|
|||||||
display:'grid',
|
display:'grid',
|
||||||
gridTemplateColumns:`repeat(${perRow}, 1fr)`,
|
gridTemplateColumns:`repeat(${perRow}, 1fr)`,
|
||||||
gridTemplateRows:'repeat(2, auto)',
|
gridTemplateRows:'repeat(2, auto)',
|
||||||
justifyItems:'center',
|
|
||||||
gap, flexShrink:0, scrollSnapAlign:'start',
|
gap, flexShrink:0, scrollSnapAlign:'start',
|
||||||
width:'100%', minWidth:'100%',
|
width:'100%', minWidth:'100%',
|
||||||
}}>
|
}}>
|
||||||
@@ -507,7 +506,7 @@ function QuickLinkIcon({ l }) {
|
|||||||
style={{ display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:3,
|
style={{ display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:3,
|
||||||
padding:'4px 2px', background:'rgba(255,255,255,0.04)',
|
padding:'4px 2px', background:'rgba(255,255,255,0.04)',
|
||||||
border:'1px solid rgba(255,255,255,0.08)', borderRadius:10,
|
border:'1px solid rgba(255,255,255,0.08)', borderRadius:10,
|
||||||
textDecoration:'none', height:48, cursor:'pointer' }}>
|
textDecoration:'none', height:48, width:'100%', boxSizing:'border-box', cursor:'pointer' }}>
|
||||||
{l.icon && l.icon.startsWith('http')
|
{l.icon && l.icon.startsWith('http')
|
||||||
? <img src={l.icon} alt="" style={{width:16,height:16,objectFit:'contain'}} onError={e=>e.target.style.display='none'}/>
|
? <img src={l.icon} alt="" style={{width:16,height:16,objectFit:'contain'}} onError={e=>e.target.style.display='none'}/>
|
||||||
: <span style={{ fontSize:16 }}>{l.icon}</span>}
|
: <span style={{ fontSize:16 }}>{l.icon}</span>}
|
||||||
@@ -2381,7 +2380,7 @@ export default function App() {
|
|||||||
const [user,setUser]=useState(null);
|
const [user,setUser]=useState(null);
|
||||||
const [active,setActiveRaw]=useState('dashboard');
|
const [active,setActiveRaw]=useState('dashboard');
|
||||||
const setActive = (page) => {
|
const setActive = (page) => {
|
||||||
import('./main.jsx').then(m => m.reloadIfNewBuild?.()).catch(()=>{});
|
if (window.__newBuildAvailable) { window.location.reload(); return; }
|
||||||
setActiveRaw(page);
|
setActiveRaw(page);
|
||||||
};
|
};
|
||||||
const [toastMsg,setToastMsg]=useState({msg:'',type:'success'});
|
const [toastMsg,setToastMsg]=useState({msg:'',type:'success'});
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ export default function CalendarWidget() {
|
|||||||
<span style={{ color:'rgba(255,255,255,0.35)', fontFamily:'monospace', fontSize:9, flexShrink:0 }}>
|
<span style={{ color:'rgba(255,255,255,0.35)', fontFamily:'monospace', fontSize:9, flexShrink:0 }}>
|
||||||
{nextEvent.allDay
|
{nextEvent.allDay
|
||||||
? nextEvent.dtstart.toLocaleDateString('de-DE',{day:'numeric',month:'short'})
|
? nextEvent.dtstart.toLocaleDateString('de-DE',{day:'numeric',month:'short'})
|
||||||
: nextEvent.dtstart.toLocaleString('de-DE',{day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'})
|
: `${nextEvent.dtstart.toLocaleDateString('de-DE',{day:'2-digit',month:'2-digit'})} ${nextEvent.dtstart.toLocaleTimeString('de-DE',{hour:'2-digit',minute:'2-digit'})}`
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,13 +2,12 @@ import React from 'react'
|
|||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import App from './App.jsx'
|
import App from './App.jsx'
|
||||||
|
|
||||||
// ── Build-Zeit Check ──────────────────────────────────────────────────────────
|
// ── Build-Zeit Check & Auto-Reload ───────────────────────────────────────────
|
||||||
// Globale Variable – synchron lesbar, kein dynamischer Import nötig
|
|
||||||
window.__newBuildAvailable = false;
|
window.__newBuildAvailable = false;
|
||||||
|
|
||||||
const STORED_KEY = 'dd_build_time';
|
const STORED_KEY = 'dd_build_time';
|
||||||
|
|
||||||
async function checkBuildTime() {
|
async function checkBuildTime({ reloadIfChanged = false } = {}) {
|
||||||
try {
|
try {
|
||||||
const r = await fetch('/api/build-time', { cache: 'no-store' });
|
const r = await fetch('/api/build-time', { cache: 'no-store' });
|
||||||
const { buildTime } = await r.json();
|
const { buildTime } = await r.json();
|
||||||
@@ -18,33 +17,42 @@ async function checkBuildTime() {
|
|||||||
} else if (stored !== buildTime) {
|
} else if (stored !== buildTime) {
|
||||||
localStorage.setItem(STORED_KEY, buildTime);
|
localStorage.setItem(STORED_KEY, buildTime);
|
||||||
window.__newBuildAvailable = true;
|
window.__newBuildAvailable = true;
|
||||||
|
// Wenn explizit gewünscht (App-Fokus): sofort neu laden
|
||||||
|
if (reloadIfChanged) window.location.reload();
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sofort beim Start prüfen, dann alle 60s
|
// Beim Start prüfen
|
||||||
checkBuildTime();
|
checkBuildTime();
|
||||||
setInterval(checkBuildTime, 60_000);
|
// Alle 60s im Hintergrund
|
||||||
|
setInterval(() => checkBuildTime(), 60_000);
|
||||||
|
|
||||||
|
// Wenn die App/der Tab wieder in den Vordergrund kommt → prüfen und ggf. sofort neu laden
|
||||||
|
// Das deckt den Fall ab: PWA vom Homescreen öffnen
|
||||||
|
document.addEventListener('visibilitychange', () => {
|
||||||
|
if (document.visibilityState === 'visible') {
|
||||||
|
checkBuildTime({ reloadIfChanged: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
window.addEventListener('focus', () => {
|
||||||
|
checkBuildTime({ reloadIfChanged: true });
|
||||||
|
});
|
||||||
|
|
||||||
// ── Service Worker ────────────────────────────────────────────────────────────
|
// ── Service Worker ────────────────────────────────────────────────────────────
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.register('/sw.js').then(reg => {
|
navigator.serviceWorker.register('/sw.js').then(reg => {
|
||||||
if (reg.waiting) reg.waiting.postMessage('SKIP_WAITING');
|
if (reg.waiting) reg.waiting.postMessage('SKIP_WAITING');
|
||||||
|
|
||||||
reg.addEventListener('updatefound', () => {
|
reg.addEventListener('updatefound', () => {
|
||||||
const nw = reg.installing;
|
const nw = reg.installing;
|
||||||
nw?.addEventListener('statechange', () => {
|
nw?.addEventListener('statechange', () => {
|
||||||
if (nw.state === 'installed') {
|
if (nw.state === 'installed') nw.postMessage('SKIP_WAITING');
|
||||||
nw.postMessage('SKIP_WAITING');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Neuer SW aktiv → beim nächsten Seitenwechsel reloaden
|
|
||||||
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
||||||
window.__newBuildAvailable = true;
|
window.__newBuildAvailable = true;
|
||||||
});
|
});
|
||||||
});
|
}).catch(()=>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||||
|
|||||||
Reference in New Issue
Block a user