feat: add download status indicators for missing media files

Add visual indicators to mark movies/series as "Downloading" when they match active SABnzbd downloads. Implement text normalization for matching download titles against media entries, with special handling for series names and episode patterns. Add purple badge/state styling for downloading status and restore original "Keine Datei/Fehler" states when downloads complete.
This commit is contained in:
2026-08-13 11:06:35 +02:00
parent f52fdf747c
commit 7e5dbd8b14
+29
View File
@@ -44,3 +44,32 @@ function renderDownloads(data){if(!downloadBody)return;const items=data.items||[
async function fetchDownloads(){if(!downloadBody)return;try{const response=await fetch('/api/downloads');const data=await response.json();renderDownloads(data)}catch(error){renderDownloads({error:'Dashboard konnte SABnzbd nicht erreichen.',items:[]})}}; async function fetchDownloads(){if(!downloadBody)return;try{const response=await fetch('/api/downloads');const data=await response.json();renderDownloads(data)}catch(error){renderDownloads({error:'Dashboard konnte SABnzbd nicht erreichen.',items:[]})}};
if(downloadBody){fetchDownloads();setInterval(fetchDownloads,4000)} if(downloadBody){fetchDownloads();setInterval(fetchDownloads,4000)}
</script> </script>
<style>
.downloading-badge{background:#713c9e!important;border-color:#9257c2!important;color:#f2e5ff!important}
.downloading-state{background:#713c9e!important;color:#f2e5ff!important}
</style>
<script>
function normalizeDownloadText(value){return String(value||'').toLowerCase().replace(/[._()[\]{}'\-·]/g,' ').replace(/\s+/g,' ').trim()}
function markDownloading(items){
const downloads=(items||[]).filter(item=>!item.completed).map(item=>normalizeDownloadText(item.title));
document.querySelectorAll('#movies tbody tr,#sonarr tbody tr').forEach(row=>{
if(row.dataset.downloadMarked==='1'){
row.children[1].innerHTML='<span class="badge">Keine Datei</span>';
row.children[2].innerHTML='<span class="state bad">Fehler</span>';
row.dataset.downloadMarked='0';
}
const details=row.closest('details.series');
const seriesName=details?normalizeDownloadText(details.querySelector('summary')?.textContent.split('(')[0]):'';
const rowName=normalizeDownloadText(row.querySelector('.title')?.textContent);
if(!rowName||!downloads.some(download=>download.includes(rowName)||(seriesName&&download.includes(seriesName)&&download.includes(rowName.match(/s\d{2}e\d{2}/)?.[0]||''))))return;
const quality=row.children[1], state=row.children[2];
if(quality.textContent.includes('Keine Datei')||row.dataset.downloadMarked==='1'){
quality.innerHTML='<span class="badge downloading-badge">Downloading</span>';
state.innerHTML='<span class="state downloading-state">Downloading</span>';
row.dataset.downloadMarked='1';
}
});
}
const originalRenderDownloads=renderDownloads;
renderDownloads=function(data){originalRenderDownloads(data);markDownloading(data.items)};
</script>