feat: Web-UI zeigt KI-Filmbeschreibungen, Darsteller und Regisseur
Die filmCard-Funktion rendert jetzt die angereicherten Daten: - 3-6 Sätze Beschreibung - Hauptdarsteller + Regisseur - Land, Jahr, Genre als Metadaten-Zeile
This commit is contained in:
parent
45b2903fb6
commit
0b495c3544
1 changed files with 49 additions and 19 deletions
|
|
@ -197,15 +197,26 @@ HTML = r"""<!DOCTYPE html>
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.film-info {
|
.film-details {
|
||||||
color: var(--muted);
|
color: #9898b8;
|
||||||
font-size: 14px;
|
font-size: 13.5px;
|
||||||
margin-top: 6px;
|
margin-top: 8px;
|
||||||
font-style: italic;
|
line-height: 1.5;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity .4s;
|
transition: opacity .4s;
|
||||||
}
|
}
|
||||||
.film-info.loaded { opacity: 1; }
|
.film-details.loaded { opacity: 1; }
|
||||||
|
.film-desc {
|
||||||
|
color: #a8a8c4;
|
||||||
|
font-size: 13.5px;
|
||||||
|
line-height: 1.55;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
.film-crew {
|
||||||
|
color: #8888a8;
|
||||||
|
font-size: 12.5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
.days-badge {
|
.days-badge {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
@ -427,6 +438,12 @@ let infoLoading = false;
|
||||||
let dlProgress = {};
|
let dlProgress = {};
|
||||||
let polling = false;
|
let polling = false;
|
||||||
|
|
||||||
|
function esc(s) {
|
||||||
|
var d = document.createElement('div');
|
||||||
|
d.textContent = s;
|
||||||
|
return d.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
async function loadFilmInfo(films) {
|
async function loadFilmInfo(films) {
|
||||||
if (infoLoading) return;
|
if (infoLoading) return;
|
||||||
var missing = films.filter(function(f) { return !filmInfoCache[f.tid]; });
|
var missing = films.filter(function(f) { return !filmInfoCache[f.tid]; });
|
||||||
|
|
@ -443,20 +460,32 @@ async function loadFilmInfo(films) {
|
||||||
missing.forEach(function(f) {
|
missing.forEach(function(f) {
|
||||||
var d = data[f.title];
|
var d = data[f.title];
|
||||||
if (!d) return;
|
if (!d) return;
|
||||||
var parts = [];
|
filmInfoCache[f.tid] = d;
|
||||||
if (d.year) parts.push(d.year);
|
var el = document.getElementById('details-' + f.tid);
|
||||||
if (d.countries && d.countries.length) parts.push(d.countries.join('/'));
|
if (el) {
|
||||||
if (d.genres && d.genres.length) parts.push(d.genres.join(', '));
|
el.innerHTML = buildDetails(d);
|
||||||
if (parts.length) {
|
el.classList.add('loaded');
|
||||||
filmInfoCache[f.tid] = parts.join(' \u00b7 ');
|
|
||||||
var el = document.getElementById('info-' + f.tid);
|
|
||||||
if (el) { el.textContent = filmInfoCache[f.tid]; el.classList.add('loaded'); }
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
infoLoading = false;
|
infoLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildDetails(d) {
|
||||||
|
if (!d) return '';
|
||||||
|
var parts = [];
|
||||||
|
if (d.year) parts.push(esc(d.year));
|
||||||
|
if (d.countries && d.countries.length) parts.push(esc(d.countries.join('/')));
|
||||||
|
if (d.genres && d.genres.length) parts.push(esc(d.genres.join(', ')));
|
||||||
|
var metaLine = parts.length ? '<div style="margin-bottom:4px">' + parts.join(' \u00b7 ') + '</div>' : '';
|
||||||
|
var descLine = d.description ? '<div class="film-desc">' + esc(d.description) + '</div>' : '';
|
||||||
|
var crewParts = [];
|
||||||
|
if (d.actors && d.actors.length) crewParts.push('Mit ' + esc(d.actors.join(', ')));
|
||||||
|
if (d.director) crewParts.push('Regie: ' + esc(d.director));
|
||||||
|
var crewLine = crewParts.length ? '<div class="film-crew">' + crewParts.join(' \u00b7 ') + '</div>' : '';
|
||||||
|
return metaLine + descLine + crewLine;
|
||||||
|
}
|
||||||
|
|
||||||
async function loadFilms() {
|
async function loadFilms() {
|
||||||
var resp = await fetch('/api/films');
|
var resp = await fetch('/api/films');
|
||||||
var data = await resp.json();
|
var data = await resp.json();
|
||||||
|
|
@ -542,18 +571,19 @@ function filmCard(f) {
|
||||||
extraLine = '<div class="dl-status dl-done">Gespeichert</div>';
|
extraLine = '<div class="dl-status dl-done">Gespeichert</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var infoText = filmInfoCache[f.tid] || '';
|
var cached = filmInfoCache[f.tid];
|
||||||
var infoClass = infoText ? 'film-info loaded' : 'film-info';
|
var detailsHtml = cached ? buildDetails(cached) : '';
|
||||||
|
var detailsClass = detailsHtml ? 'film-details loaded' : 'film-details';
|
||||||
|
|
||||||
return '<div class="' + cardClass + '" onclick="toggleFilm(' + f.tid + ')" data-tid="' + f.tid + '">'
|
return '<div class="' + cardClass + '" onclick="toggleFilm(' + f.tid + ')" data-tid="' + f.tid + '">'
|
||||||
+ statusEl
|
+ statusEl
|
||||||
+ '<div class="film-title">' + f.title + '</div>'
|
+ '<div class="film-title">' + esc(f.title) + '</div>'
|
||||||
+ '<div class="film-meta">'
|
+ '<div class="film-meta">'
|
||||||
+ '<span>' + f.station + '</span>'
|
+ '<span>' + esc(f.station) + '</span>'
|
||||||
+ '<span class="badge ' + (f.cinema ? 'badge-kino' : 'badge-tv') + '">' + (f.cinema ? 'Kino' : 'TV') + '</span>'
|
+ '<span class="badge ' + (f.cinema ? 'badge-kino' : 'badge-tv') + '">' + (f.cinema ? 'Kino' : 'TV') + '</span>'
|
||||||
+ '<span class="days-badge ' + daysClass + '">' + daysLabel + '</span>'
|
+ '<span class="days-badge ' + daysClass + '">' + daysLabel + '</span>'
|
||||||
+ '</div>'
|
+ '</div>'
|
||||||
+ '<div class="' + infoClass + '" id="info-' + f.tid + '">' + infoText + '</div>'
|
+ '<div class="' + detailsClass + '" id="details-' + f.tid + '">' + detailsHtml + '</div>'
|
||||||
+ extraLine
|
+ extraLine
|
||||||
+ '</div>';
|
+ '</div>';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue