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,5 +1,6 @@
|
||||
import Foundation
|
||||
import FlixyDownloads
|
||||
import MediaKit
|
||||
import PlexKit
|
||||
|
||||
/// Füllt den Vorrat an ungesehenen Folgen wieder auf.
|
||||
@@ -9,7 +10,7 @@ import PlexKit
|
||||
/// Server und ist deshalb prüfbar, das Auswählen braucht ihn zwangsläufig.
|
||||
@MainActor
|
||||
struct DownloadRefiller {
|
||||
let server: PlexServer?
|
||||
let backend: PlexBackend?
|
||||
let coordinator: DownloadCoordinator
|
||||
|
||||
/// Lädt nach, was den Regeln nach fehlt.
|
||||
@@ -19,26 +20,26 @@ struct DownloadRefiller {
|
||||
/// wäre eine unangenehme Überraschung auf der Mobilfunkrechnung.
|
||||
@discardableResult
|
||||
func refill() async -> Int {
|
||||
guard let server, coordinator.rules.keepUnwatchedEpisodes != nil else { return 0 }
|
||||
guard let backend, coordinator.rules.keepUnwatchedEpisodes != nil else { return 0 }
|
||||
|
||||
let needed = coordinator.rules.seriesNeedingRefill(in: coordinator.items)
|
||||
guard !needed.isEmpty else { return 0 }
|
||||
|
||||
var added = 0
|
||||
let service = DownloadService(server: server, coordinator: coordinator)
|
||||
let service = DownloadService(backend: backend, coordinator: coordinator)
|
||||
|
||||
for (seriesKey, count) in needed {
|
||||
let candidates = await nextUnwatchedEpisodes(
|
||||
inSeries: seriesKey,
|
||||
count: count,
|
||||
server: server
|
||||
backend: backend
|
||||
)
|
||||
|
||||
for episode in candidates {
|
||||
// Die Kinderliste bringt keine Dateiangaben mit — ohne sie
|
||||
// ließe sich weder das Speicherlimit prüfen noch ein
|
||||
// Fortschritt anzeigen.
|
||||
let detailed = (try? await server.metadata(ratingKey: episode.ratingKey)) ?? episode
|
||||
let detailed = (try? await backend.item(id: episode.id)) ?? episode
|
||||
// Folgen ohne abrufbare Datei still überspringen: das Nachladen
|
||||
// läuft im Hintergrund, da hilft keine Fehlermeldung.
|
||||
guard let plan = try? service.plan(for: detailed) else { continue }
|
||||
@@ -55,21 +56,21 @@ struct DownloadRefiller {
|
||||
private func nextUnwatchedEpisodes(
|
||||
inSeries seriesKey: String,
|
||||
count: Int,
|
||||
server: PlexServer
|
||||
) async -> [PlexItem] {
|
||||
guard let seasons = try? await server.children(of: seriesKey) else { return [] }
|
||||
backend: PlexBackend
|
||||
) async -> [MediaItem] {
|
||||
guard let seasons = try? await backend.children(of: seriesKey) else { return [] }
|
||||
|
||||
let offlineKeys = Set(coordinator.items.map(\.ratingKey))
|
||||
var result: [PlexItem] = []
|
||||
var result: [MediaItem] = []
|
||||
|
||||
for season in seasons.sorted(by: { ($0.index ?? 0) < ($1.index ?? 0) }) {
|
||||
// Specials führt Plex als Staffel 0. Sie gehören nicht in den
|
||||
// Vorrat für „was kommt als Nächstes".
|
||||
guard (season.index ?? 0) > 0 else { continue }
|
||||
guard let episodes = try? await server.children(of: season.ratingKey) else { continue }
|
||||
guard let episodes = try? await backend.children(of: season.id) else { continue }
|
||||
|
||||
for episode in episodes.sorted(by: { ($0.index ?? 0) < ($1.index ?? 0) }) {
|
||||
guard !episode.isWatched, !offlineKeys.contains(episode.ratingKey) else { continue }
|
||||
guard !episode.isWatched, !offlineKeys.contains(episode.id) else { continue }
|
||||
result.append(episode)
|
||||
if result.count >= count { return result }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user