Einen einzelnen Titel neu holen, statt achthundert

Eine neue Quelle wirkt erst beim nächsten Holen der Metadaten. Das ging
bisher nur je Mediathek: achthundert Titel, eine Viertelstunde — nur um
an einem Film zu sehen, ob ein Schlüssel etwas bringt. Wer auf einer
Detailseite bemerkt, dass IMDb und Rotten Tomatoes fehlen, hatte von dort
keinen Weg dorthin.

Der Server kann eine Auswahl längst; es fehlte bloss die Kennung der
Mediathek in der Antwort, damit die Seite weiss, wohin ihr Titel gehört.
Der runde Knopf holt diesen einen Titel, wartet den Lauf ab und zeichnet
die Seite neu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-09 16:02:39 +02:00
co-authored by Claude Opus 5
parent 18db89399d
commit e05bbfc2cd
5 changed files with 75 additions and 5 deletions
+8
View File
@@ -81,6 +81,10 @@ export type Film = {
sortTitle: string | null;
/** Ob der Sortiertitel von Hand gesetzt wurde. */
sortTitlePinned: boolean;
/** Zu welcher Mediathek der Titel gehört — nur beim Einzelabruf.
*
* Das Auffrischen hängt an der Mediathek, nicht am Titel. */
libraryId: string | null;
};
export type Serie = {
id: string; title: string; year: number | null; overview: string | null;
@@ -104,6 +108,10 @@ export type Serie = {
titlePinned: boolean;
sortTitle: string | null;
sortTitlePinned: boolean;
/** Zu welcher Mediathek der Titel gehört — nur beim Einzelabruf.
*
* Das Auffrischen hängt an der Mediathek, nicht am Titel. */
libraryId: string | null;
};
export type Folge = {
id: string; season: number; episode: number;
+2
View File
@@ -39,6 +39,8 @@ export const icons = {
abspielen: rahmen('<path d="M8 5.5v13l11-6.5z"/>', true),
haken: rahmen('<path d="m5 12.5 4.5 4.5L19 7"/>'),
hakenKreis: rahmen('<circle cx="12" cy="12" r="9"/><path d="m8 12.3 2.8 2.7L16 9.6"/>'),
// Kreisbogen mit Pfeilspitze — das gewohnte Zeichen fürs Neuholen.
auffrischen: rahmen('<path d="M20 12a8 8 0 1 1-2.4-5.7"/><path d="M20 3.5V9h-5.5"/>'),
stift: rahmen('<path d="M4 20h4L19.5 8.5a2.1 2.1 0 0 0-3-3L5 17v3z"/>'),
download: rahmen('<path d="M12 3v12"/><path d="m7.5 11 4.5 4.5L16.5 11"/><path d="M4 20h16"/>'),
links: rahmen('<path d="M15 5 8 12l7 7"/>'),
+39 -1
View File
@@ -2,7 +2,7 @@ import { ApiFehler,
film as filmLaden, serie as serieLaden, folgen,
vorschlaege, zuordnen, bildAdresse, istAdmin, gesehen, favorit, weglegen,
type Film, type Serie, type Folge, type Datei, type Stand,
type Mitwirkender, type Spur, aehnliche,
type Mitwirkender, type Spur, aehnliche, metadatenAuffrischen, scanstand,
} from '../api';
import {
esc, dauer, groesse, knopf, feld, fehlerzeile, leer, anteil, meldung, hinweisZeigen,
@@ -61,6 +61,26 @@ function rang(quelle: string): number {
return stelle < 0 ? QUELLENFOLGE.length : stelle;
}
/** Wartet, bis der angestossene Lauf durch ist.
*
* **Ein einzelner Titel dauert Sekunden.** Ein Fortschrittsbalken dafür
* wäre mehr Gerät als Nutzen; es reicht, die Seite danach neu zu zeichnen.
*
* **Nach einer Minute wird nicht weiter gewartet.** So lange kann es nur
* dauern, wenn etwas anderes läuft — ein ganzer Scan etwa. Dann ist weiter
* zu warten sinnloser, als zu zeigen, was gerade dasteht. */
async function laufAbwarten(mediathek: string): Promise<void> {
for (let i = 0; i < 60; i++) {
await new Promise(fertig => window.setTimeout(fertig, 1000));
try {
if ((await scanstand(mediathek)).state !== 'running') return;
} catch {
// Antwortet der Stand nicht, ist Weiterwarten geraten statt gewusst.
return;
}
}
}
export function detailseite(art: Art, id: string, zurueck: () => void): HTMLElement {
const wurzel = document.createElement('div');
wurzel.className = 'detail';
@@ -417,6 +437,24 @@ export function detailseite(art: Art, id: string, zurueck: () => void): HTMLElem
async () => { await weglegen(eintrag.id); await laden(); }));
}
// **Diesen einen Titel neu holen, nicht den ganzen Bestand.**
//
// Eine neue Quelle — fanart.tv, OMDb — wirkt erst beim nächsten Holen.
// Bisher ging das nur je Mediathek: achthundert Titel, eine
// Viertelstunde, nur um an einem Film zu sehen, ob ein Schlüssel etwas
// bringt. Der Server kann längst eine Auswahl; es fehlte bloss der Weg
// dorthin von der Seite, auf der man das Fehlen bemerkt.
if (istAdmin() && eintrag.libraryId) {
const mediathek = eintrag.libraryId;
reihe.appendChild(rundKnopf('auffrischen', false, 'Metadaten neu holen',
async () => {
await metadatenAuffrischen(mediathek, [eintrag.id]);
hinweisZeigen('Metadaten werden neu geholt …');
await laufAbwarten(mediathek);
await laden();
}));
}
// **Nicht über `rundKnopf`.** Der schaltet sich beim Klick ab und erst im
// Fehlerfall wieder an — richtig für etwas, das danach die Seite neu lädt.
// Ein Dialog kehrt sofort zurück; der Knopf bliebe für den Rest der Seite