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>
This commit is contained in:
Scarriffle
2026-09-12 21:19:50 +02:00
co-authored by Claude Opus 5
parent af45bebceb
commit c348ab0755
9 changed files with 2804 additions and 2705 deletions
+33 -18
View File
@@ -162,34 +162,49 @@ struct MiniPlayer: View {
/// erreichbar, egal in welcher Ecke die Kachel klebt. Am äußeren Rand
/// läge er halb außerhalb des Daumens.
private func resizeHandle(corner: MiniPlayerPlacement.Corner) -> some View {
VStack {
if corner.isTop { Spacer() }
HStack {
if corner.isLeading { Spacer() }
Image(systemName: "arrow.up.left.and.arrow.down.right")
.font(.caption2.weight(.bold))
.foregroundStyle(.white)
.padding(FlixySpacing.snug)
.contentShape(.rect)
.gesture(resizeGesture(corner: corner))
.accessibilityLabel(Text("miniPlayer.resize"))
if !corner.isLeading { Spacer() }
}
if !corner.isTop { Spacer() }
// Über `overlay(alignment:)` gesetzt, nicht über gedrehte Stapel:
// eine Drehung auf dem Überzug kippt die gesamte Trefferfläche mit,
// und der Griff lag dann dort, wo man nicht hinfasst. Genau daran war
// das Ziehen vorher wirkungslos.
Color.clear.overlay(alignment: handleAlignment(for: corner)) {
Image(systemName: "arrow.up.left.and.arrow.down.right")
.font(.caption.weight(.bold))
.foregroundStyle(.white)
// Nur das Symbol dreht sich, damit der Pfeil in die Richtung
// zeigt, in die es tatsächlich größer wird.
.rotationEffect(.degrees(corner.isTop == corner.isLeading ? 0 : 90))
.frame(width: 44, height: 44)
.contentShape(.rect)
// Vorrang vor dem Verschieben der Kachel, das am selben Ort
// hängt — sonst gewinnt das Ziehen und die Kachel wandert.
.highPriorityGesture(resizeGesture(corner: corner))
// Und ein Tippen darf hier nicht ins Vollbild führen.
.onTapGesture { reveal() }
.accessibilityLabel(Text("miniPlayer.resize"))
}
}
/// Die Ecke der Kachel, die zur Bildschirmmitte zeigt.
private func handleAlignment(for corner: MiniPlayerPlacement.Corner) -> Alignment {
switch corner {
case .topLeading: .bottomTrailing
case .topTrailing: .bottomLeading
case .bottomLeading: .topTrailing
case .bottomTrailing: .topLeading
}
// Gespiegelt, damit das Symbol in die Richtung zeigt, in die es
// tatsächlich größer wird.
.rotationEffect(.degrees(corner.isTop == corner.isLeading ? 0 : 90))
}
private func resizeGesture(corner: MiniPlayerPlacement.Corner) -> some Gesture {
DragGesture()
DragGesture(minimumDistance: 2)
.onChanged { value in
hideTask?.cancel()
// Klebt die Kachel rechts, wächst sie beim Ziehen nach links.
widthChange = corner.isLeading ? value.translation.width : -value.translation.width
}
.onEnded { _ in
// Die **begrenzte** Breite merken, nicht die gezogene: eine
// einmal zu weit gezogene Kachel bliebe sonst für immer zu
// groß, auch auf einem kleineren Bildschirm.
storedWidth = Double(lastWidth)
widthChange = 0
reveal()