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:
co-authored by
Claude Opus 5
parent
8f0568cb6c
commit
79d7d04583
@@ -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>
|
||||
|
||||
@@ -764,6 +764,92 @@ public class PlaybackTests
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>Wer bei Folge 2 steht, bekommt nicht Folge 1 angeboten.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// <b>Der Fall aus dem Gebrauch.</b> Folge 1 halb gesehen und liegen
|
||||
/// gelassen, dann bei Folge 2 weitergemacht — und „Als Nächstes" schlug
|
||||
/// Folge 1 vor, weil sie die erste ohne Häkchen war. Die Reihe sagt aber
|
||||
/// nicht, was man übersprungen hat, sondern was als Nächstes dran ist.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public async Task Wer_bei_Folge_zwei_steht_bekommt_nicht_Folge_eins_vorgeschlagen()
|
||||
{
|
||||
Datei("Dark/Season 01/Dark - S01E01 - Geheimnisse.mkv");
|
||||
Datei("Dark/Season 01/Dark - S01E02 - Luegen.mkv");
|
||||
Datei("Dark/Season 01/Dark - S01E03 - Gestern.mkv");
|
||||
|
||||
using var server = new FlaroServer();
|
||||
var client = await Eingelesen(server, "Shows");
|
||||
|
||||
var serien = await client.GetFromJsonAsync<Page<SeriesResponse>>("/api/v1/series");
|
||||
var folgen = await client.GetFromJsonAsync<Page<EpisodeResponse>>(
|
||||
$"/api/v1/series/{serien!.Items[0].Id}/episodes");
|
||||
|
||||
// Folge 1 angefangen und liegen gelassen, Folge 2 läuft gerade.
|
||||
await Melden(client, folgen!.Items[0].Id, 300, 2700);
|
||||
await Melden(client, folgen.Items[1].Id, 900, 2700);
|
||||
|
||||
var naechste = await client.GetFromJsonAsync<Page<ContinueEntry>>("/api/v1/home/next");
|
||||
Assert.That(naechste!.Items, Is.Empty,
|
||||
"Folge 2 läuft und steht in Weiterschauen, also hat Als Naechstes nichts anzubieten");
|
||||
}
|
||||
|
||||
/// <summary>Und abhaken holt die Serie nicht zurück.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// Wer Folge 1 nachträglich abhakt, hat damit nicht gesagt, dass er
|
||||
/// Folge 2 noch einmal anfangen will — die läuft ja.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public async Task Folge_eins_abhaken_holt_die_Serie_nicht_zurueck()
|
||||
{
|
||||
Datei("Dark/Season 01/Dark - S01E01 - Geheimnisse.mkv");
|
||||
Datei("Dark/Season 01/Dark - S01E02 - Luegen.mkv");
|
||||
|
||||
using var server = new FlaroServer();
|
||||
var client = await Eingelesen(server, "Shows");
|
||||
|
||||
var serien = await client.GetFromJsonAsync<Page<SeriesResponse>>("/api/v1/series");
|
||||
var folgen = await client.GetFromJsonAsync<Page<EpisodeResponse>>(
|
||||
$"/api/v1/series/{serien!.Items[0].Id}/episodes");
|
||||
|
||||
await Melden(client, folgen!.Items[1].Id, 900, 2700);
|
||||
await client.PutAsJsonAsync($"/api/v1/items/{folgen.Items[0].Id}/watched",
|
||||
new WatchedRequest(true));
|
||||
|
||||
var naechste = await client.GetFromJsonAsync<Page<ContinueEntry>>("/api/v1/home/next");
|
||||
Assert.That(naechste!.Items, Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>Nach der letzten angefassten Folge geht es weiter.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// Folge 1 und 2 durch, Folge 3 nie angefasst: dann ist Folge 3 dran —
|
||||
/// und nicht Folge 1, nur weil dort irgendwann einmal ein Häkchen
|
||||
/// fehlte.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public async Task Nach_der_letzten_gesehenen_Folge_kommt_die_naechste()
|
||||
{
|
||||
Datei("Dark/Season 01/Dark - S01E01 - Geheimnisse.mkv");
|
||||
Datei("Dark/Season 01/Dark - S01E02 - Luegen.mkv");
|
||||
Datei("Dark/Season 01/Dark - S01E03 - Gestern.mkv");
|
||||
|
||||
using var server = new FlaroServer();
|
||||
var client = await Eingelesen(server, "Shows");
|
||||
|
||||
var serien = await client.GetFromJsonAsync<Page<SeriesResponse>>("/api/v1/series");
|
||||
var folgen = await client.GetFromJsonAsync<Page<EpisodeResponse>>(
|
||||
$"/api/v1/series/{serien!.Items[0].Id}/episodes");
|
||||
|
||||
await client.PutAsJsonAsync($"/api/v1/items/{folgen!.Items[1].Id}/watched",
|
||||
new WatchedRequest(true));
|
||||
|
||||
var naechste = await client.GetFromJsonAsync<Page<ContinueEntry>>("/api/v1/home/next");
|
||||
Assert.That(naechste!.Items.Single().Episode, Is.EqualTo(3));
|
||||
}
|
||||
|
||||
/// <summary>Was in „Weiterschauen" steht, steht nicht nochmal daneben.</summary>
|
||||
[Test]
|
||||
public async Task Eine_angefangene_Folge_erscheint_nur_in_einer_Reihe()
|
||||
|
||||
Reference in New Issue
Block a user