Die Plakate blieben weg, und der Grund stand nicht im Code, sondern daneben: eine App-Erweiterung hat ihre **eigene** Info.plist, und damit ihre eigene Transportsicherheit. Die Ausnahme fürs lokale Netz, die in der Info.plist der App seit jeher steht, gilt dort nicht. Ein Jellyfin im Heimnetz antwortet auf blankem HTTP. Jede Bildanfrage der Erweiterung lief damit gegen ATS — lautlos, ohne Fehler, ohne Eintrag. Das Regal blieb leer und sah aus wie „geht halt nicht". Dazu die richtige Plakatgrösse: 666×1000 statt 404×606, Apples Mass für die doppelte Auflösung. Für beide Stufen dasselbe Bild — ein Apple TV zeichnet das Regal ohnehin doppelt aufgelöst, und zwei Adressen abzulegen hiesse, dem Server zwei Grössen desselben Plakats abzuverlangen, damit eine davon nie gebraucht wird. Nicht nachgewiesen: dass es jetzt zeichnet. Das Regal erscheint nur, wenn die App in der **obersten** Reihe des Menüs steht und fokussiert ist, und den Fokus kann ich im Simulator nicht bewegen — tvOS nimmt keine Touch-Eingaben, und an die Simulator-App komme ich aus dieser Umgebung nicht heran. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
67 lines
2.6 KiB
Swift
67 lines
2.6 KiB
Swift
import Foundation
|
|
import MediaKit
|
|
|
|
/// Legt für das Regal über der App hin, was es zeigen soll.
|
|
///
|
|
/// **Beim Laden der Startseite, nicht auf einem Zeitgeber.** Das Regal wird
|
|
/// gezeichnet, wenn jemand im Menü über der App steht — und dann ist die App
|
|
/// nicht gestartet. Was dort steht, ist also immer das, was beim letzten
|
|
/// Öffnen zu sehen war. Ein Zeitgeber änderte daran nichts und hielte nur die
|
|
/// App wach.
|
|
@MainActor
|
|
enum TopShelfWriter {
|
|
/// Die App-Gruppe, die App und Erweiterung teilen.
|
|
static let group = "group.com.scarriffleservices.flixy"
|
|
|
|
/// Die Kante, in der das Regal Plakate zeigt.
|
|
///
|
|
/// **Apples Mass für die doppelte Auflösung**, und für beide Stufen
|
|
/// dasselbe Bild. Ein Apple TV zeichnet das Regal ohnehin doppelt
|
|
/// aufgelöst; zwei Adressen abzulegen hiesse, dem Server zwei Grössen
|
|
/// desselben Plakats abzuverlangen, damit eine davon nie gebraucht wird.
|
|
private static let posterWidth = 666
|
|
private static let posterHeight = 1000
|
|
|
|
static func update(
|
|
rows: [MediaRowGroup],
|
|
backend: (any MediaBackend)?
|
|
) {
|
|
guard let backend else { return }
|
|
|
|
let abschnitte = rows
|
|
.prefix(TopShelfSnapshot.sectionLimit)
|
|
.map { reihe in
|
|
TopShelfSnapshot.Section(
|
|
id: reihe.id,
|
|
title: reihe.title,
|
|
entries: reihe.items
|
|
.prefix(TopShelfSnapshot.entryLimit)
|
|
.map { item in
|
|
TopShelfSnapshot.Entry(
|
|
id: item.id,
|
|
title: item.rowTitle,
|
|
subtitle: item.cardSubtitle,
|
|
// **Das Hochkant-Plakat, nicht `thumb`.** Bei
|
|
// einer Folge ist `thumb` das Szenenbild; im
|
|
// Regal stünde davon ein zufälliger
|
|
// Ausschnitt. Dieselbe Rückfallkette wie auf
|
|
// den Kacheln.
|
|
imageURL: backend.artworkURL(
|
|
path: item.posterArtworkPath,
|
|
width: posterWidth,
|
|
height: posterHeight
|
|
),
|
|
progress: item.watchProgress
|
|
)
|
|
}
|
|
)
|
|
}
|
|
.filter { !$0.entries.isEmpty }
|
|
|
|
TopShelfStore.write(
|
|
TopShelfSnapshot(sections: Array(abschnitte)),
|
|
group: group
|
|
)
|
|
}
|
|
}
|