Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
644127ae40
commit
50f569d137
@ -719,6 +719,28 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Add $%lld more to meet minimum" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Add $%lld more to meet minimum"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"es-MX" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Añade $%lld más para alcanzar el mínimo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr-CA" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Ajoutez %lld$ de plus pour atteindre le minimum"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Clear" : {
|
"Clear" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"en" : {
|
"en" : {
|
||||||
|
|||||||
@ -31,10 +31,44 @@ enum Design {
|
|||||||
// MARK: - Blackjack-Specific Component Sizes
|
// MARK: - Blackjack-Specific Component Sizes
|
||||||
|
|
||||||
enum Size {
|
enum Size {
|
||||||
// Cards - slightly larger than medium for better visibility
|
// Hand scaling factor (1.5 = 50% larger hands)
|
||||||
static let cardWidth: CGFloat = 60
|
static let handScale: CGFloat = 1.5
|
||||||
|
|
||||||
|
// Cards - scaled for better visibility
|
||||||
|
static let cardWidth: CGFloat = 60 * handScale // 90pt at 1.5x
|
||||||
static let cardWidthSmall: CGFloat = CasinoDesign.Size.cardWidthSmall
|
static let cardWidthSmall: CGFloat = CasinoDesign.Size.cardWidthSmall
|
||||||
static let cardOverlap: CGFloat = CasinoDesign.Size.cardOverlap
|
static let cardOverlap: CGFloat = CasinoDesign.Size.cardOverlap * handScale // Scaled overlap
|
||||||
|
|
||||||
|
// Player hands container height (accommodates larger cards)
|
||||||
|
static let playerHandsHeight: CGFloat = 180 * handScale // 270pt at 1.5x
|
||||||
|
|
||||||
|
// Hand label font sizes (scaled)
|
||||||
|
static let handLabelFontSize: CGFloat = CasinoDesign.BaseFontSize.medium * handScale
|
||||||
|
static let handNumberFontSize: CGFloat = CasinoDesign.BaseFontSize.small * handScale
|
||||||
|
static let handValueFontSize: CGFloat = CasinoDesign.BaseFontSize.xLarge * handScale
|
||||||
|
|
||||||
|
// Hint font size (scaled to match hands)
|
||||||
|
static let hintFontSize: CGFloat = CasinoDesign.BaseFontSize.small * handScale
|
||||||
|
static let hintIconSize: CGFloat = CasinoDesign.IconSize.medium * handScale
|
||||||
|
static let hintPaddingH: CGFloat = CasinoDesign.Spacing.medium * handScale
|
||||||
|
static let hintPaddingV: CGFloat = CasinoDesign.Spacing.small * handScale
|
||||||
|
|
||||||
|
// Hand icons (scaled)
|
||||||
|
static let handIconSize: CGFloat = CasinoDesign.IconSize.medium * handScale
|
||||||
|
|
||||||
|
// Hi-Lo count badge (scaled)
|
||||||
|
static let countBadgeFontSize: CGFloat = CasinoDesign.BaseFontSize.xxSmall * handScale
|
||||||
|
static let countBadgePaddingH: CGFloat = CasinoDesign.Spacing.xSmall * handScale
|
||||||
|
static let countBadgePaddingV: CGFloat = CasinoDesign.Spacing.xxxSmall * handScale
|
||||||
|
static let countBadgeOffset: CGFloat = CasinoDesign.Spacing.xSmall * handScale
|
||||||
|
|
||||||
|
// Betting zone (chip scales, but zone height stays reasonable)
|
||||||
|
static let bettingChipSize: CGFloat = 36 * handScale // 54pt at 1.5x
|
||||||
|
static let bettingZoneHeightScaled: CGFloat = CasinoDesign.Size.bettingZoneHeight // Keep original height to save space
|
||||||
|
|
||||||
|
// Card count display (scaled)
|
||||||
|
static let cardCountLabelSize: CGFloat = CasinoDesign.BaseFontSize.xSmall * handScale
|
||||||
|
static let cardCountValueSize: CGFloat = CasinoDesign.BaseFontSize.large * handScale
|
||||||
|
|
||||||
// Chips - use CasinoDesign values
|
// Chips - use CasinoDesign values
|
||||||
static let chipBadgeSize: CGFloat = CasinoDesign.Size.chipBadge
|
static let chipBadgeSize: CGFloat = CasinoDesign.Size.chipBadge
|
||||||
|
|||||||
@ -14,7 +14,7 @@ struct BettingZoneView: View {
|
|||||||
let maxBet: Int
|
let maxBet: Int
|
||||||
let onTap: () -> Void
|
let onTap: () -> Void
|
||||||
|
|
||||||
@ScaledMetric(relativeTo: .headline) private var labelFontSize: CGFloat = Design.BaseFontSize.large
|
@ScaledMetric(relativeTo: .headline) private var labelFontSize: CGFloat = Design.Size.handLabelFontSize
|
||||||
|
|
||||||
private var isAtMax: Bool {
|
private var isAtMax: Bool {
|
||||||
betAmount >= maxBet
|
betAmount >= maxBet
|
||||||
@ -33,8 +33,8 @@ struct BettingZoneView: View {
|
|||||||
|
|
||||||
// Content
|
// Content
|
||||||
if betAmount > 0 {
|
if betAmount > 0 {
|
||||||
// Show chip with amount
|
// Show chip with amount (scaled)
|
||||||
ChipOnTableView(amount: betAmount, showMax: isAtMax)
|
ChipOnTableView(amount: betAmount, showMax: isAtMax, size: Design.Size.bettingChipSize)
|
||||||
} else {
|
} else {
|
||||||
// Empty state
|
// Empty state
|
||||||
VStack(spacing: Design.Spacing.small) {
|
VStack(spacing: Design.Spacing.small) {
|
||||||
@ -44,18 +44,18 @@ struct BettingZoneView: View {
|
|||||||
|
|
||||||
HStack(spacing: Design.Spacing.medium) {
|
HStack(spacing: Design.Spacing.medium) {
|
||||||
Text(String(localized: "Min: $\(minBet)"))
|
Text(String(localized: "Min: $\(minBet)"))
|
||||||
.font(.system(size: Design.BaseFontSize.small, weight: .medium))
|
.font(.system(size: Design.Size.handNumberFontSize, weight: .medium))
|
||||||
.foregroundStyle(.white.opacity(Design.Opacity.light))
|
.foregroundStyle(.white.opacity(Design.Opacity.light))
|
||||||
|
|
||||||
Text(String(localized: "Max: $\(maxBet.formatted())"))
|
Text(String(localized: "Max: $\(maxBet.formatted())"))
|
||||||
.font(.system(size: Design.BaseFontSize.small, weight: .medium))
|
.font(.system(size: Design.Size.handNumberFontSize, weight: .medium))
|
||||||
.foregroundStyle(.white.opacity(Design.Opacity.light))
|
.foregroundStyle(.white.opacity(Design.Opacity.light))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.frame(height: Design.Size.bettingZoneHeight)
|
.frame(height: Design.Size.bettingZoneHeightScaled)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.accessibilityLabel(betAmount > 0 ? "$\(betAmount) bet" + (isAtMax ? ", maximum" : "") : "Place bet")
|
.accessibilityLabel(betAmount > 0 ? "$\(betAmount) bet" + (isAtMax ? ", maximum" : "") : "Place bet")
|
||||||
|
|||||||
@ -39,15 +39,18 @@ struct BlackjackTableView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
// Player hands area
|
// Player hands area - only show when there are cards dealt
|
||||||
PlayerHandsView(
|
if state.playerHands.first?.cards.isEmpty == false {
|
||||||
hands: state.playerHands,
|
PlayerHandsView(
|
||||||
activeHandIndex: state.activeHandIndex,
|
hands: state.playerHands,
|
||||||
isPlayerTurn: isPlayerTurn,
|
activeHandIndex: state.activeHandIndex,
|
||||||
showCardCount: showCardCount,
|
isPlayerTurn: isPlayerTurn,
|
||||||
cardWidth: cardWidth,
|
showCardCount: showCardCount,
|
||||||
cardSpacing: cardSpacing
|
cardWidth: cardWidth,
|
||||||
)
|
cardSpacing: cardSpacing
|
||||||
|
)
|
||||||
|
.transition(.opacity)
|
||||||
|
}
|
||||||
|
|
||||||
// Betting zone (when betting)
|
// Betting zone (when betting)
|
||||||
if state.currentPhase == .betting {
|
if state.currentPhase == .betting {
|
||||||
|
|||||||
@ -15,7 +15,7 @@ struct DealerHandView: View {
|
|||||||
let cardWidth: CGFloat
|
let cardWidth: CGFloat
|
||||||
let cardSpacing: CGFloat
|
let cardSpacing: CGFloat
|
||||||
|
|
||||||
@ScaledMetric(relativeTo: .headline) private var labelFontSize: CGFloat = Design.BaseFontSize.medium
|
@ScaledMetric(relativeTo: .headline) private var labelFontSize: CGFloat = Design.Size.handLabelFontSize
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: Design.Spacing.small) {
|
VStack(spacing: Design.Spacing.small) {
|
||||||
|
|||||||
@ -111,18 +111,18 @@ struct GameTableView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
// Chip selector - only interactive during betting phase
|
// Chip selector - only shown during betting phase
|
||||||
// During gameplay, show chips as they were (balance + currentBet) but dimmed
|
if state.currentPhase == .betting {
|
||||||
ChipSelectorView(
|
ChipSelectorView(
|
||||||
selectedChip: $selectedChip,
|
selectedChip: $selectedChip,
|
||||||
balance: state.currentPhase == .betting ? state.balance : (state.balance + state.currentBet),
|
balance: state.balance,
|
||||||
currentBet: state.currentPhase == .betting ? state.currentBet : 0,
|
currentBet: state.currentBet,
|
||||||
maxBet: state.settings.maxBet
|
maxBet: state.settings.maxBet
|
||||||
)
|
)
|
||||||
.frame(maxWidth: maxContentWidth)
|
.frame(maxWidth: maxContentWidth)
|
||||||
.padding(.bottom, Design.Spacing.small)
|
.padding(.bottom, Design.Spacing.small)
|
||||||
.opacity(state.currentPhase == .betting ? 1.0 : Design.Opacity.medium)
|
.transition(.opacity.combined(with: .move(edge: .bottom)))
|
||||||
.allowsHitTesting(state.currentPhase == .betting) // Disable interaction when not betting
|
}
|
||||||
|
|
||||||
// Action buttons
|
// Action buttons
|
||||||
ActionButtonsView(state: state)
|
ActionButtonsView(state: state)
|
||||||
@ -216,24 +216,47 @@ struct ActionButtonsView: View {
|
|||||||
|
|
||||||
// MARK: - Betting Phase Buttons
|
// MARK: - Betting Phase Buttons
|
||||||
|
|
||||||
|
/// Whether the current bet meets the minimum requirement
|
||||||
|
private var isBetBelowMinimum: Bool {
|
||||||
|
state.currentBet > 0 && state.currentBet < state.settings.minBet
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Amount needed to reach minimum bet
|
||||||
|
private var amountNeededForMinimum: Int {
|
||||||
|
state.settings.minBet - state.currentBet
|
||||||
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var bettingButtons: some View {
|
private var bettingButtons: some View {
|
||||||
if state.currentBet > 0 {
|
if state.currentBet > 0 {
|
||||||
ActionButton(
|
VStack(spacing: Design.Spacing.small) {
|
||||||
String(localized: "Clear"),
|
// Show hint if bet is below minimum
|
||||||
icon: "xmark.circle",
|
if isBetBelowMinimum {
|
||||||
style: .destructive
|
Text(String(localized: "Add $\(amountNeededForMinimum) more to meet minimum"))
|
||||||
) {
|
.font(.system(size: Design.BaseFontSize.small, weight: .medium))
|
||||||
state.clearBet()
|
.foregroundStyle(.orange)
|
||||||
}
|
.transition(.opacity)
|
||||||
|
}
|
||||||
if state.canDeal {
|
|
||||||
ActionButton(
|
HStack(spacing: Design.Spacing.medium) {
|
||||||
String(localized: "Deal"),
|
ActionButton(
|
||||||
icon: "play.fill",
|
String(localized: "Clear"),
|
||||||
style: .primary
|
icon: "xmark.circle",
|
||||||
) {
|
style: .destructive
|
||||||
Task { await state.deal() }
|
) {
|
||||||
|
state.clearBet()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always show Deal button, but disable if below minimum
|
||||||
|
ActionButton(
|
||||||
|
String(localized: "Deal"),
|
||||||
|
icon: "play.fill",
|
||||||
|
style: .primary
|
||||||
|
) {
|
||||||
|
Task { await state.deal() }
|
||||||
|
}
|
||||||
|
.opacity(state.canDeal ? 1.0 : Design.Opacity.medium)
|
||||||
|
.disabled(!state.canDeal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -379,11 +402,11 @@ struct CardCountView: View {
|
|||||||
// Running count
|
// Running count
|
||||||
VStack(spacing: Design.Spacing.xxSmall) {
|
VStack(spacing: Design.Spacing.xxSmall) {
|
||||||
Text("Running")
|
Text("Running")
|
||||||
.font(.system(size: Design.BaseFontSize.xSmall, weight: .medium))
|
.font(.system(size: Design.Size.cardCountLabelSize, weight: .medium))
|
||||||
.foregroundStyle(.white.opacity(Design.Opacity.medium))
|
.foregroundStyle(.white.opacity(Design.Opacity.medium))
|
||||||
|
|
||||||
Text(runningCount >= 0 ? "+\(runningCount)" : "\(runningCount)")
|
Text(runningCount >= 0 ? "+\(runningCount)" : "\(runningCount)")
|
||||||
.font(.system(size: Design.BaseFontSize.large, weight: .bold, design: .monospaced))
|
.font(.system(size: Design.Size.cardCountValueSize, weight: .bold, design: .monospaced))
|
||||||
.foregroundStyle(countColor(for: runningCount))
|
.foregroundStyle(countColor(for: runningCount))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,11 +417,11 @@ struct CardCountView: View {
|
|||||||
// True count
|
// True count
|
||||||
VStack(spacing: Design.Spacing.xxSmall) {
|
VStack(spacing: Design.Spacing.xxSmall) {
|
||||||
Text("True")
|
Text("True")
|
||||||
.font(.system(size: Design.BaseFontSize.xSmall, weight: .medium))
|
.font(.system(size: Design.Size.cardCountLabelSize, weight: .medium))
|
||||||
.foregroundStyle(.white.opacity(Design.Opacity.medium))
|
.foregroundStyle(.white.opacity(Design.Opacity.medium))
|
||||||
|
|
||||||
Text(trueCount >= 0 ? "+\(trueCount, format: .number.precision(.fractionLength(1)))" : "\(trueCount, format: .number.precision(.fractionLength(1)))")
|
Text(trueCount >= 0 ? "+\(trueCount, format: .number.precision(.fractionLength(1)))" : "\(trueCount, format: .number.precision(.fractionLength(1)))")
|
||||||
.font(.system(size: Design.BaseFontSize.large, weight: .bold, design: .monospaced))
|
.font(.system(size: Design.Size.cardCountValueSize, weight: .bold, design: .monospaced))
|
||||||
.foregroundStyle(countColor(for: Int(trueCount.rounded())))
|
.foregroundStyle(countColor(for: Int(trueCount.rounded())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,15 +14,15 @@ struct HiLoCountBadge: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Text(card.hiLoDisplayText)
|
Text(card.hiLoDisplayText)
|
||||||
.font(.system(size: Design.BaseFontSize.xxSmall, weight: .bold, design: .rounded))
|
.font(.system(size: Design.Size.countBadgeFontSize, weight: .bold, design: .rounded))
|
||||||
.foregroundStyle(badgeTextColor)
|
.foregroundStyle(badgeTextColor)
|
||||||
.padding(.horizontal, Design.Spacing.xSmall)
|
.padding(.horizontal, Design.Size.countBadgePaddingH)
|
||||||
.padding(.vertical, Design.Spacing.xxxSmall)
|
.padding(.vertical, Design.Size.countBadgePaddingV)
|
||||||
.background(
|
.background(
|
||||||
Capsule()
|
Capsule()
|
||||||
.fill(badgeBackgroundColor)
|
.fill(badgeBackgroundColor)
|
||||||
)
|
)
|
||||||
.offset(x: -Design.Spacing.xSmall, y: Design.Spacing.xSmall)
|
.offset(x: -Design.Size.countBadgeOffset, y: Design.Size.countBadgeOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var badgeBackgroundColor: Color {
|
private var badgeBackgroundColor: Color {
|
||||||
|
|||||||
@ -17,13 +17,14 @@ struct HintView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: Design.Spacing.small) {
|
HStack(spacing: Design.Spacing.small) {
|
||||||
Image(systemName: "lightbulb.fill")
|
Image(systemName: "lightbulb.fill")
|
||||||
|
.font(.system(size: Design.Size.hintIconSize))
|
||||||
.foregroundStyle(.yellow)
|
.foregroundStyle(.yellow)
|
||||||
Text(String(localized: "Hint: \(hint)"))
|
Text(String(localized: "Hint: \(hint)"))
|
||||||
.font(.system(size: Design.BaseFontSize.small, weight: .medium))
|
.font(.system(size: Design.Size.hintFontSize, weight: .medium))
|
||||||
.foregroundStyle(.white.opacity(Design.Opacity.strong))
|
.foregroundStyle(.white.opacity(Design.Opacity.strong))
|
||||||
}
|
}
|
||||||
.padding(.horizontal, Design.Spacing.medium)
|
.padding(.horizontal, Design.Size.hintPaddingH)
|
||||||
.padding(.vertical, Design.Spacing.small)
|
.padding(.vertical, Design.Size.hintPaddingV)
|
||||||
.background(
|
.background(
|
||||||
Capsule()
|
Capsule()
|
||||||
.fill(Color.black.opacity(Design.Opacity.light))
|
.fill(Color.black.opacity(Design.Opacity.light))
|
||||||
@ -66,13 +67,14 @@ struct BettingHintView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: Design.Spacing.small) {
|
HStack(spacing: Design.Spacing.small) {
|
||||||
Image(systemName: icon)
|
Image(systemName: icon)
|
||||||
|
.font(.system(size: Design.Size.hintIconSize))
|
||||||
.foregroundStyle(hintColor)
|
.foregroundStyle(hintColor)
|
||||||
Text(hint)
|
Text(hint)
|
||||||
.font(.system(size: Design.BaseFontSize.small, weight: .medium))
|
.font(.system(size: Design.Size.hintFontSize, weight: .medium))
|
||||||
.foregroundStyle(.white.opacity(Design.Opacity.strong))
|
.foregroundStyle(.white.opacity(Design.Opacity.strong))
|
||||||
}
|
}
|
||||||
.padding(.horizontal, Design.Spacing.medium)
|
.padding(.horizontal, Design.Size.hintPaddingH)
|
||||||
.padding(.vertical, Design.Spacing.small)
|
.padding(.vertical, Design.Size.hintPaddingV)
|
||||||
.background(
|
.background(
|
||||||
Capsule()
|
Capsule()
|
||||||
.fill(Color.black.opacity(Design.Opacity.light))
|
.fill(Color.black.opacity(Design.Opacity.light))
|
||||||
|
|||||||
@ -56,7 +56,7 @@ struct PlayerHandsView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(height: 180)
|
.frame(height: Design.Size.playerHandsHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,8 +71,8 @@ struct PlayerHandView: View {
|
|||||||
let cardWidth: CGFloat
|
let cardWidth: CGFloat
|
||||||
let cardSpacing: CGFloat
|
let cardSpacing: CGFloat
|
||||||
|
|
||||||
@ScaledMetric(relativeTo: .headline) private var labelFontSize: CGFloat = Design.BaseFontSize.medium
|
@ScaledMetric(relativeTo: .headline) private var labelFontSize: CGFloat = Design.Size.handLabelFontSize
|
||||||
@ScaledMetric(relativeTo: .caption) private var handNumberSize: CGFloat = Design.BaseFontSize.small
|
@ScaledMetric(relativeTo: .caption) private var handNumberSize: CGFloat = Design.Size.handNumberFontSize
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: Design.Spacing.small) {
|
VStack(spacing: Design.Spacing.small) {
|
||||||
@ -129,7 +129,7 @@ struct PlayerHandView: View {
|
|||||||
|
|
||||||
if hand.isDoubledDown {
|
if hand.isDoubledDown {
|
||||||
Image(systemName: "xmark.circle.fill")
|
Image(systemName: "xmark.circle.fill")
|
||||||
.font(.system(size: handNumberSize))
|
.font(.system(size: Design.Size.handIconSize))
|
||||||
.foregroundStyle(.purple)
|
.foregroundStyle(.purple)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,8 +139,8 @@ struct PlayerHandView: View {
|
|||||||
Text(result.displayText)
|
Text(result.displayText)
|
||||||
.font(.system(size: labelFontSize, weight: .black))
|
.font(.system(size: labelFontSize, weight: .black))
|
||||||
.foregroundStyle(result.color)
|
.foregroundStyle(result.color)
|
||||||
.padding(.horizontal, Design.Spacing.medium)
|
.padding(.horizontal, Design.Size.hintPaddingH)
|
||||||
.padding(.vertical, Design.Spacing.xSmall)
|
.padding(.vertical, Design.Size.hintPaddingV)
|
||||||
.background(
|
.background(
|
||||||
Capsule()
|
Capsule()
|
||||||
.fill(result.color.opacity(Design.Opacity.hint))
|
.fill(result.color.opacity(Design.Opacity.hint))
|
||||||
@ -151,6 +151,7 @@ struct PlayerHandView: View {
|
|||||||
if hand.bet > 0 {
|
if hand.bet > 0 {
|
||||||
HStack(spacing: Design.Spacing.xSmall) {
|
HStack(spacing: Design.Spacing.xSmall) {
|
||||||
Image(systemName: "dollarsign.circle.fill")
|
Image(systemName: "dollarsign.circle.fill")
|
||||||
|
.font(.system(size: Design.Size.handIconSize))
|
||||||
.foregroundStyle(.yellow)
|
.foregroundStyle(.yellow)
|
||||||
Text("\(hand.bet * (hand.isDoubledDown ? 2 : 1))")
|
Text("\(hand.bet * (hand.isDoubledDown ? 2 : 1))")
|
||||||
.font(.system(size: handNumberSize, weight: .bold, design: .rounded))
|
.font(.system(size: handNumberSize, weight: .bold, design: .rounded))
|
||||||
|
|||||||
@ -62,26 +62,29 @@ public struct ChipStackView: View {
|
|||||||
public struct ChipOnTableView: View {
|
public struct ChipOnTableView: View {
|
||||||
let amount: Int
|
let amount: Int
|
||||||
let showMax: Bool
|
let showMax: Bool
|
||||||
|
let size: CGFloat
|
||||||
let theme: any CasinoTheme
|
let theme: any CasinoTheme
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
amount: Int,
|
amount: Int,
|
||||||
showMax: Bool = false,
|
showMax: Bool = false,
|
||||||
|
size: CGFloat = 36,
|
||||||
theme: any CasinoTheme = DefaultCasinoTheme()
|
theme: any CasinoTheme = DefaultCasinoTheme()
|
||||||
) {
|
) {
|
||||||
self.amount = amount
|
self.amount = amount
|
||||||
self.showMax = showMax
|
self.showMax = showMax
|
||||||
|
self.size = size
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Layout Constants
|
// MARK: - Layout Constants (relative to size)
|
||||||
|
|
||||||
private let chipSize: CGFloat = 36
|
private var chipSize: CGFloat { size }
|
||||||
private let innerRingSize: CGFloat = 26
|
private var innerRingSize: CGFloat { size * 0.72 } // 26/36
|
||||||
private let gradientEndRadius: CGFloat = 20
|
private var gradientEndRadius: CGFloat { size * 0.56 } // 20/36
|
||||||
private let maxBadgeFontSize: CGFloat = 8
|
private var maxBadgeFontSize: CGFloat { size * 0.22 } // 8/36
|
||||||
private let maxBadgeOffsetX: CGFloat = 6
|
private var maxBadgeOffsetX: CGFloat { size * 0.17 } // 6/36
|
||||||
private let maxBadgeOffsetY: CGFloat = -4
|
private var maxBadgeOffsetY: CGFloat { size * -0.11 } // -4/36
|
||||||
|
|
||||||
// MARK: - Computed Properties
|
// MARK: - Computed Properties
|
||||||
|
|
||||||
@ -95,8 +98,10 @@ public struct ChipOnTableView: View {
|
|||||||
amount >= 1000 ? "\(amount / 1000)K" : "\(amount)"
|
amount >= 1000 ? "\(amount / 1000)K" : "\(amount)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Text font size scales with chip size
|
||||||
private var textFontSize: CGFloat {
|
private var textFontSize: CGFloat {
|
||||||
amount >= 1000 ? CasinoDesign.BaseFontSize.xSmall : CasinoDesign.BaseFontSize.xSmall + 1
|
let baseFontSize = amount >= 1000 ? size * 0.25 : size * 0.30
|
||||||
|
return baseFontSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Accessibility
|
// MARK: - Accessibility
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user