Gesehen und Favorit direkt an der Kachel — und die Pinch-Geste greift wieder

Drei Dinge aus dem Gebrauch.

**Das Kontextmenü einer Kachel trug genau einen Eintrag.** „Abspielen",
sonst nichts; der Kommentar daneben nannte es seit Längerem den
natürlichen Ort für „Als gesehen markieren". Jetzt steht es dort —
zusammen mit Favorit und Sternen, soweit der Server sie kennt. Es sind
dieselben Einträge wie im Menü der Detailseite: `ItemActionEntries` wird
von beiden benutzt, statt sie zweimal zu beschreiben.

Zwei Dinge daran sind nicht offensichtlich. Der Inhalt eines
Kontextmenüs lebt nur, solange das Menü offen ist — ein `@State` darin
könnte nichts anzeigen, was nach dem Tippen passiert. Ausgeführt wird
deshalb von der Kachel, die länger lebt, und dort hängt auch die
Fehlermeldung. Und danach muss die Seite neu laden: eine abgehakte Folge
gehört nicht mehr in „Weiterschauen", und der Fortschrittsbalken stimmte
sonst nicht mehr. Dafür gibt es `flixyItemChanged` in der Umgebung —
sonst müsste der Rückweg durch jede Zwischenebene gereicht werden.

**Die Pinch-Geste griff fast nie.** Sie hing an der Bildfläche, und über
der liegen die Sprungflächen — und sobald man einmal getippt hat, die
ganze Bedienung. Eine Zwei-Finger-Geste bildet sich aber nur, wenn
**beide** Finger auf der Ansicht landen, die sie trägt; in dem schmalen
Streifen dazwischen gelang das kaum. Sie hängt jetzt als
`simultaneousGesture` am ganzen Player: sie erkennt mit, statt
dazwischenzugehen, und Tippen, Doppeltippen und Scrubber bleiben
unberührt.

Gemessen im Simulator, Querformat auf einem Pro Max, mit einer echten
Zwei-Finger-Geste:

    auseinander   956 × 440 pt, Rand 0,0 / 0,0
    zusammen      782 × 440 pt, Rand 87,0 / 87,0

**Der Drehknopf zeigte ein Telefon.** Das las sich als Zustandsanzeige —
„so liegt es" — statt als Knopf. Zwei Pfeile im Kreis sagen, was
passiert.

iOS und tvOS bauen, 463 Tests grün.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-01 08:19:19 +02:00
co-authored by Claude Opus 5
parent 46b0117984
commit 3f680c7426
6 changed files with 172 additions and 62 deletions
+4 -48
View File
@@ -27,54 +27,10 @@ struct ItemActionsMenu: View {
var body: some View {
Menu {
Button {
run { backend in
if item.isWatched {
try await backend.markUnwatched(id: item.id)
} else {
try await backend.markWatched(id: item.id)
}
}
} label: {
Label(
item.isWatched ? "action.markUnwatched" : "action.markWatched",
systemImage: item.isWatched ? "eye.slash" : "checkmark.circle"
)
}
if capabilities.contains(.favourites) {
Button {
run { try await $0.setFavourite(!item.isFavourite, id: item.id) }
} label: {
Label(
item.isFavourite ? "action.removeFavourite" : "action.addFavourite",
systemImage: item.isFavourite ? "heart.slash" : "heart"
)
}
}
if capabilities.contains(.ratings) {
Menu {
ForEach((1...5).reversed(), id: \.self) { stars in
Button {
// In Zehnteln: fünf Sterne sind eine 10.
run { try await $0.rate(id: item.id, rating: stars * 2) }
} label: {
Label(String(repeating: "★", count: stars), systemImage: "star")
}
}
if item.rating != nil {
Divider()
Button(role: .destructive) {
run { try await $0.rate(id: item.id, rating: 0) }
} label: {
Label("action.clearRating", systemImage: "star.slash")
}
}
} label: {
Label("action.rate", systemImage: "star")
}
}
// Dieselben Einträge wie im Kontextmenü einer Kachel — siehe
// `ItemActionEntries`. Hier mit Kreisel und Fehlermeldung, weil
// diese Ansicht lange genug lebt, um beides zu zeigen.
ItemActionEntries(item: item, capabilities: capabilities, run: run)
} label: {
if isWorking {
ProgressView().controlSize(.small)