Files
Flaro/Packages/FlixyKit/Sources/FlixyDesign/Components/FlixyArtwork.swift
T
ScarriffleandClaude Opus 5 c348ab0755 Kachel größer ziehen, Senderlogos vollständig, Sendung im Player
Drei Sachen aus dem Feldtest.

Der Griff zum Größerziehen war wirkungslos, und zwar durch meinen Fehler:
die Drehung lag auf dem ganzen Überzug statt auf dem Symbol. Bei zwei der
vier Ecken kippte damit die gesamte Trefferfläche weg, und man griff ins
Leere. Jetzt sitzt der Griff über `overlay(alignment:)`, nur der Pfeil
dreht sich, und das Ziehen hat Vorrang vor dem Verschieben der Kachel —
sonst gewinnt das Verschieben, das am selben Ort hängt.

Senderlogos sind Schriftzüge und fast nie quadratisch. Formatfüllend in
einem Quadrat fehlten links und rechts genau die Teile, an denen man den
Sender erkennt. Sie bekommen jetzt eine breitere Fläche und werden
eingepasst statt beschnitten — `FlixyArtwork` kann beides, und welches
gilt, entscheidet der Aufrufer.

Und im Player steht bei Live-TV, was gerade läuft. Der Name reist mit dem
Einschalten mit, denn nachzuschlagen ist er nicht — ein Sender hat keine
Metadaten in der Mediathek. Beim Aufdecken der Bedienelemente wird er
nachgeholt, aber nur, wenn die alte Sendung wirklich abgelaufen ist:
sonst stünde derselbe Name den ganzen Abend, und das wäre derselbe
Fehler, der eben erst im Programm behoben wurde.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 21:19:50 +02:00

61 lines
2.4 KiB
Swift

import SwiftUI
/// Ein Bild vom Server mit Lade- und Fehlerzustand.
///
/// Kapselt `AsyncImage`, damit der Austausch gegen einen eigenen, zwischen-
/// speichernden Lader später genau eine Datei betrifft. Die Startseite zeigt
/// dutzende Bilder gleichzeitig; ohne Zwischenspeicher lädt `AsyncImage` sie
/// bei jedem Erscheinen neu.
public struct FlixyArtwork: View {
private let url: URL?
private let aspectRatio: CGFloat
private let fallbackSymbol: String
private let contentMode: ContentMode
/// - Parameter contentMode: `.fill` füllt die Fläche und schneidet ab —
/// richtig für Plakate und Szenenbilder, die ohnehin formatfüllend
/// gedacht sind. `.fit` zeigt das ganze Bild. Das braucht alles, was
/// kein festes Seitenverhältnis hat: **Sendersymbole** sind mal breit,
/// mal schmal, und formatfüllend in einem Quadrat fehlten links und
/// rechts genau die Teile, an denen man den Sender erkennt.
public init(
url: URL?,
aspectRatio: CGFloat,
fallbackSymbol: String = "film",
contentMode: ContentMode = .fill
) {
self.url = url
self.aspectRatio = aspectRatio
self.fallbackSymbol = fallbackSymbol
self.contentMode = contentMode
}
public var body: some View {
Rectangle()
.fill(Color.flixyPlaceholder)
.aspectRatio(aspectRatio, contentMode: .fit)
.overlay {
AsyncImage(url: url, transaction: Transaction(animation: .easeOut(duration: 0.2))) { phase in
switch phase {
case .success(let image):
switch contentMode {
case .fill: image.resizable().scaledToFill()
case .fit: image.resizable().scaledToFit()
}
case .failure:
// Kein Fehlertext: bei einer Reihe aus zwanzig Kacheln
// wäre das mehr Lärm als Hilfe. Das Symbol sagt genug.
Image(systemName: fallbackSymbol)
.font(.title2)
.foregroundStyle(Color.flixyTextMuted)
case .empty:
ShimmerPlaceholder()
@unknown default:
ShimmerPlaceholder()
}
}
}
.clipped()
}
}