**Antippen startet, langes Drücken führt auf die Detailseite.** Am Telefon und am iPad; am Mac bleibt der Klick die Seite, denn dort gibt es den Abspielknopf beim Überfahren und langes Drücken ist keine übliche Geste. Die Hürde war nicht die Geste, sondern das Schieben: ein `NavigationLink` schiebt selbst, ein Menüeintrag kann es nicht. Der Stapel ist deshalb ein eigener Typ mit Pfad (`MediaStack`) und reicht eine Schiebefunktion über die Umgebung nach innen — denselben Weg nimmt schon die Meldung, dass sich am Server etwas geändert hat. **Zwei Knöpfe übereinander auf der Detailseite.** Das Monogramm hing als Überzug an `mediaStack` — also über **jedem** Bildschirm dieses Stapels, auch den geschobenen, und dort über deren Drei-Punkte-Menü. Es gilt jetzt für die Startseite und endet mit ihr. **Der Kopf der Detailseite war viel zu flach.** Dort stand kein Seitenverhältnis, also galt die Vorgabe 16∶9 — während `HeroArtwork` auf einem schmalen Gerät ein **Plakat** anfordert, also hochkant. Zu sehen war ein Streifen aus der Mitte. Der Aufmacher auf der Startseite macht es seit Langem richtig; die beiden Detailseiten nicht. **Die Mediathekenleiste stand linksbündig in einer halbleeren Kapsel.** Jetzt ist sie so breit wie ihr Inhalt und mittig. `ViewThatFits` nimmt die ungescrollte Reihe, solange sie passt, sonst die scrollbare — damit steht nirgends eine Zahl, ab wann es kippt. **Und der Grund, warum die Mediathekenauswahl beim Nutzer nie griff:** Plex. Dessen Hubs sagten nicht, aus welcher Mediathek sie stammen, also warf der Filter jede Reihe weg und fiel auf „alles" zurück — ein Schalter, der nichts tut. `PlexHub` liest jetzt `librarySectionID`, als Zahl oder als Zeichenkette, je nachdem was der Server liefert. Vier Tests dazu. Das ist **kein** Wiederaufnehmen der Plex-Arbeit: es repariert eine Funktion, die dort gelogen hat. Neues kommt weiterhin nicht dazu. iOS und tvOS bauen, 476 Tests grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
50 lines
2.1 KiB
Swift
50 lines
2.1 KiB
Swift
import SwiftUI
|
|
import MediaKit
|
|
|
|
/// Ein Navigationsstapel mit allen Zielen — und einem Weg, von innen zu
|
|
/// schieben.
|
|
///
|
|
/// **Warum der Pfad hier liegt und nicht beim System.** Ein `NavigationLink`
|
|
/// schiebt selbst; wer stattdessen aus einem Knopf heraus schieben will,
|
|
/// braucht eine Bindung. Genau das verlangt die Kachel, seit Antippen
|
|
/// abspielt: der Weg auf die Detailseite führt dann über das Kontextmenü, und
|
|
/// ein Menüeintrag ist kein Link.
|
|
///
|
|
/// **Die Ziele stehen hier und nur hier.** Sie je Bildschirm anzumelden hat
|
|
/// schon einmal nicht funktioniert: liegen zwei Bildschirme übereinander,
|
|
/// entscheidet sonst die Reihenfolge, und ein Tippen landete im Nichts.
|
|
struct MediaStack<Content: View>: View {
|
|
@ViewBuilder let content: () -> Content
|
|
|
|
@Environment(FlixySession.self) private var session
|
|
@State private var path = NavigationPath()
|
|
|
|
var body: some View {
|
|
NavigationStack(path: $path) {
|
|
content()
|
|
.navigationDestination(for: MediaRoute.self) { MediaDetailView(route: $0) }
|
|
.navigationDestination(for: LibraryRoute.self) { route in
|
|
if let library = session.libraries.first(where: { $0.id == route.id }) {
|
|
LibraryView(library: library)
|
|
}
|
|
}
|
|
.navigationDestination(for: LiveTVRoute.self) { _ in LiveTVView() }
|
|
.navigationDestination(for: SearchRoute.self) { _ in SearchView() }
|
|
}
|
|
.environment(\.flixyPush) { ziel in path.append(ziel) }
|
|
}
|
|
}
|
|
|
|
extension EnvironmentValues {
|
|
/// Schiebt ein Ziel auf den Stapel, in dem man gerade steht.
|
|
///
|
|
/// **Über die Umgebung, weil der Weg sonst lang ist.** Eine Kachel steckt
|
|
/// in einer Reihe, die in der Startseite steckt, die im Stapel steckt.
|
|
/// Eine Bindung durch jede Ebene zu reichen hiesse, drei Ansichten um ein
|
|
/// Argument zu erweitern, das sie nur weitergeben.
|
|
///
|
|
/// Die Voreinstellung tut nichts: ausserhalb eines Stapels gibt es nichts
|
|
/// zu schieben, und ein Absturz wäre die schlechtere Antwort.
|
|
@Entry var flixyPush: (any Hashable) -> Void = { _ in }
|
|
}
|