Der Schriftzug gehört zum Aufmacher, nicht zu sich selbst
`AsyncImage` bringt seine eigene Einblendung mit und fängt erst an zu laden, wenn es erscheint. Beim Überblenden des Aufmachers blendete sich der Schriftzug des Films deshalb getrennt und später ein, während Titelzeile, Beschreibung und Knöpfe längst mitgewandert waren — zwei Bewegungen, wo eine sein soll. Jetzt lädt er über denselben Zwischenspeicher wie alle anderen Bilder, und das Karussell holt ihn zusammen mit dem Hintergrundbild vor. Beim Erscheinen liegt er bereit und macht mit, was der Aufmacher macht. Dazu ein kleines Hilfsprogramm, das die Fensterkennung eines laufenden Programms ausgibt, damit `screencapture -l` genau dessen Fenster fotografiert und sonst nichts vom Bildschirm. Das System-Python bringt PyObjC nicht mehr mit, und ohne Kennung gibt es keinen Weg dorthin. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7155f50bac
commit
e5e01838f7
@@ -17,6 +17,8 @@ public struct HeroBanner<Actions: View>: View {
|
||||
private let aspectRatio: CGFloat
|
||||
private let actions: Actions
|
||||
|
||||
@State private var logo: PlatformImage?
|
||||
|
||||
public init(
|
||||
title: String,
|
||||
metadata: String? = nil,
|
||||
@@ -53,32 +55,45 @@ public struct HeroBanner<Actions: View>: View {
|
||||
|
||||
/// Schriftzug, wenn vorhanden — sonst gesetzter Titel.
|
||||
///
|
||||
/// Der Schriftzug wird ohne Bild-Transcoder geladen; er ist ein
|
||||
/// freigestelltes PNG, und der Transcoder liefert JPEG. Aus dem
|
||||
/// freigestellten Logo würde sonst ein schwarzer Kasten.
|
||||
/// Geladen wird über `ArtworkLoader`, **nicht** über `AsyncImage`. Der
|
||||
/// Unterschied ist beim Überblenden des Aufmachers zu sehen: `AsyncImage`
|
||||
/// bringt seine eigene Einblendung mit und fängt erst an zu laden, wenn es
|
||||
/// erscheint. Der Schriftzug blendete sich dann getrennt und später ein,
|
||||
/// während Titelzeile, Beschreibung und Knöpfe längst mitgewandert waren —
|
||||
/// zwei Bewegungen, wo eine sein soll.
|
||||
///
|
||||
/// Jetzt liegt das Bild beim Erscheinen schon im Zwischenspeicher (das
|
||||
/// Karussell holt es vor) und wird ohne eigene Bewegung gezeigt: es gehört
|
||||
/// zum Aufmacher und macht mit, was der Aufmacher macht.
|
||||
///
|
||||
/// Ohne Bild-Transcoder, weil der Schriftzug ein freigestelltes PNG ist und
|
||||
/// der Transcoder JPEG liefert — aus dem Logo würde sonst ein schwarzer
|
||||
/// Kasten.
|
||||
@ViewBuilder
|
||||
private func titleView(scale: CGFloat) -> some View {
|
||||
if let logoURL {
|
||||
AsyncImage(url: logoURL) { phase in
|
||||
switch phase {
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
// Nach oben begrenzt: manche Schriftzüge sind fast
|
||||
// quadratisch, andere sehr breit. Ohne Deckel schöbe
|
||||
// ein hohes Logo die Knöpfe aus dem Bild.
|
||||
.frame(maxWidth: 260 * scale, maxHeight: 76 * scale, alignment: .leading)
|
||||
default:
|
||||
// Solange geladen wird — und wenn es scheitert — bleibt es
|
||||
// beim gesetzten Titel. Ein leerer Platz wäre schlimmer
|
||||
// als eine Systemschrift.
|
||||
plainTitle(scale: scale)
|
||||
}
|
||||
Group {
|
||||
if let logo {
|
||||
Image(platform: logo)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
// Nach oben begrenzt: manche Schriftzüge sind fast
|
||||
// quadratisch, andere sehr breit. Ohne Deckel schöbe ein
|
||||
// hohes Logo die Knöpfe aus dem Bild.
|
||||
.frame(maxWidth: 260 * scale, maxHeight: 76 * scale, alignment: .leading)
|
||||
.accessibilityLabel(Text(title))
|
||||
} else {
|
||||
// Solange nichts da ist — und wenn es scheitert — bleibt es
|
||||
// beim gesetzten Titel. Ein leerer Platz wäre schlimmer als
|
||||
// eine Systemschrift.
|
||||
plainTitle(scale: scale)
|
||||
}
|
||||
.accessibilityLabel(Text(title))
|
||||
} else {
|
||||
plainTitle(scale: scale)
|
||||
}
|
||||
.task(id: logoURL) {
|
||||
guard let logoURL else {
|
||||
logo = nil
|
||||
return
|
||||
}
|
||||
logo = await ArtworkLoader.shared.image(for: logoURL)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user