Files
Flaro/Packages/FlixyKit/Sources/MediaKit/MediaLibrary.swift
T
ScarriffleandClaude Opus 5 2dbe260901 Mediatheken stehen sofort da statt sich jedes Mal neu zu laden
Jeder Aufruf einer Mediathek war ein Serverabruf mit Ladekreis davor. Die
Plakate lagen längst auf der Platte; was fehlte, war die Liste, die sagt,
welche davon hierhergehören.

Jetzt liegt die erste Seite als Abzug daneben: beim Aufrufen steht sie
sofort da, der Server wird still nachgefragt, und man sieht in aller Regel
nichts davon. Antwortet er nicht, bleibt der Abzug stehen — eine Liste von
gestern ist im Zug brauchbarer als ein Fehlerbildschirm.

Bewusst nur die erste Seite. Stünden 240 gespeicherte Titel da und der
Server antwortet mit 60, müsste entweder die Liste vor den Augen schrumpfen
oder der Versatz fürs Nachladen wäre falsch.

Gespeichert wird ausserdem nur, was eine Kachel zeigt. Ein Titel aus einer
Listenabfrage bringt jede Spur jeder Datei mit — im Raster steht davon
nichts, und ausgepackt werden müsste es bei jedem Aufrufen, also genau da,
wo der Abzug Zeit sparen soll.

Die Mediathekenliste selbst wird nur als Rettungsanker gemerkt, nicht als
Beschleuniger: sie sofort zu zeigen hiesse, eine Sitzung für fertig zu
erklären, bevor feststeht, dass der Token noch gilt.

Abmelden räumt alles weg. Titel, Zusammenfassungen und Sehfortschritt sind
persönlich.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-28 15:59:15 +02:00

80 lines
2.8 KiB
Swift

import Foundation
/// Eine Mediathek auf dem Server.
public struct MediaLibrary: Sendable, Equatable, Identifiable, Codable {
public enum Kind: String, Sendable, Equatable, Codable {
case movie, show, music, photo, liveTV, other
}
public let id: String
public let title: String
public let kind: Kind
public let thumb: String?
public let art: String?
public init(
id: String,
title: String,
kind: Kind,
thumb: String? = nil,
art: String? = nil
) {
self.id = id
self.title = title
self.kind = kind
self.thumb = thumb
self.art = art
}
/// Ob die App mit dieser Mediathek etwas anfangen kann.
///
/// Musik und Fotos sind bewusst außen vor: sie bräuchten eigene Ansichten
/// und eigene Wiedergabe, und eine halbherzige Musikansicht ist schlechter
/// als gar keine. Live-TV hat einen eigenen Bildschirm und gehört nicht
/// noch einmal in die Mediathekenliste.
///
/// **`other` zählt dazu.** Hier stand vorher `movie || show`, und alles
/// Übrige fiel wortlos heraus — auch eine Mediathek mit gemischtem
/// Inhalt, die Jellyfin ohne `CollectionType` meldet. Wer Filme und
/// Serien nicht getrennt hat, sah sie nirgends: nicht in der
/// Seitenleiste, nicht auf der Startseite, nirgends eine Meldung. Eine
/// unbekannte Art ist kein Grund, etwas zu verschweigen — sie ist nur
/// ein Grund, nichts über den Inhalt anzunehmen.
public var isSupported: Bool {
switch kind {
case .movie, .show, .other: true
case .music, .photo, .liveTV: false
}
}
}
/// Eine Reihe auf der Startseite oder in den Suchergebnissen.
public struct MediaRowGroup: Sendable, Equatable, Identifiable {
/// Eine stabile Kennung für diese Reihe.
///
/// Sie entscheidet, welche Reihe der Nutzer ausgeblendet oder verschoben
/// hat — und muss deshalb über Abrufe hinweg gleich bleiben, auch wenn
/// sich der angezeigte Titel ändert.
public let id: String
public let title: String
/// Der Pfad, unter dem es „alles davon" gäbe.
public let moreKey: String?
public let items: [MediaItem]
public init(id: String, title: String, moreKey: String? = nil, items: [MediaItem] = []) {
self.id = id
self.title = title
self.moreKey = moreKey
self.items = items
}
/// Ob diese Reihe das Weiterschauen ist.
///
/// Sie wird anders dargestellt: dort zeigt das Szenenbild, wo man
/// aufgehört hat, während man sonst nach Plakaten sucht.
public var isContinueWatching: Bool {
let lowered = id.lowercased()
return lowered.contains("continue") || lowered.contains("resume") || lowered.contains("nextup")
}
}