Player: die Sprungflächen lagen über allen Knöpfen

Ein Überzug liegt in SwiftUI zwangsläufig obenauf. Ich hatte die
Doppeltipp-Flächen als `.overlay` über den ganzen Player gelegt, also
eine durchsichtige Fläche vor jeden Knopf — Pause, Scrubber, Qualität,
Kopfzeile, alles wirkungslos. Im Stapel entscheidet dagegen die
Reihenfolge, und dort liegen sie jetzt: über dem Bild, unter den
Bedienelementen.

Dazu kleiner. Volle Bildschirmhälften decken die Mitte ab, wo der
Pause-Knopf sitzt, und den oberen Rand mit der Kopfzeile — beim Zielen
auf einen Knopf träfe man zuerst die Fläche. Jetzt sind es zwei Streifen
von je dreißig Prozent Breite in der mittleren Höhe, mit Abstand zu oben
und unten.

Tippen außerhalb zeigt und verbirgt die Bedienelemente wie zuvor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-09-12 21:56:18 +02:00
co-authored by Claude Opus 5
parent 12bb49615b
commit b53fce65b8
2 changed files with 2791 additions and 2759 deletions
File diff suppressed because it is too large Load Diff
+37 -12
View File
@@ -43,6 +43,14 @@ struct PlayerView: View {
.ignoresSafeArea()
}
// **Unter** den Bedienelementen, nicht darüber. Als Überzug
// über dem ganzen Player lag hier eine durchsichtige Fläche
// vor jedem Knopf und hat sämtliche Tipper verschluckt —
// Pause, Scrubber, Qualität, alles tot. Ein Überzug liegt in
// SwiftUI zwangsläufig obenauf; hier im Stapel entscheidet
// die Reihenfolge, und alles Spätere liegt darüber.
seekZones
switch model.phase {
case .preparing:
preparing(for: model)
@@ -90,15 +98,9 @@ struct PlayerView: View {
.persistentSystemOverlays(showsControls ? .automatic : .hidden)
.landscapeWhileVisible()
.contentShape(.rect)
// Zwei Hälften: links zurück, rechts vor. Ein einzelnes Tippen zeigt
// weiterhin die Bedienelemente — die Reihenfolge entscheidet, sonst
// verschluckt das einfache Tippen das doppelte.
.overlay {
HStack(spacing: 0) {
seekZone(seconds: -10, symbol: "gobackward.10")
seekZone(seconds: 10, symbol: "goforward.10")
}
}
// Für alles außerhalb der Sprungflächen: Tippen zeigt und verbirgt
// die Bedienelemente wie bisher.
.onTapGesture { toggleControls() }
.sheet(isPresented: $showsTrackPicker) {
TrackPickerSheet(model: model)
}
@@ -370,10 +372,33 @@ struct PlayerView: View {
.padding(FlixySpacing.section)
}
/// Eine Bildschirmhälfte zum Springen.
/// Die beiden Flächen zum Springen.
///
/// Bewusst ohne sichtbare Trennung: die Fläche soll sich nicht aufdrängen.
/// Der kurze Hinweis beim Doppeltippen sagt genug.
/// Bewusst nicht die ganzen Bildschirmhälften: in der Mitte sitzt der
/// Pause-Knopf, oben die Kopfzeile, unten der Scrubber. Deckten die
/// Flächen alles ab, träfe man beim Zielen auf einen Knopf zuerst die
/// Fläche — und der Knopf bliebe wirkungslos.
private var seekZones: some View {
GeometryReader { geometry in
let width = geometry.size.width * 0.3
let height = geometry.size.height * 0.45
HStack(spacing: 0) {
seekZone(seconds: -10, symbol: "gobackward.10").frame(width: width)
Spacer(minLength: 0)
seekZone(seconds: 10, symbol: "goforward.10").frame(width: width)
}
.frame(height: height)
// Etwas unterhalb der Mitte: oben bleibt die Kopfzeile frei,
// unten der Scrubber.
.position(x: geometry.size.width / 2, y: geometry.size.height * 0.5)
}
}
/// Eine Fläche zum Springen.
///
/// Ohne sichtbare Begrenzung: die Fläche soll sich nicht aufdrängen. Der
/// kurze Hinweis beim Doppeltippen sagt genug.
private func seekZone(seconds: Double, symbol: String) -> some View {
Color.clear
.contentShape(.rect)