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 public init(url: URL?, aspectRatio: CGFloat, fallbackSymbol: String = "film") { self.url = url self.aspectRatio = aspectRatio self.fallbackSymbol = fallbackSymbol } 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): image.resizable().scaledToFill() 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() } }