Der Abschnitt verschwand alle drei Sekunden und kam wieder

`laden()` setzte `innerHTML = ''` und baute die Mediathekenliste neu —
während eines Scans alle drei Sekunden. Der ganze Abschnitt flackerte
sichtbar, und wer gerade auf einen Knopf zielte, klickte ins Leere.
Schlimmer: jeder Neuaufbau startete über `verfolgen(false)` einen
weiteren Takt. Nach einer Minute liefen zwanzig davon nebeneinander.

Jetzt wird fortgeschrieben statt neu gezeichnet: eine Zeile je
Mediathek, die bleibt, und nur Kopfzeile, Prüfungsknopf und
Freigabeknopf ändern sich. Belegt im Browser — nach einem Auffrischen
sind es dieselben Knoten, nur die Beschriftung ist eine andere.

Dieselbe Behandlung für die Seitenleiste. Und weil Seitenleiste und
Verwaltung getrennt nachfragten, zeigten sie zwei Momente — 95 hier, 84
dort, während im Hintergrund Doppelte zusammengelegt wurden. Die
Verwaltung reicht ihren Stand jetzt weiter: ein Abruf, zwei Anzeigen.

Dazu zwei Dinge, die beim Prüfen auffielen. Zurücksetzen und Entfernen
prallen jetzt serverseitig mit 409 ab, solange ein Lauf läuft — die
Oberfläche sperrt die Knöpfe, aber darauf darf sich der Server nicht
verlassen; ein Aufruf von Hand während eines Scans liess den Lauf an
einer DbUpdateConcurrencyException sterben. Und in der
Fortschrittszeile steht beim Holen der Folgenmetadaten jetzt der
Serienname: „Folge 2×13" allein sagt bei 3815 Folgen nichts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-04 18:21:43 +02:00
co-authored by Claude Opus 5
parent a6e9a6e425
commit 960cca3dae
16 changed files with 311 additions and 85 deletions
+13 -5
View File
@@ -325,9 +325,12 @@ public sealed class MetadataEnricher(
private async Task<int> FolgenZuordnen(
Guid libraryId, bool erneut, IProgress<Scanschritt>? fortschritt, CancellationToken ct)
{
// **Mit Titel, nicht nur mit Kennung.** In der Fortschrittszeile stand
// „Hole Metadaten zu Folge 2×13" — und bei 3815 Folgen aus achtzig
// Serien sagt eine Folgennummer ohne Serie überhaupt nichts.
var serien = await db.Series
.Where(s => s.LibraryId == libraryId && s.TmdbId != null)
.Select(s => new { s.Id, TmdbId = s.TmdbId!.Value })
.Select(s => new { s.Id, TmdbId = s.TmdbId!.Value, s.Title })
.ToListAsync(ct);
if (serien.Count == 0) return 0;
@@ -336,16 +339,21 @@ public sealed class MetadataEnricher(
.Where(f => kennungen.Contains(f.SeriesId) && (erneut || f.Overview == null))
.ToListAsync(ct);
// Einmal nachschlagbar machen: `First` je Folge wäre bei 3815 Folgen
// und achtzig Serien eine Viertelmillion Vergleiche.
var nachKennung = serien.ToDictionary(s => s.Id);
var zugeordnet = 0;
var durch = 0;
foreach (var folge in offen)
{
ct.ThrowIfCancellationRequested();
if (!nachKennung.TryGetValue(folge.SeriesId, out var serie)) continue;
fortschritt?.Report(new Scanschritt(
Scanphase.Holen,
$"Folge {folge.SeasonNumber}x{folge.EpisodeNumber:00}", ++durch, offen.Count));
ct.ThrowIfCancellationRequested();
var serie = serien.First(s => s.Id == folge.SeriesId);
$"{serie.Title} {folge.SeasonNumber}x{folge.EpisodeNumber:00}",
++durch, offen.Count));
var gefunden = await anbieter.FindEpisodeAsync(serie.TmdbId, folge.SeasonNumber, folge.EpisodeNumber, ct);
if (gefunden is null) continue;