Fix: Media-Uploads direkt ans Netz (kein SW-Clone), SW _nocache-Bypass, Samsung-Dark-Mode-Hint, Update-Button fire-and-forget (SW by-v796)
This commit is contained in:
parent
5949a07b28
commit
209d6703ad
6 changed files with 33 additions and 11 deletions
|
|
@ -327,7 +327,7 @@ MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media")
|
||||||
os.makedirs(MEDIA_DIR, exist_ok=True)
|
os.makedirs(MEDIA_DIR, exist_ok=True)
|
||||||
app.mount("/media", StaticFiles(directory=MEDIA_DIR), name="media")
|
app.mount("/media", StaticFiles(directory=MEDIA_DIR), name="media")
|
||||||
|
|
||||||
APP_VER = "791" # muss mit APP_VER in app.js übereinstimmen
|
APP_VER = "796" # muss mit APP_VER in app.js übereinstimmen
|
||||||
|
|
||||||
@app.get("/.well-known/assetlinks.json")
|
@app.get("/.well-known/assetlinks.json")
|
||||||
async def assetlinks():
|
async def assetlinks():
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
1. TOKENS — Farben, Abstände, Typografie, Schatten
|
1. TOKENS — Farben, Abstände, Typografie, Schatten
|
||||||
------------------------------------------------------------ */
|
------------------------------------------------------------ */
|
||||||
:root {
|
:root {
|
||||||
|
color-scheme: dark light;
|
||||||
/* Primärfarben — Honig-Amber aus Ban Yaros Fell */
|
/* Primärfarben — Honig-Amber aus Ban Yaros Fell */
|
||||||
--c-primary: #C4843A;
|
--c-primary: #C4843A;
|
||||||
--c-primary-dark: #9E6520;
|
--c-primary-dark: #9E6520;
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,9 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- Eigenes Farbschema — verhindert Browser-eigenen Dark-Mode-Filter -->
|
||||||
|
<meta name="color-scheme" content="dark light">
|
||||||
|
|
||||||
<!-- Favicons -->
|
<!-- Favicons -->
|
||||||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png">
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Router, State-Management, Navigation, Initialisierung.
|
Router, State-Management, Navigation, Initialisierung.
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const APP_VER = '791'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
const APP_VER = '796'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||||
const APP_VERSION = '1.5.0'; // ← semantische Version, wird bei make release gesetzt
|
const APP_VERSION = '1.5.0'; // ← semantische Version, wird bei make release gesetzt
|
||||||
const IS_STAGING = location.hostname === 'staging.banyaro.app';
|
const IS_STAGING = location.hostname === 'staging.banyaro.app';
|
||||||
// Cache-Bust-Parameter nach Update-Reload sofort entfernen
|
// Cache-Bust-Parameter nach Update-Reload sofort entfernen
|
||||||
|
|
@ -976,7 +976,6 @@ const App = (() => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------
|
|
||||||
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
||||||
// VERSION-CHECK
|
// VERSION-CHECK
|
||||||
let _updateBannerShown = false;
|
let _updateBannerShown = false;
|
||||||
|
|
@ -1045,18 +1044,19 @@ const App = (() => {
|
||||||
|
|
||||||
banner.querySelector('#upd-btn-close').addEventListener('click', () => banner.remove());
|
banner.querySelector('#upd-btn-close').addEventListener('click', () => banner.remove());
|
||||||
|
|
||||||
banner.querySelector('#upd-btn-reload').addEventListener('click', async () => {
|
banner.querySelector('#upd-btn-reload').addEventListener('click', () => {
|
||||||
const btn = banner.querySelector('#upd-btn-reload');
|
const btn = banner.querySelector('#upd-btn-reload');
|
||||||
btn.textContent = 'Lädt…';
|
btn.textContent = 'Lädt…';
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
|
// Cleanup fire-and-forget — kein await, nie blockieren
|
||||||
try {
|
try {
|
||||||
// Alle SW deregistrieren + alle Caches löschen → sauberer Neustart
|
navigator.serviceWorker?.getRegistrations()
|
||||||
const regs = await navigator.serviceWorker?.getRegistrations() ?? [];
|
.then(regs => regs.forEach(r => r.unregister())).catch(() => {});
|
||||||
await Promise.all(regs.map(r => r.unregister()));
|
caches.keys()
|
||||||
const keys = await caches.keys();
|
.then(keys => keys.forEach(k => caches.delete(k))).catch(() => {});
|
||||||
await Promise.all(keys.map(k => caches.delete(k)));
|
} catch { }
|
||||||
} catch { /* ignorieren */ }
|
// Sofort neu laden — nicht auf Cleanup warten
|
||||||
location.replace('/?_t=' + Date.now());
|
location.href = '/?_nocache=' + Date.now();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -329,6 +329,15 @@ window.Page_settings = (() => {
|
||||||
<option value="dark" ${(u.preferred_theme||localStorage.getItem('by_theme')) === 'dark' ? 'selected' : ''}>Dunkel</option>
|
<option value="dark" ${(u.preferred_theme||localStorage.getItem('by_theme')) === 'dark' ? 'selected' : ''}>Dunkel</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
${/SamsungBrowser/i.test(navigator.userAgent) ? `
|
||||||
|
<div style="margin:6px 0 4px;padding:10px 12px;border-radius:var(--radius-md);
|
||||||
|
background:var(--c-warning-subtle,rgba(245,158,11,0.12));
|
||||||
|
border:1px solid rgba(245,158,11,0.3);
|
||||||
|
font-size:var(--text-xs);color:var(--c-text-secondary);line-height:1.5">
|
||||||
|
<strong style="color:var(--c-warning,#f59e0b)">Samsung Internet Tipp:</strong>
|
||||||
|
Für korrekte Farben im Samsung Browser unter
|
||||||
|
<em>Einstellungen → Webseitenansicht → Dark Mode</em> deaktivieren.
|
||||||
|
</div>` : ''}
|
||||||
|
|
||||||
<!-- KI-Notiz-Assistent -->
|
<!-- KI-Notiz-Assistent -->
|
||||||
<div class="settings-toggle-row">
|
<div class="settings-toggle-row">
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,12 @@ self.addEventListener('activate', event => {
|
||||||
self.addEventListener('fetch', event => {
|
self.addEventListener('fetch', event => {
|
||||||
const url = new URL(event.request.url);
|
const url = new URL(event.request.url);
|
||||||
|
|
||||||
|
// Force-Update: SW komplett umgehen → direkt vom Netzwerk
|
||||||
|
if (url.searchParams.has('_nocache')) {
|
||||||
|
event.respondWith(fetch(event.request.url.replace(/[?&]_nocache=[^&]*/,'') || '/', { cache: 'no-store' }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// API-Calls mit Timeout, Caching und Write-Queue
|
// API-Calls mit Timeout, Caching und Write-Queue
|
||||||
if (url.pathname.startsWith('/api/')) {
|
if (url.pathname.startsWith('/api/')) {
|
||||||
const method = event.request.method;
|
const method = event.request.method;
|
||||||
|
|
@ -224,6 +230,9 @@ self.addEventListener('fetch', event => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Media-Uploads: direkt ans Netzwerk — kein Clone, kein Timeout, kein Queue
|
||||||
|
if (method === 'POST' && _isMediaUpload(event.request)) return;
|
||||||
|
|
||||||
// Mutationen (POST/PATCH/PUT/DELETE): mit Timeout, bei Offline → Queue
|
// Mutationen (POST/PATCH/PUT/DELETE): mit Timeout, bei Offline → Queue
|
||||||
if (['POST', 'PATCH', 'PUT', 'DELETE'].includes(method)) {
|
if (['POST', 'PATCH', 'PUT', 'DELETE'].includes(method)) {
|
||||||
event.respondWith((async () => {
|
event.respondWith((async () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue