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") } }