Ein Download sah aus wie eine Videodatei, nicht wie ein Film

Vier Dinge, die beim Ausprobieren auffielen.

**Die Plakate blieben grau.** Sie lagen auf der Platte, der Lader wollte
sie aber nicht: er verlangte von jeder Antwort eine HTTPURLResponse, und
eine Datei antwortet nicht so. Jede lokale Adresse kam als `nil` zurück.

**Eine Serie hatte ohnehin nie ein Plakat.** Heruntergeladen wird nie die
Serie, nur ihre Folgen — und deren Bild ist das Szenenbild, quer. Jetzt
kommt das Serienplakat unter dem Serienschlüssel mit und geht mit der
letzten Folge wieder.

**Zwanzig Folgen waren zwanzig Kacheln.** Jetzt steht die Serie einmal
da, darunter wie viele Folgen bereitliegen; welche genau, zeigt ihre
Seite — auch ohne Server, dann aus dem, was auf dem Gerät liegt.

**Das Bild wurde schwarz, sobald jemand auf „Bildfüllend" wechselte.**
Daran war ein eigener ViewModifier schuld, der zwischen
`ignoresSafeArea()` und gar nichts umschaltete. Genau das ist in SwiftUI
ein Zweig: der Baum darunter wurde neu gebaut, die Bildebene mit ihm.
`edges: []` ignoriert nichts und bleibt doch derselbe Modifikator.

Dazu „Als Nächstes": die Reihe begann am Anfang der Serie statt dort, wo
der Benutzer steht. Wer bei Folge 2 war und Folge 1 nie abgehakt hatte,
bekam Folge 1 vorgeschlagen — und das Abhaken half nicht, weil die
Kachel sich nur selbst einen Haken malte, statt zu verschwinden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-12 20:20:27 +02:00
co-authored by Claude Opus 5
parent 8f0568cb6c
commit 79d7d04583
14 changed files with 388 additions and 63 deletions
@@ -363,15 +363,35 @@ public static class PlaybackEndpoints
{
if (serienzustaende.GetValueOrDefault(x.SeriesId) is { Dismissed: true }) continue;
var naechste = folgen
var derSerie = folgen
.Where(f => f.SeriesId == x.SeriesId)
.OrderBy(f => f.SeasonNumber).ThenBy(f => f.EpisodeNumber)
.ToList();
// **Die Reihe fängt dort an, wo der Benutzer steht — nicht
// am Anfang der Serie.**
//
// Hier stand „die erste Folge ohne Häkchen". Wer bei Folge 2
// mittendrin ist und Folge 1 nie abgehakt hat — weil er sie
// nicht ganz zu Ende gesehen hat, oder weil er gleich bei
// Folge 2 eingestiegen ist —, bekam Folge 1 vorgeschlagen.
// Und das Abhaken von Folge 1 half nicht: dann kam Folge 2,
// obwohl die längst in „Weiterschauen" steht.
//
// Massgeblich ist die **letzte** angefasste Folge. Ist sie
// noch offen, läuft sie — dann gehört die Serie nach
// „Weiterschauen" und nicht hierher. Ist sie durch, ist die
// Folge danach dran.
var letzte = derSerie.FindLastIndex(
f => Angefasst(zustände.GetValueOrDefault(f.Id)));
if (letzte < 0) continue;
if (zustände.GetValueOrDefault(derSerie[letzte].Id) is not { Watched: true }) continue;
var naechste = derSerie.Skip(letzte + 1)
.FirstOrDefault(f => zustände.GetValueOrDefault(f.Id) is not { Watched: true });
// Nichts offen — die Serie ist durch.
if (naechste is null) continue;
// Mittendrin: steht bereits in „Weiterschauen".
if (zustände.GetValueOrDefault(naechste.Id) is { InProgress: true }) continue;
if (!serien.TryGetValue(x.SeriesId, out var serie)) continue;
var zustand = zustände.GetValueOrDefault(naechste.Id);
@@ -564,6 +584,18 @@ public static class PlaybackEndpoints
/// Folge" zeigt überwiegend Folgen ohne Stand, und ein Client, der für
/// jede davon einen Sonderfall braucht, vergisst ihn irgendwo.
/// </remarks>
/// <summary>Ob der Benutzer diese Folge überhaupt schon angefasst hat.</summary>
///
/// <remarks>
/// Eine Zeile allein genügt nicht: sie entsteht auch, wenn jemand nur
/// einen Stern vergibt. Angefasst heisst gesehen, angefangen oder
/// ausdrücklich weggelegt.
/// </remarks>
private static bool Angefasst(UserItemState? zustand) =>
zustand is not null
&& (zustand.Watched || zustand.InProgress || zustand.Dismissed
|| zustand.Position > TimeSpan.Zero);
private static ItemStateResponse Leer() => new(0, null, false, 0, false, null, false, null);
/// <summary>Macht aus Zuständen Einträge mit Titel und Bild.</summary>