crossmate

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

commit c502f3e58561fa059e1930d2628a03a46c9f7657
parent 2a593b08d9d0923931b903884407a6b0747b1b96
Author: Michael Camilleri <[email protected]>
Date:   Fri,  1 May 2026 20:04:55 +0900

Use panel rather than sheet on puzzle completion

Prior to this commit, a sheet would be shown on puzzle completion. This
commit replaces the sheet with a panel that appears in place of the
keyboard (since it is no longer required).

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

Diffstat:
MCrossmate/Views/KeyboardView.swift | 2++
MCrossmate/Views/PuzzleView.swift | 65++++++++++++++++++++++++++++-------------------------------------
2 files changed, 30 insertions(+), 37 deletions(-)

diff --git a/Crossmate/Views/KeyboardView.swift b/Crossmate/Views/KeyboardView.swift @@ -14,6 +14,8 @@ struct KeyboardView: View { private let spacing: CGFloat = 6 private let keyHeight: CGFloat = 46 + static let standardHeight: CGFloat = 170 + var body: some View { VStack(spacing: spacing) { KeyboardRow(referenceColumns: 10, spacing: spacing, keyHeight: keyHeight) { diff --git a/Crossmate/Views/PuzzleView.swift b/Crossmate/Views/PuzzleView.swift @@ -9,7 +9,6 @@ struct PuzzleView: View { @Environment(\.dismiss) private var dismiss @State private var isRenaming = false @State private var renameDraft = "" - @State private var showSuccessScreen = false @State private var showErrorsAlert = false @State private var isConfirmingLeave = false @State private var leaveError: String? @@ -180,7 +179,6 @@ struct PuzzleView: View { session.togglePencil() } onComplete?() - showSuccessScreen = true } } .alert("Not Quite Right", isPresented: $showErrorsAlert) { @@ -188,9 +186,6 @@ struct PuzzleView: View { } message: { Text("One or more squares are incorrect.") } - .sheet(isPresented: $showSuccessScreen) { - SuccessScreen(session: session) - } .alert("Leave Puzzle?", isPresented: $isConfirmingLeave) { Button("Leave", role: .destructive) { Task { await leaveSharedGame() } @@ -264,9 +259,22 @@ struct PuzzleView: View { private var controlsArea: some View { VStack(spacing: 0) { ClueBarSlot(session: session) - KeyboardView(session: session) - .disabled(isSolved) - .background(Color(.systemGroupedBackground)) + ZStack { + if isSolved { + SuccessPanel(session: session) + .transition(.move(edge: .bottom)) + } else { + KeyboardView(session: session) + .transition(.move(edge: .bottom)) + } + } + .frame(height: KeyboardView.standardHeight) + .clipped() + .background { + Color(.systemGroupedBackground) + .ignoresSafeArea(edges: .bottom) + } + .animation(.smooth(duration: 0.4), value: isSolved) } } @@ -450,40 +458,23 @@ private struct ClueBar: View { } } -private struct SuccessScreen: View { +private struct SuccessPanel: View { let session: PlayerSession - @Environment(\.dismiss) private var dismiss var body: some View { - NavigationStack { - VStack(spacing: 24) { - VStack(spacing: 8) { - Image(systemName: "checkmark.seal.fill") - .font(.system(size: 64)) - .foregroundStyle(.tint) - Text("Solved!") - .font(.largeTitle.weight(.bold)) - Text(session.puzzle.title) - .font(.headline) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - if let author = session.puzzle.author { - Text(author) - .font(.subheadline) - .foregroundStyle(.secondary) - } - } - Spacer() - } - .frame(maxWidth: .infinity) - .padding(.top, 48) - .padding(.horizontal) - .toolbar { - ToolbarItem(placement: .topBarTrailing) { - Button("Done") { dismiss() } - } + VStack(spacing: 8) { + Image(systemName: "checkmark.seal.fill") + .font(.system(size: 44)) + .foregroundStyle(.tint) + Text("Solved!") + .font(.title2.weight(.bold)) + if let author = session.puzzle.author { + Text("By \(author)") + .font(.subheadline) + .foregroundStyle(.secondary) } } + .frame(maxWidth: .infinity, maxHeight: .infinity) } }