Die Oberfläche weiß nicht mehr, dass es Plex gibt
Keine Datei unter Views/LiveTV importiert noch PlexKit. Sender, Programm und Einschalten laufen über den neutralen Vertrag, und supportsLiveTV fragt endlich die Fähigkeit ab statt "server != nil" — womit die Zusage in JellyfinBackend.capabilities zum ersten Mal stimmt. Der Player holt die laufende Sendung jetzt für genau einen Sender nach. Vorher ging dafür das Raster über alle Sender hinaus, weil der Plex-Weg keinen schmaleren kannte; im neutralen Vertrag ist die Senderliste ein Parameter. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
24765a5afc
commit
eebe9280cb
@@ -1,7 +1,7 @@
|
||||
import SwiftUI
|
||||
import FlixyDesign
|
||||
import FlixyPlayback
|
||||
import PlexKit
|
||||
import MediaKit
|
||||
|
||||
/// Live-TV mit Programmführer.
|
||||
struct LiveTVView: View {
|
||||
@@ -11,14 +11,12 @@ struct LiveTVView: View {
|
||||
@Environment(NetworkConditions.self) private var network
|
||||
|
||||
@State private var availability: LiveTVAvailability?
|
||||
/// Der Empfänger, über den eingeschaltet wird.
|
||||
@State private var dvr: PlexDVR?
|
||||
@State private var channels: [PlexChannel] = []
|
||||
@State private var channels: [LiveChannel] = []
|
||||
/// Woher die Senderliste kam — steht in der leeren Ansicht.
|
||||
@State private var channelSource: String?
|
||||
/// Jede abgeklopfte Adresse mit ihrer Antwort.
|
||||
@State private var trace: [ChannelProbe] = []
|
||||
@State private var programs: [String: [PlexProgram]] = [:]
|
||||
@State private var trace: [LiveChannelProbe] = []
|
||||
@State private var programs: [String: [LiveProgram]] = [:]
|
||||
@State private var isTuning: String?
|
||||
/// Warum das Einschalten nicht geklappt hat — mit jedem versuchten Weg.
|
||||
@State private var tuneFailure: TuneFailure?
|
||||
@@ -34,7 +32,7 @@ struct LiveTVView: View {
|
||||
|
||||
/// Die Sender nach der Auswahl — überall dieselbe Liste, damit Raster und
|
||||
/// Liste nicht auseinanderlaufen.
|
||||
private var shownChannels: [PlexChannel] {
|
||||
private var shownChannels: [LiveChannel] {
|
||||
ChannelSelection.apply(ChannelSelection.decode(storedSelection), to: channels)
|
||||
}
|
||||
|
||||
@@ -85,7 +83,7 @@ struct LiveTVView: View {
|
||||
programs: programs,
|
||||
tuning: isTuning,
|
||||
artwork: { channel in
|
||||
session.server?.artworkURL(path: channel.thumb, width: 120, height: 120)
|
||||
session.backend?.artworkURL(path: channel.artworkPath, width: 120, height: 120)
|
||||
},
|
||||
onTune: { channel, program in Task { await tune(channel, program: program) } }
|
||||
)
|
||||
@@ -200,13 +198,12 @@ struct LiveTVView: View {
|
||||
}
|
||||
|
||||
private func load() async {
|
||||
guard let server = session.server else { return }
|
||||
guard let liveTV = session.liveTV else { return }
|
||||
|
||||
let availability = await server.liveTVAvailability()
|
||||
let availability = await liveTV.liveTVAvailability()
|
||||
self.availability = availability
|
||||
|
||||
guard case .available(let dvrs) = availability, let dvr = dvrs.first else { return }
|
||||
self.dvr = dvr
|
||||
guard case .available = availability else { return }
|
||||
|
||||
// Sender und Programm kommen zusammen: die Senderliste des Anbieters
|
||||
// antwortet auf manchen Servern gar nicht, und dann tragen die
|
||||
@@ -216,15 +213,21 @@ struct LiveTVView: View {
|
||||
// Sechs Stunden: ein ganzer Fernsehabend. Mehr wäre bei einer Liste
|
||||
// mit fünfhundert Sendern eine Antwort im zweistelligen Megabereich,
|
||||
// und über Mobilfunk wartet man darauf.
|
||||
let guide = await server.liveTVGuide(dvr: dvr, hours: 6)
|
||||
channels = guide.channels
|
||||
programs = guide.programs
|
||||
channelSource = guide.source
|
||||
trace = guide.trace
|
||||
let listing = await liveTV.liveChannels()
|
||||
channels = listing.channels
|
||||
channelSource = listing.source
|
||||
trace = listing.probes
|
||||
|
||||
let now = Date()
|
||||
programs = (try? await liveTV.livePrograms(
|
||||
channelIDs: listing.channels.map(\.id),
|
||||
from: now.addingTimeInterval(-3_600),
|
||||
to: now.addingTimeInterval(6 * 3_600)
|
||||
)) ?? [:]
|
||||
}
|
||||
|
||||
private func tune(_ channel: PlexChannel, program: PlexProgram? = nil) async {
|
||||
guard let server = session.server, isTuning == nil else { return }
|
||||
private func tune(_ channel: LiveChannel, program: LiveProgram? = nil) async {
|
||||
guard let liveTV = session.liveTV, isTuning == nil else { return }
|
||||
isTuning = channel.id
|
||||
defer { isTuning = nil }
|
||||
|
||||
@@ -233,12 +236,9 @@ struct LiveTVView: View {
|
||||
let running = program ?? programs[channel.id]?.first { $0.isRunning() }
|
||||
let policy = settings.policy(for: network)
|
||||
|
||||
let result = await server.tune(
|
||||
let result = await liveTV.tune(
|
||||
channel: channel,
|
||||
program: running,
|
||||
// Der Programmanbieter kennt keinen Weg zum Einschalten — der
|
||||
// Empfänger schon, und ohne ihn bleibt der halbe Suchraum zu.
|
||||
dvr: dvr,
|
||||
maximumBitrate: policy.maximumBitrate
|
||||
)
|
||||
|
||||
@@ -268,16 +268,16 @@ struct LiveTVView: View {
|
||||
|
||||
/// Eine Senderzeile mit dem, was gerade und als Nächstes läuft.
|
||||
private struct ChannelRow: View {
|
||||
let channel: PlexChannel
|
||||
let programs: [PlexProgram]
|
||||
let channel: LiveChannel
|
||||
let programs: [LiveProgram]
|
||||
let isTuning: Bool
|
||||
let onTune: () -> Void
|
||||
|
||||
@Environment(FlixySession.self) private var session
|
||||
@Environment(\.flixyAccent) private var accent
|
||||
|
||||
private var current: PlexProgram? { programs.first { $0.isRunning() } }
|
||||
private var next: PlexProgram? { programs.first { $0.startsAt > Date() } }
|
||||
private var current: LiveProgram? { programs.first { $0.isRunning() } }
|
||||
private var next: LiveProgram? { programs.first { $0.startsAt > Date() } }
|
||||
|
||||
var body: some View {
|
||||
Button(action: onTune) {
|
||||
@@ -286,7 +286,7 @@ private struct ChannelRow: View {
|
||||
// fast nie quadratisch, und formatfüllend fehlten links und
|
||||
// rechts genau die Teile, an denen man den Sender erkennt.
|
||||
FlixyArtwork(
|
||||
url: session.server?.artworkURL(path: channel.thumb, width: 200, height: 120),
|
||||
url: session.backend?.artworkURL(path: channel.artworkPath, width: 200, height: 120),
|
||||
aspectRatio: FlixyAspectRatio.channelLogo,
|
||||
fallbackSymbol: "tv",
|
||||
contentMode: .fit
|
||||
@@ -295,7 +295,7 @@ private struct ChannelRow: View {
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
HStack(spacing: FlixySpacing.snug) {
|
||||
if let number = channel.channelIdentifier {
|
||||
if let number = channel.number {
|
||||
Text(number)
|
||||
.font(.system(.caption, design: .monospaced))
|
||||
.foregroundStyle(Color.flixyTextMuted)
|
||||
|
||||
Reference in New Issue
Block a user