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