Update series summary sticky top position from 0 to 64px and add z-index:30 to prevent overlap with fixed header. Update season divider sticky top position to 110px with z-index:29 to stack below series summaries but above content.
103 lines
23 KiB
HTML
103 lines
23 KiB
HTML
<!doctype html>
|
|
<html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Language Dashboard</title>
|
|
<style>
|
|
:root{color-scheme:dark;--bg:#181818;--panel:#222;--line:#3a3a3a;--text:#dedede;--muted:#929292;--yellow:#f4c430;--blue:#60a9e6}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text);font:13px Inter,system-ui,sans-serif}header{height:58px;display:flex;align-items:center;gap:15px;padding:0 20px;background:#242424;border-bottom:1px solid #343434}.logo{color:var(--yellow);font-size:22px;font-weight:900;letter-spacing:1px}.head-title{font-weight:700}.head-sub{font-size:12px;color:var(--muted);margin-top:2px}.actions{margin-left:auto}button,input,select{font:inherit;color:var(--text);background:#292929;border:1px solid #444;border-radius:5px}button{padding:7px 10px;cursor:pointer}main{padding:14px 20px 30px}.nav{display:flex;gap:4px;margin-bottom:12px;border-bottom:1px solid var(--line)}.nav button{border:0;border-radius:5px 5px 0 0;background:transparent;color:#aaa}.nav button.active{background:#303030;color:#fff}.view{display:none}.view.active{display:block}.toolbar{display:grid;grid-template-columns:minmax(280px,1fr) 190px 190px 170px;gap:8px;margin-bottom:10px}input,select{padding:7px 10px;height:34px}.stats{display:flex;gap:8px;margin-bottom:10px;flex-wrap:wrap}.stat{background:#242424;border:1px solid #363636;padding:5px 9px;border-radius:5px;color:#bbb}.scan{color:#f4c430}.banner{padding:9px 11px;border:1px solid #693b3b;background:#372424;border-radius:5px;margin-bottom:10px;color:#ffd1d1}.tablewrap{border:1px solid #353535;border-radius:6px;overflow:hidden;background:var(--panel)}table{width:100%;border-collapse:collapse;table-layout:fixed}th{padding:8px 10px;background:#282828;border-bottom:1px solid #444;text-align:left;font-size:12px}td{padding:7px 10px;border-bottom:1px solid #343434;vertical-align:middle}.col-title{width:28%}.col-quality{width:12%}.col-state{width:10%}.col-audio{width:17%}.col-subs{width:17%}.col-video{width:8%}.col-size{width:8%}.title{color:var(--blue);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:inline-block;max-width:90%;vertical-align:bottom}.year{color:var(--muted);font-size:11px;margin-left:5px}.badges{display:flex;gap:4px;flex-wrap:wrap}.badge{display:inline-flex;gap:4px;align-items:center;padding:2px 6px;border-radius:999px;border:1px solid #484848;background:#303030;white-space:nowrap;font-size:11px}.quality{background:#0e7138;border-color:#19894b}.state{font-size:11px;font-weight:700;padding:3px 7px;border-radius:4px;display:inline-block}.state.ok{background:#126f39;color:#d9ffe8}.state.warn{background:#77561e;color:#ffebc4}.state.bad{background:#763030;color:#ffd9d9}.state.neutral{background:#3b3b3b;color:#ccc}.muted{color:var(--muted)}.hidden{display:none}.series{border-bottom:1px solid var(--line)}.series:last-child{border:0}.series summary{padding:12px;cursor:pointer;background:#282828;font-weight:700}.series summary:hover{background:#303030}.series table{border-radius:0}.series td:first-child{padding-left:28px}@media(max-width:1100px){.toolbar{grid-template-columns:1fr 1fr}.col-video,.col-size{display:none}}
|
|
</style></head><body>
|
|
<header><div class="logo">MEDIA</div><div><div class="head-title">Language Dashboard</div><div class="head-sub">Audio- und Untertitelspuren aus den Mediendateien</div></div><div class="actions"><button id="rescan">↻ Neu scannen</button></div></header>
|
|
<main>
|
|
{% if error %}<div class="banner"><strong>Fehler:</strong> {{ error }}</div>{% endif %}
|
|
<nav class="nav"><button class="active" data-view="radarr">RADARR · Filme</button>{% if sonarr_enabled %}<button data-view="sonarr">SONARR · Serien</button>{% endif %}{% if sab_enabled %}<button data-view="downloads">SABNZBD · Downloads</button>{% endif %}</nav>
|
|
<section id="radarr" class="view active" data-source="radarr">
|
|
<div class="toolbar"><input id="search" type="search" placeholder="Film suchen …"><select id="audioFilter"><option value="">Alle Audio-Sprachen</option><option>Deutsch</option><option>Englisch</option><option>Japanisch</option><option>Koreanisch</option></select><select id="subFilter"><option value="">Alle Untertitel</option><option>Deutsch</option><option>Englisch</option><option>Japanisch</option><option>Koreanisch</option></select><select id="stateFilter"><option value="">Alle Status</option><option>DE + EN</option><option>Deutsch</option><option>English only</option></select></div>
|
|
<div class="stats"><span class="stat" id="visibleCount"></span><span class="stat scan" id="radarrStatus">Scan wird vorbereitet …</span><span class="stat">Radarr: {{ radarr_media_path }}</span></div>
|
|
<div class="tablewrap"><table id="movies"><thead><tr><th class="col-title">Film</th><th class="col-quality">Quality</th><th class="col-state">Status</th><th class="col-audio">Audio</th><th class="col-subs">Untertitel</th><th class="col-video">Video</th><th class="col-size">Größe</th></tr></thead><tbody>
|
|
{% for r in rows %}<tr data-title="{{ (r.title ~ ' ' ~ (r.year or ''))|lower }}" data-audio="{{ r.audio_languages|map(attribute='name')|join(',') }}" data-subs="{{ r.subtitle_languages|map(attribute='name')|join(',') }}" data-state="{{ r.state.label }}"><td><span class="title">{{ r.title }}</span><span class="year">{{ r.year or '' }}</span>{% if r.error %} ⚠{% endif %}</td><td><span class="badge {% if not r.missing %}quality{% endif %}">{{ r.quality }}</span></td><td><span class="state {{ r.state.class }}">{{ r.state.label }}</span></td><td><div class="badges">{% for l in r.audio_languages %}<span class="badge">{{ l.flag }} {{ l.name }}</span>{% else %}<span class="muted">—</span>{% endfor %}</div></td><td><div class="badges">{% for l in r.subtitle_languages %}<span class="badge">{{ l.flag }} {{ l.name }}</span>{% else %}<span class="muted">—</span>{% endfor %}</div></td><td>{{ r.video_codec }}</td><td>{{ r.size }}</td></tr>{% endfor %}
|
|
</tbody></table></div></section>
|
|
{% if sonarr_enabled %}<section id="sonarr" class="view" data-source="sonarr"><div class="stats"><span class="stat" id="seriesCount">{{ series|length }} Serien</span><span class="stat scan" id="sonarrStatus">Scan wird vorbereitet …</span><span class="stat">Dashboard: {{ local_series_path }}</span></div><div class="tablewrap" id="seriesList">
|
|
{% for group in series %}<details class="series" open><summary>{{ group.title }} <span class="muted">({{ group.year or '—' }}) · {{ group.episodes|length }} Episoden</span></summary><table><thead><tr><th class="col-title">Episode</th><th class="col-quality">Quality</th><th class="col-state">Status</th><th class="col-audio">Audio</th><th class="col-subs">Untertitel</th><th class="col-video">Video</th><th class="col-size">Größe</th></tr></thead><tbody>{% for r in group.episodes %}<tr><td><span class="title">{{ r.title }}</span></td><td><span class="badge {% if not r.missing %}quality{% endif %}">{{ r.quality }}</span></td><td><span class="state {{ r.state.class }}">{{ r.state.label }}</span></td><td><div class="badges">{% for l in r.audio_languages %}<span class="badge">{{ l.flag }} {{ l.name }}</span>{% else %}<span class="muted">—</span>{% endfor %}</div></td><td><div class="badges">{% for l in r.subtitle_languages %}<span class="badge">{{ l.flag }} {{ l.name }}</span>{% else %}<span class="muted">—</span>{% endfor %}</div></td><td>{{ r.video_codec }}</td><td>{{ r.size }}</td></tr>{% endfor %}</tbody></table></details>{% endfor %}
|
|
</div></section>{% endif %}
|
|
{% if sab_enabled %}<section id="downloads" class="view" data-source="downloads"><div class="stats"><span class="stat" id="downloadCount">Downloads werden geladen …</span><span class="stat" id="sabQueueStatus">SABnzbd …</span><span class="stat" id="sabSpeed">Geschwindigkeit: —</span></div><div id="downloadError" class="banner hidden"></div><div class="tablewrap"><table id="downloadsTable"><thead><tr><th class="col-title">Download</th><th class="col-state">Status</th><th class="col-progress">Fortschritt</th><th class="col-size">Größe / Rest</th><th class="col-time">Restzeit</th><th class="col-source">Quelle</th><th class="col-language">Sprache</th></tr></thead><tbody id="downloadsBody"><tr><td colspan="7" class="muted">Downloads werden geladen …</td></tr></tbody></table></div></section>{% endif %}
|
|
</main>
|
|
<script>
|
|
const rows=[...document.querySelectorAll('#movies tbody tr')], search=document.querySelector('#search'), audio=document.querySelector('#audioFilter'), subs=document.querySelector('#subFilter'), state=document.querySelector('#stateFilter'), count=document.querySelector('#visibleCount');
|
|
function apply(){const q=search.value.trim().toLowerCase();let n=0;rows.forEach(r=>{const ok=(!q||r.dataset.title.includes(q))&&(!audio.value||r.dataset.audio.includes(audio.value))&&(!subs.value||r.dataset.subs.includes(subs.value))&&(!state.value||r.dataset.state===state.value);r.classList.toggle('hidden',!ok);if(ok)n++});count.textContent=`${n} Filme`};[search,audio,subs,state].forEach(x=>x.addEventListener(x===search?'input':'change',apply));apply();
|
|
document.querySelectorAll('.nav button').forEach(b=>b.onclick=()=>{document.querySelectorAll('.nav button').forEach(x=>x.classList.remove('active'));document.querySelectorAll('.view').forEach(x=>x.classList.remove('active'));b.classList.add('active');document.querySelector('#'+b.dataset.view).classList.add('active');document.querySelector('#rescan').dataset.source=b.dataset.view});
|
|
function statusText(s){if(s.state==='running')return `Scan: ${s.done}/${s.total||'?'} Dateien`;if(s.state==='done')return 'Scan abgeschlossen';if(s.state==='error')return 'Scanfehler: '+s.error;return 'Scan wird vorbereitet …'}
|
|
const seenRunning={radarr:false,sonarr:false};async function poll(){try{const data=await (await fetch('/api/scan-status')).json();document.querySelector('#radarrStatus').textContent=statusText(data.radarr);const sonarr=document.querySelector('#sonarrStatus');if(sonarr)sonarr.textContent=statusText(data.sonarr);['radarr','sonarr'].forEach(source=>{if(data[source].state==='running')seenRunning[source]=true;if(seenRunning[source]&&['done','error'].includes(data[source].state)){seenRunning[source]=false;setTimeout(()=>location.reload(),700)}})}catch(e){} };setInterval(poll,1200);poll();
|
|
document.querySelector('#rescan').onclick=async()=>{const b=document.querySelector('#rescan');b.disabled=true;b.textContent='Scanne …';await fetch('/api/rescan?source='+(b.dataset.source||'radarr'),{method:'POST'});b.disabled=false;b.textContent='↻ Neu scannen';poll()};
|
|
</script></body></html>
|
|
<style>
|
|
details.series{margin-bottom:8px;border:1px solid var(--line);border-radius:6px;overflow:hidden;background:#222}
|
|
details.series:last-child{margin-bottom:0}
|
|
</style>
|
|
<script>document.querySelectorAll('details.series').forEach(series => { series.open = false; });</script>
|
|
<style>
|
|
.subtitle-de{background:#126f39!important;border-color:#19894b!important;color:#d9ffe8!important}
|
|
.col-progress{width:16%}.col-time{width:10%}.col-source{width:10%}.col-language{width:12%}
|
|
.progress-wrap{display:flex;align-items:center;gap:8px}.progress-bar{height:7px;min-width:70px;flex:1;background:#3a3a3a;border-radius:99px;overflow:hidden}.progress-bar span{display:block;height:100%;background:#159447;border-radius:99px}.download-title{color:var(--blue);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
|
|
</style>
|
|
<script>
|
|
document.querySelectorAll('#movies tbody tr td:nth-child(5) .badge,#sonarr tbody tr td:nth-child(5) .badge').forEach(badge=>{if(badge.textContent.includes('Deutsch'))badge.classList.add('subtitle-de')});
|
|
document.querySelectorAll('#movies tbody tr,#sonarr tbody tr').forEach(row=>{if(row.querySelector('.state.downloading'))row.children[1].querySelector('.badge')?.classList.add('downloading-badge')});
|
|
const downloadBody=document.querySelector('#downloadsBody');
|
|
function html(value){return String(value??'—').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]))}
|
|
function renderDownloads(data){if(!downloadBody)return;const items=data.items||[];document.querySelector('#downloadCount').textContent=`${items.length} Downloads`;document.querySelector('#sabQueueStatus').textContent=`SABnzbd: ${data.paused?'Pausiert':data.queue_status||'Idle'}`;document.querySelector('#sabSpeed').textContent=`Geschwindigkeit: ${data.speed||'—'}`;const error=document.querySelector('#downloadError');error.classList.toggle('hidden',!data.error);error.innerHTML=data.error?`<strong>SABnzbd:</strong> ${html(data.error)}`:'';downloadBody.innerHTML=items.length?items.map(item=>{const pct=Math.max(0,Math.min(100,Number(item.percentage)||0));const languages=(item.languages||[]).map(l=>`<span class="badge">${html(l.flag)} ${html(l.name)}</span>`).join('')||'<span class="muted">Nicht erkannt</span>';return `<tr><td><span class="download-title" title="${html(item.title)}">${html(item.title)}</span><span class="muted">${html(item.category)}</span></td><td><span class="state ${item.completed?'ok':'neutral'}">${html(item.status)}</span></td><td><div class="progress-wrap"><div class="progress-bar"><span style="width:${pct}%"></span></div><span>${pct.toFixed(1)}%</span></div></td><td>${html(item.size)}<br><span class="muted">Rest: ${html(item.remaining)}</span></td><td>${html(item.completed?'—':item.timeleft)}</td><td>${html(item.source)}</td><td><div class="badges">${languages}</div></td></tr>`}).join(''):'<tr><td colspan="7" class="muted">Keine aktuellen Downloads</td></tr>'}
|
|
async function fetchDownloads(){if(!downloadBody)return;try{const response=await fetch('/api/downloads');const data=await response.json();renderDownloads(data);if(typeof markDownloading==='function')markDownloading(data.items)}catch(error){renderDownloads({error:'Dashboard konnte SABnzbd nicht erreichen.',items:[]})}};
|
|
if(downloadBody){fetchDownloads();setInterval(fetchDownloads,4000)}
|
|
</script>
|
|
<style>
|
|
.season-divider td{padding:6px 10px;background:#1b1b1b;border-top:1px solid #444;border-bottom:1px solid #303030;color:#aaa;font-size:11px;font-weight:700;letter-spacing:.3px}
|
|
#seriesList{overflow:visible}.series{overflow:visible!important}.series summary{position:sticky!important;top:64px!important;z-index:30!important}.season-divider td{top:110px!important;z-index:29!important}
|
|
.series[open] table{animation:seriesExpand .38s cubic-bezier(.2,.75,.25,1) both;transform-origin:top center}.series summary::after{content:'⌄';margin-left:auto;color:#929292;font-size:16px;line-height:1;transition:transform .3s ease,color .3s ease}.series[open] summary::after{transform:rotate(180deg);color:#60a9e6}@keyframes seriesExpand{from{opacity:0;transform:translateY(-8px) scaleY(.98)}to{opacity:1;transform:translateY(0) scaleY(1)}}
|
|
.series{position:relative;margin-bottom:14px;border:1px solid #353b46;border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.14);transition:border-color .25s ease,box-shadow .25s ease,transform .25s ease}.series:hover{border-color:#4a5565;box-shadow:0 12px 30px rgba(0,0,0,.24);transform:translateY(-1px)}.series-current{border-color:#557ba5;box-shadow:0 0 0 1px rgba(96,169,230,.18),0 14px 34px rgba(0,0,0,.25)}.series summary{position:sticky;top:0;z-index:5;display:flex;align-items:center;min-height:46px;padding:12px 14px;background:rgba(40,40,40,.96);backdrop-filter:blur(12px);border-bottom:1px solid transparent;transition:background .25s ease,border-color .25s ease,color .25s ease}.series-current summary{background:rgba(47,61,78,.98)}.series summary::marker{color:#60a9e6}.series[open] summary{border-bottom-color:#3d444f;box-shadow:0 4px 14px rgba(0,0,0,.16)}.series summary:hover{background:rgba(54,60,70,.97);color:#fff}.series summary .muted{margin-left:7px}.series table tbody tr:not(.season-divider){animation:rowIn .35s ease both;transition:background .2s ease,transform .2s ease}.series table tbody tr:not(.season-divider):hover{background:#292e36;transform:translateX(2px)}.season-divider td{position:sticky;top:46px;z-index:4;background:rgba(27,27,27,.96);backdrop-filter:blur(8px)}
|
|
.state.downloading,.downloading-badge{animation:downloadPulse 2s ease-in-out infinite}.progress-bar span{position:relative;overflow:hidden}.progress-bar span::after{content:"";position:absolute;inset:0;background:linear-gradient(110deg,transparent 20%,rgba(255,255,255,.25) 48%,transparent 72%);animation:progressShimmer 1.8s linear infinite}.nav button{transition:color .2s ease,background .2s ease,transform .2s ease}.nav button:hover{transform:translateY(-1px)}.badge{transition:transform .18s ease,filter .18s ease}.badge:hover{transform:translateY(-2px);filter:brightness(1.15)}
|
|
@keyframes rowIn{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}@keyframes downloadPulse{0%,100%{box-shadow:0 0 0 rgba(113,60,158,0)}50%{box-shadow:0 0 14px rgba(146,87,194,.35)}}@keyframes progressShimmer{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
|
|
@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-duration:.01ms!important}}
|
|
</style>
|
|
<style>
|
|
:root{--accent:#f4c430;--accent-blue:#60a9e6;--surface:rgba(35,37,42,.82);--surface-strong:#282b31;--border-soft:rgba(255,255,255,.09)}
|
|
body{background:radial-gradient(circle at 10% -15%,rgba(96,169,230,.12),transparent 33%),radial-gradient(circle at 90% 0%,rgba(244,196,48,.07),transparent 28%),#151619;letter-spacing:.01em}
|
|
header{height:64px;background:rgba(31,33,38,.9);backdrop-filter:blur(18px);border-bottom:1px solid var(--border-soft);box-shadow:0 8px 30px rgba(0,0,0,.2);position:sticky;top:0;z-index:20}.logo{font-size:23px;text-shadow:0 0 18px rgba(244,196,48,.24)}.head-title{font-size:14px;letter-spacing:.01em}.head-sub{color:#9da5b2}
|
|
main{max-width:1800px;margin:0 auto;padding:18px 20px 42px}.nav{gap:6px;margin:0 0 16px;padding:4px;border:1px solid var(--border-soft);border-radius:9px;background:rgba(31,33,38,.72);box-shadow:0 8px 24px rgba(0,0,0,.12)}.nav button{padding:9px 14px;border-radius:6px;color:#aeb5c1}.nav button.active{background:linear-gradient(135deg,#3a3f48,#2d3139);box-shadow:inset 0 1px rgba(255,255,255,.08),0 4px 12px rgba(0,0,0,.18);color:#fff}.nav button.active::after{content:"";display:block;height:2px;margin:6px 2px -4px;border-radius:2px;background:var(--accent-blue)}
|
|
.toolbar{padding:10px;border:1px solid var(--border-soft);border-radius:10px;background:rgba(35,37,42,.72);box-shadow:0 10px 28px rgba(0,0,0,.14);gap:9px}.toolbar input,.toolbar select{background:#2b2e34;border-color:#474d57;transition:border-color .2s,box-shadow .2s,background .2s}.toolbar input:focus,.toolbar select:focus{outline:none;background:#30343b;border-color:var(--accent-blue);box-shadow:0 0 0 3px rgba(96,169,230,.14)}
|
|
.stats{gap:9px;margin:12px 0}.stat{background:linear-gradient(135deg,rgba(48,52,60,.9),rgba(34,36,41,.9));border:1px solid var(--border-soft);border-radius:8px;padding:7px 11px;box-shadow:0 5px 15px rgba(0,0,0,.12)}.stat:first-child{color:#fff;font-weight:700}.scan{color:#f4c430!important}
|
|
.tablewrap{border:1px solid var(--border-soft);border-radius:10px;background:rgba(31,33,38,.84);box-shadow:0 14px 34px rgba(0,0,0,.2)}table{border-spacing:0}thead th{height:38px;background:linear-gradient(180deg,#30343b,#292c32);color:#bfc6d1;text-transform:uppercase;letter-spacing:.07em;font-size:10px}tbody td{height:42px;border-bottom-color:rgba(255,255,255,.075)}tbody tr{transition:background .2s,transform .2s}tbody tr:hover{background:rgba(96,169,230,.065);transform:translateX(1px)}.title{font-size:13px}.quality{box-shadow:0 0 12px rgba(21,148,71,.18)}
|
|
#rescan{padding:9px 13px;background:linear-gradient(135deg,#343943,#292c32);border-color:#515865;box-shadow:0 5px 16px rgba(0,0,0,.18);transition:transform .2s,box-shadow .2s,border-color .2s}#rescan:hover{transform:translateY(-2px);border-color:var(--accent-blue);box-shadow:0 8px 20px rgba(0,0,0,.28)}
|
|
@media(max-width:760px){header{padding:0 12px}.head-sub{display:none}main{padding:12px}.toolbar{grid-template-columns:1fr}.actions{margin-left:auto}.nav{overflow-x:auto}.nav button{white-space:nowrap}.tablewrap{overflow-x:auto}table{min-width:900px}}
|
|
</style>
|
|
<script>
|
|
document.querySelectorAll('details.series tbody').forEach(tbody=>{let currentSeason=null;[...tbody.querySelectorAll('tr')].forEach(row=>{if(row.classList.contains('season-divider'))return;const match=row.querySelector('.title')?.textContent.match(/^S(\d{2})E\d{2}/i);if(!match||match[1]===currentSeason)return;currentSeason=match[1];const divider=document.createElement('tr');divider.className='season-divider';divider.innerHTML=`<td colspan="7">Staffel ${Number(currentSeason)}</td>`;tbody.insertBefore(divider,row)})});
|
|
document.querySelectorAll('details.series').forEach(series=>{const summary=series.querySelector('summary');if(!summary)return;summary.title='Klicken zum Auf- oder Zuklappen';const observer=new IntersectionObserver(([entry])=>series.classList.toggle('series-current',!entry.isIntersecting&&series.open),{threshold:0,rootMargin:'-58px 0px 0px 0px'});observer.observe(summary)});
|
|
</script>
|
|
<style>
|
|
.downloading-badge{background:#713c9e!important;border-color:#9257c2!important;color:#f2e5ff!important}.state.downloading{background:#713c9e;color:#f2e5ff}
|
|
.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);
|
|
const rowTokens=rowName.split(' ').filter(token=>token.length>2);
|
|
const isMatch=downloads.some(download=>download.includes(rowName)||(seriesName&&download.includes(seriesName)&&download.includes(rowName.match(/s\d{2}e\d{2}/)?.[0]||''))||(rowTokens.length>=3&&rowTokens.filter(token=>download.includes(token)).length>=Math.ceil(rowTokens.length*.75)));
|
|
if(!rowName||!isMatch)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>
|