Drei Sachen am Karussell. Die Vorschlaege wechselten bei jedem Start, obwohl es dafuer laengst ein Zeitfenster von sechs Stunden gab. Der Grund: das Los hing an der Position in der Liste, nicht am Titel. Kam einer dazu, verschwand einer, oder aenderte sich ein Fortschritt, bekamen alle dahinter ein anderes Los — und „Weiterschauen\" waechst und schrumpft staendig. Jetzt haengt das Los an der Kennung; wer dazukommt, stoert niemanden. Als eigener Typ mit elf Tests, weil „es wechselt zu oft\" kein Befund ist, den man debuggen kann. Folgen zeigten kein Bild. Die Kette Folge → Serie gab es zwar, aber sie hoerte beim ersten Glied auf, das sich **zusammensetzen** liess — und ob es das Bild dahinter gibt, stellt sich erst beim Abruf heraus. Die Reihenfolge wandert deshalb ins Laden: Folge, Staffel, Serie, der Reihe nach, bis eine Adresse antwortet. Und auf dem Mac gibt es jetzt Pfeile links und rechts, sobald der Zeiger ueber dem Aufmacher liegt, sowie Punkte, die unter dem Zeiger wachsen und auf die man springen kann. Nur dort: auf dem iPad und dem iPhone wischt man ohnehin, und zwei Knoepfe staenden nur im Bild. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
82 lines
3.7 KiB
Swift
82 lines
3.7 KiB
Swift
import Foundation
|
||
import FlixyDesign
|
||
import MediaKit
|
||
|
||
/// Woher der Aufmacher seine Bilder nimmt.
|
||
///
|
||
/// An **einer** Stelle, weil zwei Stellen es schon zweimal falsch gemacht
|
||
/// haben:
|
||
///
|
||
/// Erstens wurde das Hintergrundbild in 900×1200 angefordert — hochkant — und
|
||
/// dann in einem 16:9-Rahmen gezeigt. Zu sehen war davon ein schmaler Streifen
|
||
/// aus der Mitte; vom Bild fehlte oben und unten je ein Drittel. Die Maße
|
||
/// richten sich jetzt nach dem Rahmen, in dem das Bild landet.
|
||
///
|
||
/// Zweitens holt das Karussell das nächste Bild vor, solange das aktuelle noch
|
||
/// steht. Weicht dessen Adresse auch nur in einer Zahl ab, ist es eine andere
|
||
/// Adresse, der Zwischenspeicher trifft daneben und der Aufmacher blendet auf
|
||
/// eine graue Fläche über.
|
||
enum HeroArtwork {
|
||
/// Die Maße, in denen das Bild angefordert wird.
|
||
///
|
||
/// Im Seitenverhältnis des Rahmens, in dem es landet — sonst schneidet der
|
||
/// Server zu, und man sieht einen Streifen aus der Mitte.
|
||
static func size(compact: Bool) -> (width: Int, height: Int) {
|
||
compact ? (600, 900) : (1920, 1080)
|
||
}
|
||
|
||
static func aspectRatio(compact: Bool) -> CGFloat {
|
||
compact ? FlixyAspectRatio.poster : FlixyAspectRatio.hero
|
||
}
|
||
|
||
/// Auf einem schmalen Bildschirm das **Plakat**, sonst das Hintergrundbild.
|
||
///
|
||
/// Ein Hintergrundbild ist 16:9. Hochkant gezeigt fehlen ihm links und
|
||
/// rechts je ein Viertel, und zu sehen ist ein Ausschnitt aus der Mitte —
|
||
/// vom Bild bleibt wenig übrig. Ein Plakat ist von vornherein hochkant;
|
||
/// es passt in den Rahmen, ohne dass etwas weggeschnitten werden muss.
|
||
static func backdropURL(for item: MediaItem, backend: any MediaBackend, compact: Bool) -> URL? {
|
||
backdropURLs(for: item, backend: backend, compact: compact).first
|
||
}
|
||
|
||
/// Alle Kandidaten, vom besten zum schlechtesten.
|
||
///
|
||
/// **Warum mehrere und nicht einer.** Eine Folge hat selten ein eigenes
|
||
/// Querformatbild, die Staffel manchmal, die Serie fast immer. Bisher
|
||
/// wurde die erste Adresse genommen, die sich **zusammensetzen** liess —
|
||
/// und ob es das Bild dahinter gibt, stellt sich erst beim Abruf heraus.
|
||
/// Gab es keines, blieb die Fläche grau, obwohl eine Ebene höher eines
|
||
/// gelegen hätte. Genau so sahen Folgen im Aufmacher aus.
|
||
///
|
||
/// Die Reihenfolge steht hier, ausprobiert wird sie beim Laden.
|
||
static func backdropURLs(
|
||
for item: MediaItem,
|
||
backend: any MediaBackend,
|
||
compact: Bool
|
||
) -> [URL] {
|
||
let size = size(compact: compact)
|
||
let pfade: [String?] = compact
|
||
// Hochkant: das Plakat der Folge, dann das der Staffel, dann das
|
||
// der Serie. Ein Hintergrundbild kommt hier zuletzt — es ist
|
||
// quer und verliert hochkant die Hälfte.
|
||
? [item.posterArtworkPath, item.thumb, item.parentThumb, item.seriesThumb, item.art]
|
||
// Quer: das eigene Hintergrundbild, dann das der Staffel, dann
|
||
// das der Serie — und erst danach das Vorschaubild der Folge.
|
||
: [item.art, item.parentThumb, item.seriesArt, item.seriesThumb, item.thumb]
|
||
|
||
var gesehen = Set<String>()
|
||
return pfade
|
||
.compactMap(\.self)
|
||
.filter { gesehen.insert($0).inserted }
|
||
.compactMap { backend.artworkURL(path: $0, width: size.width, height: size.height) }
|
||
}
|
||
|
||
/// Der freigestellte Schriftzug — ohne Bild-Transcoder.
|
||
///
|
||
/// Er ist ein PNG mit durchsichtigem Grund, und der Transcoder liefert
|
||
/// JPEG. Aus dem Schriftzug würde sonst ein schwarzer Kasten.
|
||
static func logoURL(for item: MediaItem, backend: any MediaBackend) -> URL? {
|
||
backend.rawImageURL(path: item.clearLogoPath)
|
||
}
|
||
}
|