Eine Folge weiter, eine zurück — ohne den Spieler zu verlassen

Wer eine Serie schaut, will blättern können. Bisher gab es genau einen
Knopf dafür, und der erschien erst am Ende: „Nächste Folge", wenn der
Abspann durchgelaufen war. Zurück ging gar nicht — nur über die
Serienseite, und die beendet die Wiedergabe.

Jetzt stehen beide Knöpfe in der Bedienleiste, in der App wie im Web,
links und rechts vom Abspielknopf. Nur bei Serien: bei einem Film
antwortet der Server mit 404, bei der letzten Folge mit 204, und beides
heisst hier „kein Knopf". Sie erscheinen also von selbst nur dort, wo
sie etwas tun.

Der Server kannte nur den Weg vorwärts. Jetzt gibt es `/previous`
daneben, und beide Richtungen kommen aus derselben Rechnung — als zwei
Endpunkte abgeschrieben liefen sie auseinander, sobald einer etwas
dazubekommt. Jellyfin hat kein Gegenstück zu „NextUp"; dort entsteht
die vorige Folge aus der Folgenliste der Serie.

Beim Wechsel gilt weiter, was für die Serie an Sprache eingestellt ist.
Ohne das spränge die nächste Folge auf die erste Tonspur der Datei
zurück — bei deutschen Veröffentlichungen also auf Deutsch, mitten in
einer Serie, die man im Original schaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-12 21:11:09 +02:00
co-authored by Claude Opus 5
parent bcbe5557d7
commit acba683c94
11 changed files with 319 additions and 55 deletions
@@ -348,6 +348,20 @@ public func isInLocalNetwork() async -> Bool {
return next.first { $0.id != item.id }
}
/// Die Folge davor.
///
/// **Über die Folgenliste der Serie, nicht über einen eigenen
/// Endpunkt.** Jellyfin hat ein „NextUp", aber kein Gegenstück dazu —
/// und die Liste gibt es ohnehin, weil die Serienseite sie zeigt. Eine
/// Anfrage für einen Knopf, der selten gedrückt wird, ist der bessere
/// Tausch gegenüber gar keinem Knopf.
public func previousEpisode(before item: MediaItem) async throws(MediaBackendError) -> MediaItem? {
guard let seriesID = item.seriesID else { return nil }
let folgen = try await episodes(inSeries: seriesID)
guard let stelle = folgen.firstIndex(where: { $0.id == item.id }), stelle > 0 else { return nil }
return folgen[stelle - 1]
}
// MARK: - Bilder
public nonisolated func artworkURL(path: String?, width: Int, height: Int) -> URL? {