crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

commit 769d18e27ef8ee1a2afd0573720b8febc5ed0b14
parent 23a2e4b017d917e0b6e5f614b601114d46e9fc71
Author: Michael Camilleri <[email protected]>
Date:   Mon, 15 Jun 2026 06:14:39 +0900

Update joining message to assure user

A slow share-accept could sit on a single 'Joining puzzle…' line for
many seconds, reading as a stall. The join itself exposes no observable
stages (only coarse start/complete signals), so the placeholder now
cycles its message purely on elapsed time to keep signalling that work
is still underway. A one-second ticker in the view's .task drives the
change; it is cancelled with the view when the placeholder clears on
join. The text cross-fades between stages. The accessibility label stays
static for now.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

Diffstat:
MCrossmate/Views/JoiningPuzzleView.swift | 25++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/Crossmate/Views/JoiningPuzzleView.swift b/Crossmate/Views/JoiningPuzzleView.swift @@ -8,6 +8,21 @@ import SwiftUI struct JoiningPuzzleView: View { let shape: GridSilhouette.Grid? + /// Seconds the view has been on screen. The join has no observable stages + /// to drive the message (only coarse start/complete signals exist), so the + /// text advances purely on elapsed time to reassure the user that work is + /// still happening rather than stalled. + @State private var elapsed = 0 + + private var message: String { + switch elapsed { + case ..<5: return "Joining puzzle…" + case ..<10: return "Syncing with iCloud…" + case ..<15: return "Accepting invitation…" + default: return "Waiting for response…" + } + } + var body: some View { ZStack { Color(.systemBackground).ignoresSafeArea() @@ -28,13 +43,21 @@ struct JoiningPuzzleView: View { VStack(spacing: 12) { ProgressView() - Text("Joining puzzle…") + Text(message) .font(.headline) .foregroundStyle(.secondary) + .animation(.default, value: message) } } } .accessibilityElement(children: .combine) .accessibilityLabel("Joining puzzle") + .task { + // Cancelled automatically when the placeholder clears on join. + while !Task.isCancelled { + try? await Task.sleep(for: .seconds(1)) + elapsed += 1 + } + } } }