Die Ansichten sprechen nicht mehr mit Plex
Start, Suche, Mediathek, Detailseiten und Downloads arbeiten jetzt mit `MediaItem` und dem `MediaBackend`-Vertrag. Damit sind sie fertig für einen zweiten Server, ohne dass an ihnen noch etwas zu tun wäre. Dabei sind ein paar Namen ehrlicher geworden: aus `grandparentTitle` wurde `seriesTitle`, aus `viewedLeafCount` `playedEpisodeCount`. Und `TagStrip` nahm bisher Plex-Marken mit Kennung und Rolle entgegen, um davon nur den Namen anzuzeigen — Genres sind jetzt schlicht Zeichenketten. `Arrangement` ist aus PlexKit heraus und generisch: dieselbe Rechnung gilt für jede Liste, die jemand selbst zusammenstellt. Phase 3 baut die konfigurierbare Seitenleiste darauf, statt sie ein zweites Mal — und ein zweites Mal falsch — zu schreiben. Die Fehlerübersetzung gibt es nur noch einmal. Es waren zwei, und sie waren bereits auseinandergelaufen: derselbe Fehler bekam je nach Bildschirm eine andere Erklärung. Das Nachladen der Mediathek bleibt unangetastet: eine lange Liste, die fünf Einträge vor dem Ende nachlädt. `MediaPage` heißt zwar Seite, ist aber eine technische Portion — Blättern mit „weiter zu Seite 2" gehört nicht in eine Mediathek, in der man stöbert. Der Kommentar dort sagt das jetzt ausdrücklich, damit es niemand später „aufräumt". Player, Live-TV und die Download-Engine sprechen noch unmittelbar mit Plex. Sie folgen als Nächstes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
effdcd4532
commit
fe2d730c00
@@ -1,12 +1,12 @@
|
||||
import SwiftUI
|
||||
import FlixyDesign
|
||||
import PlexKit
|
||||
import MediaKit
|
||||
|
||||
/// Die Startseite: Aufmacher oben, darunter die Reihen vom Server.
|
||||
struct HomeView: View {
|
||||
@Environment(FlixySession.self) private var session
|
||||
@Environment(HomeLayoutSettings.self) private var layout
|
||||
@State private var state: LoadState<[PlexHub]> = .loading
|
||||
@State private var state: LoadState<[MediaRowGroup]> = .loading
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
@@ -23,8 +23,8 @@ struct HomeView: View {
|
||||
Button("action.retry") { Task { await load() } }
|
||||
}
|
||||
|
||||
case .loaded(let allHubs):
|
||||
let hubs = layout.apply(to: allHubs)
|
||||
case .loaded(let allRows):
|
||||
let hubs = layout.apply(to: allRows)
|
||||
if hubs.isEmpty {
|
||||
ContentUnavailableView {
|
||||
Label("home.empty.title", systemImage: "film.stack")
|
||||
@@ -55,7 +55,7 @@ struct HomeView: View {
|
||||
.refreshable { await load() }
|
||||
}
|
||||
|
||||
private func content(hubs: [PlexHub]) -> some View {
|
||||
private func content(hubs: [MediaRowGroup]) -> some View {
|
||||
ScrollView {
|
||||
LazyVStack(alignment: .leading, spacing: FlixySpacing.section) {
|
||||
if let featured = heroItem(in: hubs) {
|
||||
@@ -63,7 +63,7 @@ struct HomeView: View {
|
||||
}
|
||||
|
||||
ForEach(hubs) { hub in
|
||||
MediaRow(hub: hub)
|
||||
MediaRow(row: hub)
|
||||
}
|
||||
}
|
||||
.padding(.bottom, FlixySpacing.section)
|
||||
@@ -76,15 +76,15 @@ struct HomeView: View {
|
||||
/// Erste Wahl ist etwas Angefangenes — wer die App öffnet, will meistens
|
||||
/// weiterschauen. Erst wenn es nichts Angefangenes gibt, tritt der
|
||||
/// Neuzugang an die Stelle.
|
||||
private func heroItem(in hubs: [PlexHub]) -> PlexItem? {
|
||||
let continuing = hubs.first { $0.hubIdentifier.contains("continue") }
|
||||
private func heroItem(in hubs: [MediaRowGroup]) -> MediaItem? {
|
||||
let continuing = hubs.first(where: \.isContinueWatching)
|
||||
return continuing?.items.first ?? hubs.first?.items.first
|
||||
}
|
||||
|
||||
private func load() async {
|
||||
guard let server = session.server else { return }
|
||||
guard let backend = session.backend else { return }
|
||||
state = await LoadState.load(keepingPrevious: state) {
|
||||
try await server.homeHubs()
|
||||
try await backend.homeRows()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user