MediaKit: die neutralen Datensätze und die Übersetzung aus Plex
`MediaItem` und die Typen darunter — die Form, in der die Oberfläche Titel sieht, unabhängig davon, welcher Server sie geliefert hat. Die Namen sind dort geblieben, wo sie ohnehin neutral waren: `title`, `summary`, `year`, `index`. Umbenannt wurde, was Plex-Jargon ist. `ratingKey` heißt `id`, `viewOffset` heißt `resumeMilliseconds`, und aus dem „Großelternteil" ist die Serie geworden, die von Anfang an gemeint war — ein Name, den man in jeder Ansicht im Kopf übersetzen musste. Zwei Dinge, die dabei ehrlicher werden: `isFavourite` gibt es, aber Plex meldet immer `false`. Ein Feld, das ein Server nicht füllt, ist besser als eine Fähigkeit, die es nur auf einem gibt und die sich nirgends setzen ließe. Dateigrößen sind jetzt `Int64`. Ein Remux überschreitet vier Gigabyte mühelos. Die Übersetzung steht in **einer** Datei und geht in **eine** Richtung. Die Drahtmodelle bleiben, wo sie sind — sie tragen Eigenheiten, die nur Plex hat, und die gehören nicht nach oben. Geprüft wird gegen echte Server-Antworten, nicht gegen erfundene Werte: genau dort stehen die Eigenheiten, an denen eine Übersetzung scheitert. Ein Test vergleicht außerdem beide Wege zum Wiedergabe-Profil — sagten sie Unterschiedliches, spielte ein Titel nach dem Umbau plötzlich über einen anderen Player. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
5b2b86b66b
commit
ba6be4ac79
@@ -0,0 +1,65 @@
|
||||
import Foundation
|
||||
|
||||
/// Eine Mediathek auf dem Server.
|
||||
public struct MediaLibrary: Sendable, Equatable, Identifiable {
|
||||
public enum Kind: String, Sendable, Equatable {
|
||||
case movie, show, music, photo, liveTV, other
|
||||
}
|
||||
|
||||
public let id: String
|
||||
public let title: String
|
||||
public let kind: Kind
|
||||
public let thumb: String?
|
||||
public let art: String?
|
||||
|
||||
public init(
|
||||
id: String,
|
||||
title: String,
|
||||
kind: Kind,
|
||||
thumb: String? = nil,
|
||||
art: String? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.kind = kind
|
||||
self.thumb = thumb
|
||||
self.art = art
|
||||
}
|
||||
|
||||
/// Ob die App mit dieser Mediathek etwas anfangen kann.
|
||||
///
|
||||
/// Musik und Fotos sind bewusst außen vor: sie bräuchten eigene Ansichten
|
||||
/// und eigene Wiedergabe, und eine halbherzige Musikansicht ist schlechter
|
||||
/// als gar keine.
|
||||
public var isSupported: Bool { kind == .movie || kind == .show }
|
||||
}
|
||||
|
||||
/// Eine Reihe auf der Startseite oder in den Suchergebnissen.
|
||||
public struct MediaRowGroup: Sendable, Equatable, Identifiable {
|
||||
/// Eine stabile Kennung für diese Reihe.
|
||||
///
|
||||
/// Sie entscheidet, welche Reihe der Nutzer ausgeblendet oder verschoben
|
||||
/// hat — und muss deshalb über Abrufe hinweg gleich bleiben, auch wenn
|
||||
/// sich der angezeigte Titel ändert.
|
||||
public let id: String
|
||||
public let title: String
|
||||
/// Der Pfad, unter dem es „alles davon" gäbe.
|
||||
public let moreKey: String?
|
||||
public let items: [MediaItem]
|
||||
|
||||
public init(id: String, title: String, moreKey: String? = nil, items: [MediaItem] = []) {
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.moreKey = moreKey
|
||||
self.items = items
|
||||
}
|
||||
|
||||
/// Ob diese Reihe das Weiterschauen ist.
|
||||
///
|
||||
/// Sie wird anders dargestellt: dort zeigt das Szenenbild, wo man
|
||||
/// aufgehört hat, während man sonst nach Plakaten sucht.
|
||||
public var isContinueWatching: Bool {
|
||||
let lowered = id.lowercased()
|
||||
return lowered.contains("continue") || lowered.contains("resume") || lowered.contains("nextup")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user