Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
3132d760ad
commit
4bd99d88ef
@ -159,16 +159,52 @@ final class GameSettings {
|
|||||||
static let soundVolume = "settings.soundVolume"
|
static let soundVolume = "settings.soundVolume"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - iCloud
|
||||||
|
|
||||||
|
private let iCloudStore = NSUbiquitousKeyValueStore.default
|
||||||
|
|
||||||
|
/// Whether iCloud is available.
|
||||||
|
var iCloudAvailable: Bool {
|
||||||
|
FileManager.default.ubiquityIdentityToken != nil
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Initialization
|
// MARK: - Initialization
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
load()
|
load()
|
||||||
|
|
||||||
|
// Register for iCloud changes
|
||||||
|
NotificationCenter.default.addObserver(
|
||||||
|
forName: NSUbiquitousKeyValueStore.didChangeExternallyNotification,
|
||||||
|
object: iCloudStore,
|
||||||
|
queue: .main
|
||||||
|
) { [weak self] _ in
|
||||||
|
Task { @MainActor in
|
||||||
|
self?.loadFromiCloud()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger iCloud sync
|
||||||
|
if iCloudAvailable {
|
||||||
|
iCloudStore.synchronize()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Persistence
|
// MARK: - Persistence
|
||||||
|
|
||||||
/// Loads settings from UserDefaults.
|
/// Loads settings from UserDefaults, then checks iCloud for newer settings.
|
||||||
func load() {
|
func load() {
|
||||||
|
// First load from local UserDefaults
|
||||||
|
loadFromLocal()
|
||||||
|
|
||||||
|
// Then check iCloud for potentially newer settings
|
||||||
|
if iCloudAvailable {
|
||||||
|
loadFromiCloud()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loads settings from local UserDefaults.
|
||||||
|
private func loadFromLocal() {
|
||||||
let defaults = UserDefaults.standard
|
let defaults = UserDefaults.standard
|
||||||
|
|
||||||
if let rawDeckCount = defaults.object(forKey: Keys.deckCount) as? Int,
|
if let rawDeckCount = defaults.object(forKey: Keys.deckCount) as? Int,
|
||||||
@ -214,8 +250,58 @@ final class GameSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Saves settings to UserDefaults.
|
/// Loads settings from iCloud.
|
||||||
|
private func loadFromiCloud() {
|
||||||
|
guard iCloudAvailable else { return }
|
||||||
|
|
||||||
|
if let rawDeckCount = iCloudStore.object(forKey: Keys.deckCount) as? Int,
|
||||||
|
let deckCount = DeckCount(rawValue: rawDeckCount) {
|
||||||
|
self.deckCount = deckCount
|
||||||
|
}
|
||||||
|
|
||||||
|
if let rawTableLimits = iCloudStore.string(forKey: Keys.tableLimits),
|
||||||
|
let tableLimits = TableLimits(rawValue: rawTableLimits) {
|
||||||
|
self.tableLimits = tableLimits
|
||||||
|
}
|
||||||
|
|
||||||
|
if let balance = iCloudStore.object(forKey: Keys.startingBalance) as? Int {
|
||||||
|
self.startingBalance = balance
|
||||||
|
}
|
||||||
|
|
||||||
|
if iCloudStore.object(forKey: Keys.showAnimations) != nil {
|
||||||
|
self.showAnimations = iCloudStore.bool(forKey: Keys.showAnimations)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let speed = iCloudStore.object(forKey: Keys.dealingSpeed) as? Double {
|
||||||
|
self.dealingSpeed = speed
|
||||||
|
}
|
||||||
|
|
||||||
|
if iCloudStore.object(forKey: Keys.showCardsRemaining) != nil {
|
||||||
|
self.showCardsRemaining = iCloudStore.bool(forKey: Keys.showCardsRemaining)
|
||||||
|
}
|
||||||
|
|
||||||
|
if iCloudStore.object(forKey: Keys.showHistory) != nil {
|
||||||
|
self.showHistory = iCloudStore.bool(forKey: Keys.showHistory)
|
||||||
|
}
|
||||||
|
|
||||||
|
if iCloudStore.object(forKey: Keys.soundEnabled) != nil {
|
||||||
|
self.soundEnabled = iCloudStore.bool(forKey: Keys.soundEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
if iCloudStore.object(forKey: Keys.hapticsEnabled) != nil {
|
||||||
|
self.hapticsEnabled = iCloudStore.bool(forKey: Keys.hapticsEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let volume = iCloudStore.object(forKey: Keys.soundVolume) as? Double {
|
||||||
|
self.soundVolume = Float(volume)
|
||||||
|
}
|
||||||
|
|
||||||
|
print("GameSettings: Loaded from iCloud")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Saves settings to UserDefaults and iCloud.
|
||||||
func save() {
|
func save() {
|
||||||
|
// Save to local UserDefaults
|
||||||
let defaults = UserDefaults.standard
|
let defaults = UserDefaults.standard
|
||||||
defaults.set(deckCount.rawValue, forKey: Keys.deckCount)
|
defaults.set(deckCount.rawValue, forKey: Keys.deckCount)
|
||||||
defaults.set(tableLimits.rawValue, forKey: Keys.tableLimits)
|
defaults.set(tableLimits.rawValue, forKey: Keys.tableLimits)
|
||||||
@ -227,6 +313,22 @@ final class GameSettings {
|
|||||||
defaults.set(soundEnabled, forKey: Keys.soundEnabled)
|
defaults.set(soundEnabled, forKey: Keys.soundEnabled)
|
||||||
defaults.set(hapticsEnabled, forKey: Keys.hapticsEnabled)
|
defaults.set(hapticsEnabled, forKey: Keys.hapticsEnabled)
|
||||||
defaults.set(soundVolume, forKey: Keys.soundVolume)
|
defaults.set(soundVolume, forKey: Keys.soundVolume)
|
||||||
|
|
||||||
|
// Also save to iCloud
|
||||||
|
if iCloudAvailable {
|
||||||
|
iCloudStore.set(deckCount.rawValue, forKey: Keys.deckCount)
|
||||||
|
iCloudStore.set(tableLimits.rawValue, forKey: Keys.tableLimits)
|
||||||
|
iCloudStore.set(startingBalance, forKey: Keys.startingBalance)
|
||||||
|
iCloudStore.set(showAnimations, forKey: Keys.showAnimations)
|
||||||
|
iCloudStore.set(dealingSpeed, forKey: Keys.dealingSpeed)
|
||||||
|
iCloudStore.set(showCardsRemaining, forKey: Keys.showCardsRemaining)
|
||||||
|
iCloudStore.set(showHistory, forKey: Keys.showHistory)
|
||||||
|
iCloudStore.set(soundEnabled, forKey: Keys.soundEnabled)
|
||||||
|
iCloudStore.set(hapticsEnabled, forKey: Keys.hapticsEnabled)
|
||||||
|
iCloudStore.set(Double(soundVolume), forKey: Keys.soundVolume)
|
||||||
|
iCloudStore.synchronize()
|
||||||
|
print("GameSettings: Saved to iCloud")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets all settings to defaults.
|
/// Resets all settings to defaults.
|
||||||
|
|||||||
@ -67,13 +67,17 @@ ChipSelectorView(
|
|||||||
ChipStackView(amount: 500, chipColor: .red)
|
ChipStackView(amount: 500, chipColor: .red)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Chip Denominations**
|
**Chip Denominations** (with standard casino colors)
|
||||||
- `.one` (1)
|
- `.one` ($1) - White/Light Blue
|
||||||
- `.five` (5)
|
- `.five` ($5) - Red
|
||||||
- `.twentyFive` (25)
|
- `.twentyFive` ($25) - Green
|
||||||
- `.hundred` (100)
|
- `.hundred` ($100) - Black
|
||||||
- `.fiveHundred` (500)
|
- `.fiveHundred` ($500) - Purple
|
||||||
- `.thousand` (1000)
|
- `.thousand` ($1,000) - Yellow
|
||||||
|
- `.fiveThousand` ($5,000) - Brown
|
||||||
|
- `.tenThousand` ($10,000) - Gray (custom)
|
||||||
|
- `.twentyFiveThousand` ($25,000) - Teal (plaque style)
|
||||||
|
- `.hundredThousand` ($100,000) - Burgundy (VIP)
|
||||||
|
|
||||||
### 📋 Sheets & Popups
|
### 📋 Sheets & Popups
|
||||||
|
|
||||||
|
|||||||
@ -8,34 +8,33 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
/// The available chip denominations for casino games.
|
/// The available chip denominations for casino games.
|
||||||
|
/// Colors follow standard US casino chip conventions.
|
||||||
public enum ChipDenomination: Int, CaseIterable, Identifiable, Sendable {
|
public enum ChipDenomination: Int, CaseIterable, Identifiable, Sendable {
|
||||||
case ten = 10
|
case one = 1 // White/Blue/Gray
|
||||||
case twentyFive = 25
|
case five = 5 // Red
|
||||||
case fifty = 50
|
case twentyFive = 25 // Green
|
||||||
case hundred = 100
|
case hundred = 100 // Black
|
||||||
case fiveHundred = 500
|
case fiveHundred = 500 // Purple
|
||||||
case thousand = 1_000
|
case thousand = 1_000 // Yellow
|
||||||
case fiveThousand = 5_000
|
case fiveThousand = 5_000 // Brown/Orange
|
||||||
case tenThousand = 10_000
|
case tenThousand = 10_000 // Custom (often plaques)
|
||||||
case twentyFiveThousand = 25_000
|
case twentyFiveThousand = 25_000 // Plaque style
|
||||||
case fiftyThousand = 50_000
|
case hundredThousand = 100_000 // Plaque style
|
||||||
case hundredThousand = 100_000
|
|
||||||
|
|
||||||
public var id: Int { rawValue }
|
public var id: Int { rawValue }
|
||||||
|
|
||||||
/// The display text for this denomination.
|
/// The display text for this denomination.
|
||||||
public var displayText: String {
|
public var displayText: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .ten: return "10"
|
case .one: return "1"
|
||||||
|
case .five: return "5"
|
||||||
case .twentyFive: return "25"
|
case .twentyFive: return "25"
|
||||||
case .fifty: return "50"
|
|
||||||
case .hundred: return "100"
|
case .hundred: return "100"
|
||||||
case .fiveHundred: return "500"
|
case .fiveHundred: return "500"
|
||||||
case .thousand: return "1K"
|
case .thousand: return "1K"
|
||||||
case .fiveThousand: return "5K"
|
case .fiveThousand: return "5K"
|
||||||
case .tenThousand: return "10K"
|
case .tenThousand: return "10K"
|
||||||
case .twentyFiveThousand: return "25K"
|
case .twentyFiveThousand: return "25K"
|
||||||
case .fiftyThousand: return "50K"
|
|
||||||
case .hundredThousand: return "100K"
|
case .hundredThousand: return "100K"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,13 +43,12 @@ public enum ChipDenomination: Int, CaseIterable, Identifiable, Sendable {
|
|||||||
/// Higher chips unlock as you win more!
|
/// Higher chips unlock as you win more!
|
||||||
public var unlockBalance: Int {
|
public var unlockBalance: Int {
|
||||||
switch self {
|
switch self {
|
||||||
case .ten, .twentyFive, .fifty, .hundred: return 0 // Always available
|
case .one, .five, .twentyFive, .hundred: return 0 // Always available
|
||||||
case .fiveHundred: return 500
|
case .fiveHundred: return 500
|
||||||
case .thousand: return 1_000
|
case .thousand: return 1_000
|
||||||
case .fiveThousand: return 5_000
|
case .fiveThousand: return 5_000
|
||||||
case .tenThousand: return 10_000
|
case .tenThousand: return 10_000
|
||||||
case .twentyFiveThousand: return 25_000
|
case .twentyFiveThousand: return 25_000
|
||||||
case .fiftyThousand: return 50_000
|
|
||||||
case .hundredThousand: return 100_000
|
case .hundredThousand: return 100_000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -121,71 +121,75 @@ public struct DefaultCasinoTheme: CasinoTheme {
|
|||||||
|
|
||||||
public func chipColors(for denomination: ChipDenomination) -> ChipColorSet {
|
public func chipColors(for denomination: ChipDenomination) -> ChipColorSet {
|
||||||
switch denomination {
|
switch denomination {
|
||||||
case .ten:
|
// $1 - White/Light Blue (classic casino white chip)
|
||||||
|
case .one:
|
||||||
return ChipColorSet(
|
return ChipColorSet(
|
||||||
primary: Color(red: 0.15, green: 0.35, blue: 0.65),
|
primary: Color(red: 0.92, green: 0.94, blue: 0.96),
|
||||||
secondary: Color(red: 0.25, green: 0.5, blue: 0.85),
|
secondary: Color(red: 0.98, green: 0.99, blue: 1.0),
|
||||||
|
stripe: Color(red: 0.3, green: 0.5, blue: 0.7) // Blue accent
|
||||||
|
)
|
||||||
|
// $5 - Red (standard casino red)
|
||||||
|
case .five:
|
||||||
|
return ChipColorSet(
|
||||||
|
primary: Color(red: 0.8, green: 0.15, blue: 0.15),
|
||||||
|
secondary: Color(red: 0.95, green: 0.25, blue: 0.25),
|
||||||
stripe: .white
|
stripe: .white
|
||||||
)
|
)
|
||||||
|
// $25 - Green (standard casino green)
|
||||||
case .twentyFive:
|
case .twentyFive:
|
||||||
return ChipColorSet(
|
return ChipColorSet(
|
||||||
primary: Color(red: 0.1, green: 0.55, blue: 0.25),
|
primary: Color(red: 0.1, green: 0.55, blue: 0.25),
|
||||||
secondary: Color(red: 0.15, green: 0.75, blue: 0.35),
|
secondary: Color(red: 0.15, green: 0.7, blue: 0.35),
|
||||||
stripe: .white
|
|
||||||
)
|
|
||||||
case .fifty:
|
|
||||||
return ChipColorSet(
|
|
||||||
primary: Color(red: 0.9, green: 0.5, blue: 0.1),
|
|
||||||
secondary: Color(red: 1.0, green: 0.65, blue: 0.2),
|
|
||||||
stripe: .white
|
stripe: .white
|
||||||
)
|
)
|
||||||
|
// $100 - Black (standard casino black)
|
||||||
case .hundred:
|
case .hundred:
|
||||||
return ChipColorSet(
|
return ChipColorSet(
|
||||||
primary: Color(red: 0.1, green: 0.1, blue: 0.12),
|
primary: Color(red: 0.1, green: 0.1, blue: 0.12),
|
||||||
secondary: Color(red: 0.25, green: 0.25, blue: 0.28),
|
secondary: Color(red: 0.2, green: 0.2, blue: 0.22),
|
||||||
stripe: Color(red: 0.85, green: 0.65, blue: 0.2) // Gold
|
stripe: Color(red: 0.85, green: 0.65, blue: 0.2) // Gold accent
|
||||||
)
|
)
|
||||||
|
// $500 - Purple (standard casino purple)
|
||||||
case .fiveHundred:
|
case .fiveHundred:
|
||||||
return ChipColorSet(
|
return ChipColorSet(
|
||||||
primary: Color(red: 0.5, green: 0.15, blue: 0.55),
|
primary: Color(red: 0.45, green: 0.15, blue: 0.55),
|
||||||
secondary: Color(red: 0.7, green: 0.25, blue: 0.75),
|
secondary: Color(red: 0.6, green: 0.25, blue: 0.7),
|
||||||
stripe: .white
|
stripe: .white
|
||||||
)
|
)
|
||||||
|
// $1,000 - Yellow/Gold (standard casino yellow)
|
||||||
case .thousand:
|
case .thousand:
|
||||||
return ChipColorSet(
|
return ChipColorSet(
|
||||||
primary: Color(red: 0.85, green: 0.75, blue: 0.5),
|
primary: Color(red: 0.95, green: 0.8, blue: 0.2),
|
||||||
secondary: Color(red: 1.0, green: 0.95, blue: 0.7),
|
secondary: Color(red: 1.0, green: 0.9, blue: 0.4),
|
||||||
stripe: .black
|
stripe: .black
|
||||||
)
|
)
|
||||||
|
// $5,000 - Brown/Orange (standard casino brown)
|
||||||
case .fiveThousand:
|
case .fiveThousand:
|
||||||
return ChipColorSet(
|
return ChipColorSet(
|
||||||
primary: Color(red: 0.65, green: 0.35, blue: 0.2),
|
primary: Color(red: 0.55, green: 0.35, blue: 0.2),
|
||||||
secondary: Color(red: 0.85, green: 0.5, blue: 0.3),
|
secondary: Color(red: 0.7, green: 0.45, blue: 0.25),
|
||||||
stripe: Color(red: 0.85, green: 0.65, blue: 0.2) // Gold
|
stripe: Color(red: 0.9, green: 0.7, blue: 0.3) // Gold accent
|
||||||
)
|
)
|
||||||
|
// $10,000+ - Custom/Gray (high roller, often plaque style)
|
||||||
case .tenThousand:
|
case .tenThousand:
|
||||||
return ChipColorSet(
|
return ChipColorSet(
|
||||||
primary: Color(red: 0.7, green: 0.75, blue: 0.8),
|
primary: Color(red: 0.6, green: 0.65, blue: 0.7),
|
||||||
secondary: Color(red: 0.85, green: 0.9, blue: 0.95),
|
secondary: Color(red: 0.75, green: 0.8, blue: 0.85),
|
||||||
stripe: .white
|
stripe: Color(red: 0.2, green: 0.25, blue: 0.4) // Dark blue accent
|
||||||
)
|
)
|
||||||
|
// $25,000 - Teal/Custom (often plaques at this level)
|
||||||
case .twentyFiveThousand:
|
case .twentyFiveThousand:
|
||||||
return ChipColorSet(
|
return ChipColorSet(
|
||||||
primary: Color(red: 0.15, green: 0.4, blue: 0.45),
|
primary: Color(red: 0.15, green: 0.45, blue: 0.5),
|
||||||
secondary: Color(red: 0.2, green: 0.55, blue: 0.6),
|
secondary: Color(red: 0.2, green: 0.6, blue: 0.65),
|
||||||
stripe: Color(red: 0.85, green: 0.65, blue: 0.2) // Gold
|
stripe: Color(red: 0.9, green: 0.75, blue: 0.3) // Gold accent
|
||||||
)
|
|
||||||
case .fiftyThousand:
|
|
||||||
return ChipColorSet(
|
|
||||||
primary: Color(red: 0.85, green: 0.4, blue: 0.5),
|
|
||||||
secondary: Color(red: 1.0, green: 0.55, blue: 0.65),
|
|
||||||
stripe: Color(red: 0.3, green: 0.15, blue: 0.2)
|
|
||||||
)
|
)
|
||||||
|
// $100,000 - Burgundy/Custom (VIP plaques)
|
||||||
case .hundredThousand:
|
case .hundredThousand:
|
||||||
return ChipColorSet(
|
return ChipColorSet(
|
||||||
primary: Color(red: 0.6, green: 0.1, blue: 0.15),
|
primary: Color(red: 0.5, green: 0.1, blue: 0.15),
|
||||||
secondary: Color(red: 0.75, green: 0.15, blue: 0.2),
|
secondary: Color(red: 0.65, green: 0.15, blue: 0.2),
|
||||||
stripe: Color(red: 0.95, green: 0.75, blue: 0.3) // Bright gold
|
stripe: Color(red: 0.95, green: 0.8, blue: 0.35) // Bright gold
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,7 +87,7 @@ public struct ChipOnTableView: View {
|
|||||||
|
|
||||||
private var chipColor: Color {
|
private var chipColor: Color {
|
||||||
// Find the closest denomination for coloring
|
// Find the closest denomination for coloring
|
||||||
let denomination = ChipDenomination.allCases.last { $0.rawValue <= amount } ?? .ten
|
let denomination = ChipDenomination.allCases.last { $0.rawValue <= amount } ?? .one
|
||||||
return theme.chipColors(for: denomination).primary
|
return theme.chipColors(for: denomination).primary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user