tv-anarchy/Sources/TVAnarchyiOS/BridgeModels.swift
Natalie 17cf518418 feat(ios): downloads (DownloadManager/DownloadsView), remote control view + bridge/player refinements
(cherry picked from commit a1f7e44e17bb41f48976b69f4dbe5278cbad06b2)
2026-06-09 06:38:45 -07:00

117 lines
2.8 KiB
Swift

// Wire models for the plum-control-bridge HTTP API. These mirror the JSON the
// bridge emits (src/http.ts in plum-control-mcp) one-for-one. The iOS app is a
// pure bridge client it never touches the filesystem or SSH so these are the
// only "library" types it knows.
import Foundation
struct BridgeShow: Codable, Identifiable, Hashable {
let id: String
let name: String
let episodeCount: Int
let seasons: [Int]
let episodes: [BridgeEpisode]
}
struct BridgeEpisode: Codable, Identifiable, Hashable {
/// Opaque, server-issued stream id (base64url of the file path on black/plum).
let id: String
let season: Int
let episode: Int
let label: String
let ext: String
/// e.g. "S01E02" compact badge for the list row.
var code: String {
String(format: "S%02dE%02d", season, episode)
}
}
struct ShowsResponse: Codable {
let shows: [BridgeShow]
}
// MARK: - Continue watching / prefetch
struct ResumePoint: Codable, Hashable {
let episodeId: String
let season: Int
let episode: Int
let label: String
let positionSeconds: Double
let durationSeconds: Double?
var code: String { String(format: "S%02dE%02d", season, episode) }
}
struct NextEpisode: Codable, Hashable {
let episodeId: String
let season: Int
let episode: Int
let label: String
}
struct ContinueItem: Codable, Identifiable, Hashable {
let show: String
let showId: String
let resume: ResumePoint?
let next: NextEpisode?
let lastWatched: String
var id: String { showId }
}
struct ContinueResponse: Codable { let items: [ContinueItem] }
struct ResumeResponse: Codable { let positionSeconds: Double }
// MARK: - Remote transport (Black TV)
struct RemoteStatus: Codable, Hashable {
let playing: Bool
let paused: Bool?
let title: String?
let volume: Double?
let position: Double?
let duration: Double?
}
// MARK: - Downloads
struct Torrent: Codable, Identifiable, Hashable {
let id: Int
let name: String
let percentDone: Double
let status: Int
let rateDownload: Double
let rateUpload: Double
let eta: Double
let sizeWhenDone: Double
let haveValid: Double
var statusLabel: String {
switch status {
case 0: return "Stopped"
case 1, 2: return "Checking"
case 3, 5: return "Queued"
case 4: return "Downloading"
case 6: return "Seeding"
default: return ""
}
}
}
struct TorrentsResponse: Codable { let torrents: [Torrent] }
struct SearchResult: Codable, Identifiable, Hashable {
let filename: String
let source: String
let size: String
let seeders: Int
let leechers: Int
let magnet: String?
var id: String { (magnet ?? filename) + source }
}
struct SearchResponse: Codable { let results: [SearchResult] }