Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
bde7b0bd3f
commit
754654665c
@ -388,13 +388,9 @@ final class GameState {
|
||||
bankerValue: bankerHandValue
|
||||
))
|
||||
|
||||
// Show result banner
|
||||
// Show result banner - stays until user taps New Round
|
||||
showResultBanner = true
|
||||
|
||||
try? await Task.sleep(for: .seconds(2))
|
||||
|
||||
currentPhase = .roundComplete
|
||||
showResultBanner = false
|
||||
isAnimating = false
|
||||
}
|
||||
|
||||
@ -402,6 +398,9 @@ final class GameState {
|
||||
func newRound() {
|
||||
guard currentPhase == .roundComplete else { return }
|
||||
|
||||
// Dismiss result banner
|
||||
showResultBanner = false
|
||||
|
||||
currentBets = []
|
||||
visiblePlayerCards = []
|
||||
visibleBankerCards = []
|
||||
|
||||
@ -81,7 +81,7 @@ struct GameTableView: View {
|
||||
)
|
||||
.padding(.horizontal, Design.Spacing.medium)
|
||||
|
||||
Spacer(minLength: Design.Spacing.small)
|
||||
Spacer(minLength: Design.Spacing.medium)
|
||||
|
||||
// Chip selector - shows higher chips as you win more!
|
||||
ChipSelectorView(
|
||||
@ -89,7 +89,8 @@ struct GameTableView: View {
|
||||
balance: state.balance,
|
||||
maxBet: state.maxBet
|
||||
)
|
||||
.padding(.bottom, Design.Spacing.medium)
|
||||
|
||||
Spacer(minLength: Design.Spacing.small)
|
||||
|
||||
// Action buttons
|
||||
ActionButtonsView(
|
||||
@ -114,7 +115,8 @@ struct GameTableView: View {
|
||||
totalWinnings: state.lastWinnings,
|
||||
betResults: state.betResults,
|
||||
playerHadPair: state.playerHadPair,
|
||||
bankerHadPair: state.bankerHadPair
|
||||
bankerHadPair: state.bankerHadPair,
|
||||
onNewRound: { state.newRound() }
|
||||
)
|
||||
.transition(.opacity)
|
||||
|
||||
@ -660,9 +662,9 @@ struct ActionButtonsView: View {
|
||||
// MARK: - Fixed font sizes for action buttons
|
||||
// Fixed because buttons have constrained space and must remain usable
|
||||
|
||||
private let buttonFontSize: CGFloat = 16
|
||||
private let iconSize: CGFloat = 24
|
||||
private let statusFontSize: CGFloat = 14
|
||||
private let buttonFontSize: CGFloat = Design.BaseFontSize.xLarge
|
||||
private let iconSize: CGFloat = Design.BaseFontSize.xxLarge + Design.Spacing.xSmall
|
||||
private let statusFontSize: CGFloat = Design.BaseFontSize.medium
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: Design.Spacing.medium) {
|
||||
@ -672,10 +674,11 @@ struct ActionButtonsView: View {
|
||||
|
||||
// Deal button - icon only at accessibility sizes
|
||||
dealButton
|
||||
} else if gameState.currentPhase == .roundComplete {
|
||||
// New round button - icon only at accessibility sizes
|
||||
} else if gameState.currentPhase == .roundComplete && !gameState.showResultBanner {
|
||||
// New round button - only shown after banner is dismissed
|
||||
// (The banner itself has a New Round button)
|
||||
newRoundButton
|
||||
} else {
|
||||
} else if !gameState.showResultBanner {
|
||||
// Playing indicator
|
||||
HStack(spacing: Design.Spacing.xSmall) {
|
||||
ProgressView()
|
||||
@ -700,7 +703,7 @@ struct ActionButtonsView: View {
|
||||
.labelStyle(.iconOnly)
|
||||
.font(.system(size: iconSize, weight: .semibold))
|
||||
.foregroundStyle(.white)
|
||||
.padding(Design.Spacing.medium)
|
||||
.padding(Design.Spacing.medium + Design.Spacing.xxSmall)
|
||||
.background(
|
||||
Circle()
|
||||
.fill(Color.Button.destructive)
|
||||
@ -712,8 +715,8 @@ struct ActionButtonsView: View {
|
||||
.labelStyle(.titleOnly)
|
||||
.font(.system(size: buttonFontSize, weight: .semibold))
|
||||
.foregroundStyle(.white)
|
||||
.padding(.horizontal, Design.Spacing.xLarge)
|
||||
.padding(.vertical, Design.Spacing.medium)
|
||||
.padding(.horizontal, Design.Spacing.xxLarge)
|
||||
.padding(.vertical, Design.Spacing.medium + Design.Spacing.xxSmall)
|
||||
.background(
|
||||
Capsule()
|
||||
.fill(Color.Button.destructive)
|
||||
@ -730,7 +733,7 @@ struct ActionButtonsView: View {
|
||||
.labelStyle(.iconOnly)
|
||||
.font(.system(size: iconSize, weight: .bold))
|
||||
.foregroundStyle(.black)
|
||||
.padding(Design.Spacing.medium)
|
||||
.padding(Design.Spacing.medium + Design.Spacing.xxSmall)
|
||||
.background(
|
||||
Circle()
|
||||
.fill(
|
||||
@ -749,8 +752,8 @@ struct ActionButtonsView: View {
|
||||
.labelStyle(.titleOnly)
|
||||
.font(.system(size: buttonFontSize, weight: .bold))
|
||||
.foregroundStyle(.black)
|
||||
.padding(.horizontal, Design.Spacing.xxxLarge)
|
||||
.padding(.vertical, Design.Spacing.medium)
|
||||
.padding(.horizontal, Design.Spacing.xxxLarge + Design.Spacing.small)
|
||||
.padding(.vertical, Design.Spacing.medium + Design.Spacing.xxSmall)
|
||||
.background(
|
||||
Capsule()
|
||||
.fill(
|
||||
@ -774,7 +777,7 @@ struct ActionButtonsView: View {
|
||||
.labelStyle(.iconOnly)
|
||||
.font(.system(size: iconSize, weight: .bold))
|
||||
.foregroundStyle(.black)
|
||||
.padding(Design.Spacing.medium)
|
||||
.padding(Design.Spacing.medium + Design.Spacing.xxSmall)
|
||||
.background(
|
||||
Circle()
|
||||
.fill(
|
||||
@ -791,8 +794,8 @@ struct ActionButtonsView: View {
|
||||
.labelStyle(.titleOnly)
|
||||
.font(.system(size: buttonFontSize, weight: .bold))
|
||||
.foregroundStyle(.black)
|
||||
.padding(.horizontal, Design.Spacing.xxxLarge)
|
||||
.padding(.vertical, Design.Spacing.medium)
|
||||
.padding(.horizontal, Design.Spacing.xxxLarge + Design.Spacing.small)
|
||||
.padding(.vertical, Design.Spacing.medium + Design.Spacing.xxSmall)
|
||||
.background(
|
||||
Capsule()
|
||||
.fill(
|
||||
|
||||
@ -15,11 +15,13 @@ struct ResultBannerView: View {
|
||||
let betResults: [BetResult]
|
||||
var playerHadPair: Bool = false
|
||||
var bankerHadPair: Bool = false
|
||||
let onNewRound: () -> Void
|
||||
|
||||
@State private var showBanner = false
|
||||
@State private var showText = false
|
||||
@State private var showBreakdown = false
|
||||
@State private var showTotal = false
|
||||
@State private var showButton = false
|
||||
|
||||
// MARK: - Scaled Font Sizes (Dynamic Type)
|
||||
|
||||
@ -110,6 +112,31 @@ struct ResultBannerView: View {
|
||||
.scaleEffect(showTotal ? Design.Scale.normal : Design.Scale.shrunk)
|
||||
.opacity(showTotal ? Design.Scale.normal : 0)
|
||||
}
|
||||
|
||||
// New Round button
|
||||
Button {
|
||||
onNewRound()
|
||||
} label: {
|
||||
Text("New Round")
|
||||
.font(.system(size: Design.BaseFontSize.xLarge, weight: .bold))
|
||||
.foregroundStyle(.black)
|
||||
.padding(.horizontal, Design.Spacing.xxxLarge + Design.Spacing.small)
|
||||
.padding(.vertical, Design.Spacing.medium + Design.Spacing.xxSmall)
|
||||
.background(
|
||||
Capsule()
|
||||
.fill(
|
||||
LinearGradient(
|
||||
colors: [Color.Button.goldLight, Color.Button.goldDark],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom
|
||||
)
|
||||
)
|
||||
)
|
||||
.shadow(color: .yellow.opacity(Design.Opacity.light), radius: Design.Shadow.radiusMedium)
|
||||
}
|
||||
.scaleEffect(showButton ? Design.Scale.normal : Design.Scale.shrunk)
|
||||
.opacity(showButton ? Design.Scale.normal : 0)
|
||||
.padding(.top, Design.Spacing.small)
|
||||
}
|
||||
.padding(.horizontal, Design.Spacing.xLarge)
|
||||
.padding(.vertical, Design.Spacing.xxLarge)
|
||||
@ -161,6 +188,11 @@ struct ResultBannerView: View {
|
||||
showTotal = true
|
||||
}
|
||||
|
||||
// Show button after everything else
|
||||
withAnimation(.spring(duration: Design.Animation.springDuration, bounce: Design.Animation.springBounce).delay(Design.Animation.staggerDelay3 + Design.Animation.staggerDelay1)) {
|
||||
showButton = true
|
||||
}
|
||||
|
||||
// Announce result to VoiceOver users
|
||||
announceResult()
|
||||
}
|
||||
@ -371,7 +403,8 @@ struct ConfettiView: View {
|
||||
BetResult(type: .tie, amount: 500, payout: -500)
|
||||
],
|
||||
playerHadPair: true,
|
||||
bankerHadPair: false
|
||||
bankerHadPair: false,
|
||||
onNewRound: {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,14 +35,14 @@ public struct ChipSelectorView: View {
|
||||
|
||||
public var body: some View {
|
||||
ScrollView(.horizontal) {
|
||||
HStack(spacing: CasinoDesign.Spacing.small) {
|
||||
HStack(spacing: CasinoDesign.Spacing.medium) {
|
||||
ForEach(availableChips) { denomination in
|
||||
Button {
|
||||
selectedChip = denomination
|
||||
} label: {
|
||||
ChipView(
|
||||
denomination: denomination,
|
||||
size: CasinoDesign.Size.chipMedium,
|
||||
size: CasinoDesign.Size.chipLarge,
|
||||
isSelected: selectedChip == denomination,
|
||||
theme: theme
|
||||
)
|
||||
@ -52,10 +52,11 @@ public struct ChipSelectorView: View {
|
||||
.disabled(balance < denomination.rawValue)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.vertical, CasinoDesign.Spacing.small) // Extra padding for selection scale effect
|
||||
.padding(.horizontal, CasinoDesign.Spacing.large)
|
||||
.padding(.vertical, CasinoDesign.Spacing.medium) // Extra padding for selection scale effect
|
||||
}
|
||||
.scrollIndicators(.hidden)
|
||||
.frame(maxWidth: .infinity) // Center the scroll content
|
||||
.accessibilityElement(children: .contain)
|
||||
.accessibilityLabel(String(localized: "Chip selector", bundle: .module))
|
||||
.accessibilityHint(String(localized: "Double tap a chip to select bet amount", bundle: .module))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user