Die Kachel zeigte auf die Folge und wollte zur Serie
„Nächste Folge" führte ins Leere, und es lag weder am Scan noch am Auffrischen: die Kachel trug die Folgenkennung und öffnete damit eine Serienseite — die es unter dieser Kennung nie gibt. Heraus kam ausgerechnet dort „Diese Serie gibt es nicht mehr", wo man gerade weiterschauen wollte. Der Server kannte die Serie an beiden Stellen und schickte sie nur nicht mit. Wohin die Kachel führt und was sie misst, ist jetzt getrennt. Beides auf dieselbe Kennung zu legen wäre der nächste Fehler gewesen: „Als gesehen markieren" hätte die ganze Serie abgehakt statt der einen Folge, die man zur Hälfte gesehen hat. Dazu Streichen wie im Dateimanager: gedrückt halten und darüberfahren wählt aus, rückwärts über Gewähltes nimmt wieder weg. Ein kurzer Klick bleibt, was er war. Abgetastet wird die Strecke zwischen zwei Zeigerereignissen, nicht nur deren Endpunkte — gemessen: ein Zug über vier Kacheln erwischte sonst die erste und die letzte. Plakate lassen sich nicht mehr durch die Gegend schleppen. „Abwählen" ist ein Kreuz geworden; als vierter Knopf neben drei Aktionen sah es aus, als täte es etwas mit den Titeln. In der kleinen Leiste lag das Vorschaubild über dem Fortschrittsstrich und verdeckte ihn rechts. Und ein Klick genau darauf tat nichts, obwohl das die Stelle ist, auf die man zeigt — jetzt holt auch das Bild den Film zurück. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7df9fa6c01
commit
c46063637f
@@ -486,11 +486,26 @@ public sealed record ItemStateResponse(
|
||||
/// steht in <c>Title</c> die Serie und in <c>SubTitle</c> die Folge — so liest
|
||||
/// sich die Kachel wie bei Plex: oben, worum es geht, darunter, wo man ist.
|
||||
/// </remarks>
|
||||
/// <param name="Id">
|
||||
/// Die Kennung des Titels selbst — bei einer Folge also die der Folge. Dorthin
|
||||
/// geht der Fortschritt.
|
||||
/// </param>
|
||||
/// <param name="SeriesId">
|
||||
/// <b>Zu welcher Serie die Folge gehört</b> — <c>null</c> bei einem Film.
|
||||
///
|
||||
/// <para>
|
||||
/// <b>Ohne diese Angabe führte die Kachel ins Leere.</b> Sie trug die
|
||||
/// Folgenkennung und sollte damit eine Serienseite öffnen; die gibt es unter
|
||||
/// dieser Kennung nie, und heraus kam „Diese Serie gibt es nicht mehr" —
|
||||
/// ausgerechnet unter „Nächste Folge", wo man gerade weiterschauen wollte.
|
||||
/// </para>
|
||||
/// </param>
|
||||
public sealed record ContinueEntry(
|
||||
Guid Id, string Kind, string Title, string? SubTitle,
|
||||
int? Season, int? Episode, int? Year,
|
||||
string? PosterImage, string? BackdropImage,
|
||||
ItemStateResponse State);
|
||||
ItemStateResponse State,
|
||||
Guid? SeriesId = null);
|
||||
|
||||
/// <summary>Eine laufende Wiedergabe — für das Dashboard.</summary>
|
||||
public sealed record SessionResponse(
|
||||
|
||||
@@ -318,7 +318,8 @@ public static class PlaybackEndpoints
|
||||
naechste.Id, "episode", serie.Title, naechste.Title,
|
||||
naechste.SeasonNumber, naechste.EpisodeNumber, null,
|
||||
serie.PosterImage, naechste.StillImage ?? serie.PosterImage,
|
||||
zustand is null ? Leer() : Abbild(zustand)));
|
||||
zustand is null ? Leer() : Abbild(zustand),
|
||||
SeriesId: x.SeriesId));
|
||||
}
|
||||
|
||||
return Results.Ok(new Page<ContinueEntry>(liste, liste.Count));
|
||||
@@ -432,7 +433,8 @@ public static class PlaybackEndpoints
|
||||
else if (z.EpisodeId is { } folge && folgendaten.TryGetValue(folge, out var f))
|
||||
liste.Add(new ContinueEntry(
|
||||
f.Id, "episode", f.SerienTitel, f.FolgenTitel, f.SeasonNumber, f.EpisodeNumber, null,
|
||||
f.PosterImage, f.StillImage ?? f.PosterImage, Abbild(z)));
|
||||
f.PosterImage, f.StillImage ?? f.PosterImage, Abbild(z),
|
||||
SeriesId: f.SerienId));
|
||||
}
|
||||
return liste;
|
||||
}
|
||||
|
||||
@@ -556,6 +556,86 @@ public class PlaybackTests
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>Eine Folge in „Weiterschauen" nennt ihre Serie.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// <b>Ohne diese Angabe führte die Kachel ins Leere.</b> Sie trug die
|
||||
/// Folgenkennung und öffnete damit eine Serienseite — die es unter dieser
|
||||
/// Kennung nie gibt. Heraus kam „Diese Serie gibt es nicht mehr",
|
||||
/// ausgerechnet unter „Nächste Folge", wo man gerade weiterschauen wollte.
|
||||
/// Es lag nicht am Scan und nicht am Auffrischen: die Kachel hat von
|
||||
/// Anfang an auf die falsche Kennung gezeigt.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public async Task Eine_angefangene_Folge_nennt_ihre_Serie()
|
||||
{
|
||||
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 serie = serien!.Items[0];
|
||||
var folgen = await client.GetFromJsonAsync<Page<EpisodeResponse>>(
|
||||
$"/api/v1/series/{serie.Id}/episodes");
|
||||
|
||||
// Mittendrin stehenbleiben — dann steht die Folge in „Weiterschauen".
|
||||
await Melden(client, folgen!.Items[0].Id, 600, 7200);
|
||||
|
||||
var weiter = await client.GetFromJsonAsync<Page<ContinueEntry>>("/api/v1/home/continue");
|
||||
var eintrag = weiter!.Items.Single();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(eintrag.Id, Is.EqualTo(folgen.Items[0].Id), "die Kennung bleibt die der Folge");
|
||||
Assert.That(eintrag.SeriesId, Is.EqualTo(serie.Id), "und daneben steht, wohin sie gehört");
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>Dasselbe für „Nächste Folge".</summary>
|
||||
[Test]
|
||||
public async Task Die_naechste_Folge_nennt_ihre_Serie()
|
||||
{
|
||||
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 serie = serien!.Items[0];
|
||||
var folgen = await client.GetFromJsonAsync<Page<EpisodeResponse>>(
|
||||
$"/api/v1/series/{serie.Id}/episodes");
|
||||
|
||||
// Die erste ganz gesehen — dann ist die zweite „die nächste".
|
||||
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");
|
||||
var eintrag = naechste!.Items.Single();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(eintrag.Id, Is.EqualTo(folgen.Items[1].Id));
|
||||
Assert.That(eintrag.SeriesId, Is.EqualTo(serie.Id));
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>Ein Film hat keine Serie — und behauptet es auch nicht.</summary>
|
||||
[Test]
|
||||
public async Task Ein_angefangener_Film_nennt_keine_Serie()
|
||||
{
|
||||
Datei("Matrix (1999)/Matrix (1999).mkv");
|
||||
|
||||
using var server = new FlaroServer();
|
||||
var client = await Eingelesen(server);
|
||||
var film = await ErsterFilm(client);
|
||||
await Melden(client, film, 600, 7200);
|
||||
|
||||
var weiter = await client.GetFromJsonAsync<Page<ContinueEntry>>("/api/v1/home/continue");
|
||||
Assert.That(weiter!.Items.Single().SeriesId, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Die_naechste_Folge_richtet_sich_nach_Staffel_und_Nummer()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user