import Foundation /// Was Flaro über die Leitung schickt. /// /// Ein Spiegel der `Contracts.cs` auf der Serverseite, und nur das: hier wird /// nichts gerechnet und nichts gedeutet. Die Übersetzung in die neutralen /// Typen steht in `FlaroBackend+Mapping`. /// /// **Die Felder heissen wie dort.** Keine `CodingKeys`, keine Umbenennung: /// ASP.NET Core schreibt `camelCase`, Swift liest `camelCase`, und jede /// Abweichung wäre eine Stelle, an der beim nächsten Serverfeld jemand /// nachziehen müsste. enum Wire { struct Page: Decodable, Sendable { let items: [T] let total: Int } struct SystemInfo: Decodable, Sendable { let version: String? let serverName: String? let needsSetup: Bool let attributions: [Attribution]? } struct Attribution: Decodable, Sendable { let text: String let logoUrl: String let url: String } struct LoginResponse: Decodable, Sendable { let token: String let user: User } struct User: Decodable, Sendable { let id: String let userName: String let isAdministrator: Bool } struct Library: Decodable, Sendable { let id: String let name: String let kind: String let path: String } struct Stream: Decodable, Sendable { let index: Int let kind: String let codec: String? let language: String? let title: String? let isDefault: Bool let isForced: Bool let channels: Int? let width: Int? let height: Int? } struct File: Decodable, Sendable { let id: String let fileName: String let sizeBytes: Int64 let container: String? let durationSeconds: Double? let streams: [Stream] } struct ItemState: Decodable, Sendable { let positionSeconds: Double let runtimeSeconds: Double? let watched: Bool let playCount: Int let favourite: Bool let rating: Int? let dismissed: Bool let lastPlayedAt: Date? } struct Movie: Decodable, Sendable { let id: String let title: String let year: Int? let overview: String? let posterImage: String? let backdropImage: String? let files: [File] let state: ItemState? } struct Series: Decodable, Sendable { let id: String let title: String let year: Int? let overview: String? let posterImage: String? let backdropImage: String? let episodeCount: Int let seasons: [Int] let unwatchedCount: Int } struct Episode: Decodable, Sendable { let id: String let season: Int let episode: Int let title: String? let overview: String? let stillImage: String? let files: [File] let state: ItemState? } /// Eine Kachel aus „Weiterschauen" oder „Nächste Folge". struct Started: Decodable, Sendable { let id: String let kind: String let title: String let subTitle: String? let season: Int? let episode: Int? let year: Int? let posterImage: String? let backdropImage: String? let state: ItemState } struct CodeResponse: Decodable, Sendable { let code: String let handle: String let expiresAt: Date } /// `state` ist „pending", „approved" oder „expired". struct CodeState: Decodable, Sendable { let state: String let login: LoginResponse? } struct CodeRequest: Encodable, Sendable { let deviceName: String let deviceId: String } struct Delivery: Decodable, Sendable { let method: String let reasons: [String] let audioToEncode: [Int] let subtitlesDropped: [Int] let packageState: String let progress: Double let error: String? } // --- Was hinausgeht -------------------------------------------------- struct LoginRequest: Encodable, Sendable { let userName: String let password: String let deviceName: String let deviceId: String } struct ProgressRequest: Encodable, Sendable { let positionSeconds: Double let runtimeSeconds: Double? } struct WatchedRequest: Encodable, Sendable { let watched: Bool } struct FavouriteRequest: Encodable, Sendable { let favourite: Bool } struct RatingRequest: Encodable, Sendable { let rating: Int? } }