-
-
-
+
+
+
@@ -331,10 +346,10 @@ HTML = r"""
@@ -343,6 +358,38 @@ let allFilms = [];
let selected = new Set();
let downloads = {};
let currentFilter = 'all';
+let filmInfoCache = {};
+let infoQueue = [];
+let infoLoading = false;
+
+function queueInfoLoad(films) {
+ films.forEach(f => {
+ if (!filmInfoCache[f.tid] && !infoQueue.some(q => q.tid === f.tid)) {
+ infoQueue.push({tid: f.tid, title: f.title});
+ }
+ });
+ if (!infoLoading) processInfoQueue();
+}
+
+async function processInfoQueue() {
+ if (!infoQueue.length) { infoLoading = false; return; }
+ infoLoading = true;
+ const item = infoQueue.shift();
+ try {
+ const r = await fetch('/api/filminfo?title=' + encodeURIComponent(item.title));
+ const d = await r.json();
+ let parts = [];
+ if (d.year) parts.push(d.year);
+ if (d.countries && d.countries.length) parts.push(d.countries.join('/'));
+ if (d.genres && d.genres.length) parts.push(d.genres.join(', '));
+ if (parts.length) {
+ filmInfoCache[item.tid] = parts.join(' \u00b7 ');
+ const el = document.getElementById('info-' + item.tid);
+ if (el) { el.textContent = filmInfoCache[item.tid]; el.classList.add('loaded'); }
+ }
+ } catch(e) {}
+ setTimeout(processInfoQueue, 200);
+}
async function loadFilms() {
const resp = await fetch('/api/films');
@@ -352,80 +399,85 @@ async function loadFilms() {
document.getElementById('loading').style.display = 'none';
document.getElementById('content').style.display = 'block';
document.getElementById('header-stats').textContent =
- `${data.total} Aufnahmen · ${data.kino} Kino · ${data.urgent} dringend`;
+ data.total + ' Aufnahmen \u00b7 ' + data.kino + ' Kino \u00b7 ' + data.urgent + ' dringend';
renderFilms();
}
function setFilter(f) {
currentFilter = f;
- document.querySelectorAll('.filter-btn').forEach((b, i) => {
+ document.querySelectorAll('.filter-btn').forEach(function(b, i) {
b.classList.toggle('active', ['all','urgent','kino','tv'][i] === f);
});
renderFilms();
}
function renderFilms() {
- const q = document.getElementById('search').value.toLowerCase();
- const films = allFilms.filter(f => {
- if (q && !f.title.toLowerCase().includes(q)) return false;
+ var q = document.getElementById('search').value.toLowerCase();
+ var films = allFilms.filter(function(f) {
+ if (q && f.title.toLowerCase().indexOf(q) === -1) return false;
if (currentFilter === 'urgent') return f.days_left <= 7;
if (currentFilter === 'kino') return f.cinema && f.days_left > 7;
if (currentFilter === 'tv') return !f.cinema;
return true;
});
- const urgent = films.filter(f => f.days_left <= 7);
- const kino = films.filter(f => f.cinema && f.days_left > 7);
- const tv = films.filter(f => !f.cinema && f.days_left > 7);
+ var urgent = films.filter(function(f) { return f.days_left <= 7; });
+ var kino = films.filter(function(f) { return f.cinema && f.days_left > 7; });
+ var tv = films.filter(function(f) { return !f.cinema && f.days_left > 7; });
document.getElementById('urgent-count').textContent = urgent.length;
document.getElementById('kino-count').textContent = kino.length;
document.getElementById('tv-count').textContent = tv.length;
function renderGrid(arr, gridId, sectionId) {
- const el = document.getElementById(sectionId);
- const grid = document.getElementById(gridId);
+ var el = document.getElementById(sectionId);
+ var grid = document.getElementById(gridId);
if (!arr.length) { el.style.display = 'none'; return; }
el.style.display = 'block';
- grid.innerHTML = arr.map(f => filmCard(f)).join('');
+ grid.innerHTML = arr.map(function(f) { return filmCard(f); }).join('');
}
renderGrid(urgent, 'urgent-grid', 'urgent-section');
renderGrid(kino, 'kino-grid', 'kino-section');
renderGrid(tv, 'tv-grid', 'tv-section');
+ queueInfoLoad(allFilms);
}
function filmCard(f) {
- const sel = selected.has(f.tid);
- const dlState = downloads[f.tid];
- const daysClass = f.days_left <= 3 ? 'days-urgent' : 'days-ok';
- const daysLabel = f.days_left === 0 ? 'heute' : f.days_left === 1 ? '1 Tag' : `${f.days_left} Tage`;
+ var sel = selected.has(f.tid);
+ var dlState = downloads[f.tid];
+ var daysClass = f.days_left <= 3 ? 'days-urgent' : 'days-ok';
+ var daysLabel = f.days_left === 0 ? 'heute' : f.days_left === 1 ? '1 Tag' : f.days_left + ' Tage';
- let cardClass = 'film-card';
+ var cardClass = 'film-card';
if (sel) cardClass += ' selected';
if (dlState === 'done') cardClass += ' downloaded';
if (dlState === 'running') cardClass += ' downloading';
- let statusEl = `
${sel ? '✓' : ''}
`;
- let extraLine = '';
+ var statusEl = '
' + (sel ? '\u2713' : '') + '
';
+ var extraLine = '';
if (dlState === 'running') {
- statusEl = `
⬇
`;
- extraLine = `
Download läuft...
`;
+ statusEl = '
\u2b07
';
+ extraLine = '
Download l\u00e4uft...
';
} else if (dlState === 'done') {
- statusEl = `
✅
`;
- extraLine = `
Gespeichert
`;
+ statusEl = '
\u2705
';
+ extraLine = '
Gespeichert
';
}
- return `
- ${statusEl}
-
${f.title}
-
- ${f.station}
- ${f.cinema ? 'Kino' : 'TV'}
- ${daysLabel}
-
- ${extraLine}
-
`;
+ var infoText = filmInfoCache[f.tid] || '';
+ var infoClass = infoText ? 'film-info loaded' : 'film-info';
+
+ return '
'
+ + statusEl
+ + '
' + f.title + '
'
+ + '
'
+ + '' + f.station + ''
+ + '' + (f.cinema ? 'Kino' : 'TV') + ''
+ + '' + daysLabel + ''
+ + '
'
+ + '
' + infoText + '
'
+ + extraLine
+ + '
';
}
function toggleFilm(tid) {
@@ -442,7 +494,7 @@ function updateToolbar() {
}
function selectUrgent() {
- allFilms.filter(f => f.days_left <= 7 && downloads[f.tid] !== 'done').forEach(f => selected.add(f.tid));
+ allFilms.filter(function(f) { return f.days_left <= 7 && downloads[f.tid] !== 'done'; }).forEach(function(f) { selected.add(f.tid); });
updateToolbar();
renderFilms();
}
@@ -454,38 +506,34 @@ function clearSelection() {
}
async function startDownloads() {
- const tids = Array.from(selected);
+ var tids = Array.from(selected);
if (!tids.length) return;
document.getElementById('dl-btn').disabled = true;
-
- showToast(`Starte ${tids.length} Download(s)...`);
-
- tids.forEach(tid => { downloads[tid] = 'running'; });
+ showToast('Starte ' + tids.length + ' Download(s)...');
+ tids.forEach(function(tid) { downloads[tid] = 'running'; });
selected.clear();
updateToolbar();
renderFilms();
- const resp = await fetch('/api/download', {
+ var resp = await fetch('/api/download', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
- body: JSON.stringify({tids})
+ body: JSON.stringify({tids: tids})
});
- const result = await resp.json();
-
- result.results.forEach(r => {
+ var result = await resp.json();
+ result.results.forEach(function(r) {
downloads[r.tid] = r.ok ? 'done' : 'error';
});
renderFilms();
-
- const ok = result.results.filter(r => r.ok).length;
- showToast(`✅ ${ok}/${tids.length} Downloads gestartet`);
+ var ok = result.results.filter(function(r) { return r.ok; }).length;
+ showToast('\u2705 ' + ok + '/' + tids.length + ' Downloads gestartet');
}
function showToast(msg) {
- const t = document.getElementById('toast');
+ var t = document.getElementById('toast');
t.textContent = msg;
t.classList.add('show');
- setTimeout(() => t.classList.remove('show'), 3500);
+ setTimeout(function() { t.classList.remove('show'); }, 3500);
}
loadFilms();
@@ -494,6 +542,7 @@ loadFilms();
"""
+
@app.route("/")
def index():
return render_template_string(HTML)