feat: add service worker route with cache-control headers and update PWA manifest icons for proper maskable support

Add /sw.js route with send_from_directory to serve service worker from root scope with Service-Worker-Allowed:/ and Cache-Control:no-cache headers. Add navigator.serviceWorker.register() script to index.html with load event listener and scope:/ parameter. Update service worker cache to v4 with media-mark-192.svg/media-mark-512.svg additions to SHELL array.

Update manifest.json icons
This commit is contained in:
2026-08-16 17:29:21 +02:00
parent cef785361f
commit 5723a5d2a0
5 changed files with 23 additions and 7 deletions
+7 -1
View File
@@ -1,4 +1,11 @@
<!doctype html>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/sw.js?v=4', {scope: '/'}).catch(function () {});
});
}
</script>
<style>@media(max-width:700px){header .nav,main>.nav{display:none!important}#movies td:nth-child(4) .badge:nth-child(n+2),#movies td:nth-child(5) .badge:nth-child(n+2),#sonarr td:nth-child(4) .badge:nth-child(n+2),#sonarr td:nth-child(5) .badge:nth-child(n+2),#missing td:nth-child(4) .badge:nth-child(n+2),#missing td:nth-child(5) .badge:nth-child(n+2){display:none!important}.year{display:none!important}.title{max-width:100%!important}}</style>
<script>document.addEventListener('DOMContentLoaded',()=>{const applyPreferred=()=>{const audio=localStorage.getItem('preferred-audio')||'',subs=localStorage.getItem('preferred-subs')||'';document.querySelectorAll('#movies tbody tr,#sonarr tbody tr,#missing tbody tr').forEach(row=>{[[4,audio,'audio-preferred'],[5,subs,'subtitle-preferred']].forEach(([column,preference,className])=>{const badges=[...row.querySelectorAll(`td:nth-child(${column}) .badge`)];if(!badges.length)return;badges.forEach(badge=>badge.classList.remove(className));const preferred=preference?badges.find(badge=>badge.textContent.includes(preference)):null;if(preferred){preferred.classList.add(className);preferred.parentElement.prepend(preferred)}})})};applyPreferred();setInterval(applyPreferred,1000)});</script>
<script>document.addEventListener('DOMContentLoaded',()=>{const nav=document.querySelector('.nav');if(nav)nav.classList.add('legacy-mobile-nav');const closeAll=()=>{document.body.classList.remove('mobile-nav-open');document.querySelectorAll('.mobile-drawer-clone,.mobile-drawer-shade,.mobile-nav-backdrop').forEach(node=>node.classList.remove('open'));document.querySelectorAll('.nav').forEach(node=>node.classList.remove('mobile-drawer-open'))};document.addEventListener('click',event=>{if(!window.matchMedia('(max-width:700px)').matches||!document.body.classList.contains('mobile-nav-open'))return;if(!event.target.closest('.mobile-drawer-clone,.mobile-nav,.brand'))closeAll()});document.addEventListener('keydown',event=>{if(event.key==='Escape')closeAll()});window.addEventListener('resize',()=>{if(!window.matchMedia('(max-width:700px)').matches)closeAll()})});</script>
@@ -29,7 +36,6 @@
</style><style>.scan-control{display:flex;align-items:center;gap:5px}.scan-control select{height:36px;padding:0 8px;font-size:11px}.scan-control button{white-space:nowrap}.scan-running{position:relative;overflow:hidden;background:linear-gradient(90deg,rgba(244,196,48,.14) var(--scan-progress,0%),rgba(244,196,48,.04) var(--scan-progress,0%))!important}.scan-running::after{content:'';position:absolute;left:0;bottom:0;width:var(--scan-progress,0%);height:2px;background:#f4c430;transition:width .35s ease}@media(max-width:700px){.scan-control select{max-width:108px;font-size:10px}.scan-control button{font-size:0}.scan-control button::after{content:'↻';font-size:16px}}</style></head><body>
<header><div class="brand"><div class="brand-mark" aria-label="Media Max"><svg viewBox="0 0 48 48" role="img"><path d="M10 8h28a4 4 0 0 1 4 4v24a4 4 0 0 1-4 4H10a4 4 0 0 1-4-4V12a4 4 0 0 1 4-4Z" fill="#20252d" stroke="#60a9e6" stroke-width="2"/><path d="M14 17h20M14 24h13M14 31h20" stroke="#f4c430" stroke-width="3" stroke-linecap="round"/><circle cx="34" cy="24" r="5" fill="#159447" stroke="#c9ffe0" stroke-width="1.5"/></svg></div><div class="brand-name">MEDIA</div></div><div><div class="head-title" data-de="Media Max" data-en="Media Max">Media Max</div><div class="head-sub" data-de="Audio- und Untertitelspuren aus den Mediendateien" data-en="Audio and subtitle tracks from media files">Audio- und Untertitelspuren aus den Mediendateien</div></div><div class="actions"><button class="lang-switch" id="languageToggle" title="Sprache / Language">DE</button><button class="settings-button" id="settingsOpen" title="Einstellungen"></button><div class="scan-control"><select id="scanSource" aria-label="Scan-Quelle"><option value="all">Alles scannen</option><option value="radarr">Nur Radarr</option><option value="sonarr">Nur Sonarr</option></select><button id="rescan" data-de="↻ Neu scannen" data-en="↻ Rescan">↻ Neu scannen</button></div></div></header>
<main>
{% if error %}<div class="banner"><strong>Fehler:</strong> {{ error }}</div>{% endif %}
<nav class="nav"><button class="active" data-view="dashboard"><img class="nav-tab-icon" src="https://api.iconify.design/mdi:view-dashboard-outline.svg?color=%238bc9f2" alt="" aria-hidden="true">Dashboard</button><button data-view="radarr"><img class="nav-tab-icon" src="https://api.iconify.design/mdi:movie-open-outline.svg?color=%23cc7b19" alt="" aria-hidden="true">RADARR · Filme</button>{% if sonarr_enabled %}<button data-view="sonarr"><img class="nav-tab-icon" src="https://api.iconify.design/mdi:television-classic.svg?color=%2335c5f4" alt="" aria-hidden="true">SONARR · Serien</button>{% endif %}<button data-view="missing"><img class="nav-tab-icon" src="https://api.iconify.design/mdi:alert-outline.svg?color=%23ff9e9e" alt="" aria-hidden="true">Ohne Deutsch <span class="nav-count" id="missingNavCount">{{ missing_german_movies|length + (missing_german_series|map(attribute='episodes')|map('length')|sum) }}</span></button>{% if sab_enabled %}<button data-view="downloads"><img class="nav-tab-icon" src="https://api.iconify.design/mdi:download-box-outline.svg?color=%23f4c430" alt="" aria-hidden="true">SABNZBD · Downloads <span class="nav-count download-nav-count hidden" id="downloadNavCount">0</span></button>{% endif %}<button data-view="datastore"><img class="nav-tab-icon" src="https://api.iconify.design/mdi:harddisk.svg?color=%2360a9e6" alt="" aria-hidden="true">Datastore</button></nav>
<section id="dashboard" class="view active" data-source="dashboard"><div class="dashboard-hero"><div><div class="eyebrow">MEDIA MAX</div><h1>Dashboard</h1><p>Deine gesamte Medienbibliothek und Systemauslastung auf einen Blick.</p></div><div class="live-pill"><span class="live-dot"></span> Live</div></div><div class="overview-grid"><div class="overview-card"><span class="overview-icon movie"></span><div><span>Filme</span><strong>{{ rows|length }}</strong><small>Radarr Library</small></div></div><div class="overview-card"><span class="overview-icon series-icon"></span><div><span>Serien</span><strong>{{ series|length }}</strong><small>Sonarr Shows</small></div></div><div class="overview-card"><span class="overview-icon warning"></span><div><span>Ohne Deutsch</span><strong id="dashboardMissing">{{ missing_german_movies|length + (missing_german_series|map(attribute='episodes')|map('length')|sum) }}</strong><small>Audio oder Untertitel prüfen</small></div></div><div class="overview-card"><span class="overview-icon download-icon"></span><div><span>Downloads</span><strong id="dashboardDownloads"></strong><small id="dashboardRemaining">SABnzbd wird geladen …</small></div></div></div><div class="dashboard-columns"><section class="system-panel"><div class="panel-heading"><div><h2>Systemauslastung</h2><p>Aktuelle Werte aus dem Dashboard-Container</p></div><span id="systemUpdated" class="muted">Wird geladen …</span></div><div class="system-meters"><div class="meter"><div class="meter-top"><span>CPU</span><strong id="cpuValue"></strong></div><div class="meter-track"><span id="cpuBar"></span></div></div><div class="meter"><div class="meter-top"><span>RAM</span><strong id="ramValue"></strong></div><div class="meter-track"><span id="ramBar"></span></div></div></div><div id="diskList" class="disk-list"><div class="disk-row muted">Laufwerke werden geladen …</div></div></section><section class="service-panel"><div class="panel-heading"><div><h2>Dienste</h2><p>Verbindung und Bibliotheksstatus</p></div></div><div class="service-row"><span class="service-logo radarr-dot">R</span><div><strong>Radarr</strong><small>Filme & Qualität</small></div><span class="service-status online">Aktiv</span></div><div class="service-row"><span class="service-logo sonarr-dot">S</span><div><strong>Sonarr</strong><small>Serien & Episoden</small></div><span class="service-status {% if sonarr_enabled %}online{% else %}offline{% endif %}">{% if sonarr_enabled %}Aktiv{% else %}Nicht konfiguriert{% endif %}</span></div><div class="service-row"><span class="service-logo sab-dot"></span><div><strong>SABnzbd</strong><small>Downloads & Queue</small></div><span id="dashboardSabStatus" class="service-status {% if sab_enabled %}online{% else %}offline{% endif %}">{% if sab_enabled %}Wird geprüft …{% else %}Nicht konfiguriert{% endif %}</span></div></section></div></section>
<section id="radarr" class="view" data-source="radarr">