commit 46de4d3cfe45b6a28d8d18ca2ef83021b7b7060e
parent 3d26ea3bfed761a0051896e17bdb0a80044432e2
Author: Michael Camilleri <[email protected]>
Date: Fri, 17 Apr 2026 18:42:44 +0900
Fix clue sliding
Clues are meant to slide horizontally in a manner that responds to the
forward or backward buttons that the user presses. This commit is an
attempt to eliminate animation artifacts.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Diffstat:
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/Crossmate/Views/PuzzleView.swift b/Crossmate/Views/PuzzleView.swift
@@ -183,17 +183,17 @@ private struct ClueKey: Hashable {
private struct ClueBar: View {
@Bindable var session: PlayerSession
@Environment(PlayerPreferences.self) private var preferences
- @State private var previousKey: ClueKey?
+ @State private var slideEdge: Edge = .trailing
private var playerColor: PlayerColor { preferences.color }
var body: some View {
let clue = session.currentClue()
let currentKey = clue.map { ClueKey(direction: session.direction, number: $0.number) }
- let slideEdge = slideEdge(from: previousKey, to: currentKey)
HStack(alignment: .clueCenter, spacing: 12) {
Button {
+ slideEdge = .leading
session.goToPreviousClue()
} label: {
Image(systemName: "chevron.left")
@@ -207,21 +207,30 @@ private struct ClueBar: View {
.font(.caption)
.textCase(.uppercase)
.foregroundStyle(.secondary)
- Text(clue?.text ?? "—")
- .font(.headline)
- .lineLimit(2)
- .multilineTextAlignment(.leading)
- .alignmentGuide(.clueCenter) { d in d[VerticalAlignment.center] }
- .id(currentKey)
- .transition(.asymmetric(
- insertion: .move(edge: slideEdge),
- removal: .move(edge: slideEdge == .trailing ? .leading : .trailing)
- ))
+ ZStack(alignment: .leading) {
+ Text("X\nX")
+ .font(.headline)
+ .lineLimit(2)
+ .hidden()
+ .accessibilityHidden(true)
+ Text(clue?.text ?? "—")
+ .font(.headline)
+ .lineLimit(2)
+ .multilineTextAlignment(.leading)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ .id(currentKey)
+ .transition(.asymmetric(
+ insertion: .move(edge: slideEdge),
+ removal: .move(edge: slideEdge == .trailing ? .leading : .trailing)
+ ))
+ }
+ .alignmentGuide(.clueCenter) { d in d[VerticalAlignment.center] }
+ .frame(maxWidth: .infinity, alignment: .leading)
+ .clipped()
}
- .frame(maxWidth: .infinity, alignment: .leading)
- .clipped()
Button {
+ slideEdge = .trailing
session.goToNextClue()
} label: {
Image(systemName: "chevron.right")
@@ -234,15 +243,6 @@ private struct ClueBar: View {
.padding(.vertical, 12)
.background(playerColor.highlightFill)
.animation(.smooth(duration: 0.22), value: currentKey)
- .onChange(of: currentKey) { _, newValue in
- previousKey = newValue
- }
- }
-
- private func slideEdge(from prev: ClueKey?, to curr: ClueKey?) -> Edge {
- guard let prev, let curr else { return .trailing }
- if prev.direction != curr.direction { return .trailing }
- return curr.number > prev.number ? .trailing : .leading
}
private func label(for clue: Puzzle.Clue?) -> String {