import Foundation /// Filter und Sortierung einer Mediatheksansicht. /// /// Wird zu Abfrageparametern für Plex — die Filterung passiert also auf dem /// Server. Bei zehntausend Titeln wäre alles andere aussichtslos: die Liste /// erst vollständig zu laden, um sie dann lokal zu durchsuchen, dauert /// Minuten und belegt entsprechend Speicher. public struct LibraryQuery: Sendable, Equatable { public enum Sort: String, Sendable, Equatable, CaseIterable { case titleAscending = "titleSort:asc" case titleDescending = "titleSort:desc" case recentlyAdded = "addedAt:desc" case releaseDate = "originallyAvailableAt:desc" case rating = "rating:desc" case lastViewed = "lastViewedAt:desc" } public var sort: Sort public var unwatchedOnly: Bool public var genre: String? public var year: Int? public var contentRating: String? public var resolution: String? public init( sort: Sort = .titleAscending, unwatchedOnly: Bool = false, genre: String? = nil, year: Int? = nil, contentRating: String? = nil, resolution: String? = nil ) { self.sort = sort self.unwatchedOnly = unwatchedOnly self.genre = genre self.year = year self.contentRating = contentRating self.resolution = resolution } /// Ob überhaupt gefiltert wird — steuert, ob die Oberfläche den /// Filterknopf hervorhebt. public var isFiltering: Bool { unwatchedOnly || genre != nil || year != nil || contentRating != nil || resolution != nil } func queryItems(libraryKind: PlexLibrary.Kind?) -> [URLQueryItem] { var items: [URLQueryItem] = [URLQueryItem(name: "sort", value: sort.rawValue)] // Plex nummeriert die Arten: 1 Film, 2 Serie, 4 Folge. Ohne diese // Angabe liefert eine Serienmediathek alle Folgen einzeln statt der // Serien. switch libraryKind { case .movie: items.append(URLQueryItem(name: "type", value: "1")) case .show: items.append(URLQueryItem(name: "type", value: "2")) default: break } if unwatchedOnly { items.append(URLQueryItem(name: "unwatched", value: "1")) } if let genre { items.append(URLQueryItem(name: "genre", value: genre)) } if let year { items.append(URLQueryItem(name: "year", value: String(year))) } if let contentRating { items.append(URLQueryItem(name: "contentRating", value: contentRating)) } if let resolution { items.append(URLQueryItem(name: "resolution", value: resolution)) } return items } } /// Ein Ausschnitt aus einer längeren Liste. public struct PlexPage: Sendable { public let items: [Element] public let offset: Int /// Wie viele Einträge es insgesamt gibt. public let totalSize: Int public init(items: [Element], offset: Int, totalSize: Int) { self.items = items self.offset = offset self.totalSize = totalSize } public var hasMore: Bool { offset + items.count < totalSize } public var nextOffset: Int { offset + items.count } }