Complete native rewrite of the web-based SoliCards game as a SwiftUI multiplatform app targeting iOS 17+, iPadOS 17+, and macOS 14+. Three solitaire variants (Klondike, Spider, FreeCell) with full game rules, drag & drop, smart zoom layout, 6 themes, 4 difficulty levels, SwiftData persistence, VoiceOver accessibility, and 57 unit tests. Key features: - MVVM + Protocol-Oriented Strategy architecture - DragGesture with coordinate-space hit-testing (long press + drag) - Smart zoom: cards auto-size to fit screen based on deepest column - Landscape: 30% bigger cards with scrollable overflow (iOS) - macOS: 120pt card cap, 92% height buffer for window resizing - Auto-save, game resume, statistics tracking via SwiftData - Privacy manifest, app icon, String Catalog, zero dependencies Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
74 lines
2.5 KiB
Swift
74 lines
2.5 KiB
Swift
import SwiftUI
|
|
|
|
struct GameTheme: Identifiable, Equatable, Sendable {
|
|
let id: String
|
|
let displayName: String
|
|
let backgroundColor: Color
|
|
let tableauColor: Color
|
|
let accentColor: Color
|
|
let cardTintColor: Color
|
|
|
|
static let allThemes: [GameTheme] = [
|
|
.classicGreen,
|
|
.darkMode,
|
|
.oceanBlue,
|
|
.royalPurple,
|
|
.forestGreen,
|
|
.sunsetOrange,
|
|
]
|
|
|
|
static let classicGreen = GameTheme(
|
|
id: "classic",
|
|
displayName: "Classic Green",
|
|
backgroundColor: Color(red: 0.0, green: 0.5, blue: 0.0),
|
|
tableauColor: Color(red: 0.0, green: 0.4, blue: 0.0),
|
|
accentColor: Color.white,
|
|
cardTintColor: Color(red: 0.0, green: 0.6, blue: 0.0)
|
|
)
|
|
|
|
static let darkMode = GameTheme(
|
|
id: "dark",
|
|
displayName: "Dark Mode",
|
|
backgroundColor: Color(red: 0.12, green: 0.12, blue: 0.14),
|
|
tableauColor: Color(red: 0.18, green: 0.18, blue: 0.2),
|
|
accentColor: Color(red: 0.4, green: 0.6, blue: 1.0),
|
|
cardTintColor: Color(red: 0.25, green: 0.25, blue: 0.28)
|
|
)
|
|
|
|
static let oceanBlue = GameTheme(
|
|
id: "ocean",
|
|
displayName: "Ocean Blue",
|
|
backgroundColor: Color(red: 0.1, green: 0.3, blue: 0.5),
|
|
tableauColor: Color(red: 0.08, green: 0.25, blue: 0.42),
|
|
accentColor: Color(red: 0.6, green: 0.85, blue: 1.0),
|
|
cardTintColor: Color(red: 0.15, green: 0.35, blue: 0.55)
|
|
)
|
|
|
|
static let royalPurple = GameTheme(
|
|
id: "purple",
|
|
displayName: "Royal Purple",
|
|
backgroundColor: Color(red: 0.3, green: 0.15, blue: 0.45),
|
|
tableauColor: Color(red: 0.25, green: 0.12, blue: 0.38),
|
|
accentColor: Color(red: 0.85, green: 0.7, blue: 1.0),
|
|
cardTintColor: Color(red: 0.35, green: 0.2, blue: 0.5)
|
|
)
|
|
|
|
static let forestGreen = GameTheme(
|
|
id: "forest",
|
|
displayName: "Forest Green",
|
|
backgroundColor: Color(red: 0.1, green: 0.35, blue: 0.15),
|
|
tableauColor: Color(red: 0.08, green: 0.28, blue: 0.12),
|
|
accentColor: Color(red: 0.6, green: 0.9, blue: 0.65),
|
|
cardTintColor: Color(red: 0.15, green: 0.4, blue: 0.2)
|
|
)
|
|
|
|
static let sunsetOrange = GameTheme(
|
|
id: "sunset",
|
|
displayName: "Sunset Orange",
|
|
backgroundColor: Color(red: 0.6, green: 0.25, blue: 0.1),
|
|
tableauColor: Color(red: 0.5, green: 0.2, blue: 0.08),
|
|
accentColor: Color(red: 1.0, green: 0.85, blue: 0.5),
|
|
cardTintColor: Color(red: 0.65, green: 0.3, blue: 0.15)
|
|
)
|
|
}
|