import SwiftUI /// Eine Kachel, die es gleich geben wird. /// /// **Warum es das gibt.** Eine Mediathek lädt seitenweise nach. Wer unten /// ankommt, sieht ein Raster, das aufhört — und kann nicht unterscheiden, ob /// das alles war oder ob gerade nachgeladen wird. Beides sieht gleich aus, und /// im Zweifel hält man eine halb geladene Liste für vollständig. /// /// Diese Kacheln sagen: hier kommt noch etwas. Sie werden nur so oft gezeigt, /// wie der Server tatsächlich noch Titel gemeldet hat — es ist also keine /// Beschwichtigung, sondern eine Auskunft. /// /// Ein Ladekreis täte das nicht: er sagt „es passiert etwas", aber nicht /// **wo** und nicht **wie viel**. Die Form der Kachel an der Stelle, an der /// sie erscheinen wird, sagt beides. public struct PlaceholderCard: View { /// Womit das Aufleuchten versetzt wird. /// /// Alle gleichzeitig pulsieren zu lassen sieht nach einem Fehler aus — /// als blinkte die ganze Seite. Ein Versatz je Kachel macht daraus eine /// Bewegung, die von links nach rechts läuft. let index: Int @State private var isBright = false @Environment(\.accessibilityReduceMotion) private var reduceMotion public init(index: Int = 0) { self.index = index } public var body: some View { VStack(alignment: .leading, spacing: FlixySpacing.snug) { RoundedRectangle(cornerRadius: FlixyRadius.card) .fill(Color.flixyElevated) .aspectRatio(PosterCard.aspectRatio, contentMode: .fit) // Zwei Balken an der Stelle von Titel und Jahr. Ohne sie springt // die Zeile, sobald der echte Titel kommt. RoundedRectangle(cornerRadius: 3) .fill(Color.flixyElevated) .frame(height: 10) RoundedRectangle(cornerRadius: 3) .fill(Color.flixyElevated) .frame(width: 32, height: 8) } .opacity(isBright ? 0.85 : 0.45) .animation( reduceMotion ? nil : .easeInOut(duration: 0.9) .repeatForever(autoreverses: true) .delay(Double(index % 6) * 0.1), value: isBright ) .onAppear { isBright = true } // Für die Sprachausgabe ist eine Kachel ohne Inhalt nichts, worüber // man wischen möchte. .accessibilityHidden(true) } }