import Foundation enum CurrencyCode: String, CaseIterable, Codable { case usd = "USD" case eur = "EUR" var symbol: String { switch self { case .usd: return "$" case .eur: return "€" } } var scryfallKey: String { switch self { case .usd: return "usd" case .eur: return "eur" } } } struct AppConfig { // 1. CONTACT EMAIL (Required by Scryfall API policy) // Replace with your real developer email before submitting to the App Store. static let contactEmail = "support@iymtg.com" // TODO: Replace with your real email // 2. IN-APP PURCHASE ID (Use a "Consumable" type in App Store Connect for repeatable tips) static let tipJarProductIDs: [String] = [] // Example: Use your real Product ID // 3. VERSIONING static let appVersion = "1.1.0" // Follows Semantic Versioning (Major.Minor.Patch) static let buildNumber = "2" // Increments with each build submitted to App Store Connect // Feature Flags static let enableFoilDetection = true static let enableConditionGrading = true static let enableSetSymbolDetection = true static let enableStampDetection = true static let defaultCurrency: CurrencyCode = .usd struct Defaults { static let masterCollectionName = "Master Collection" static let unsortedBoxName = "Unsorted" static let defaultCondition = "Near Mint (NM)" static let defaultFoil = "None" } static var isTrainingOptIn: Bool { get { UserDefaults.standard.bool(forKey: "TrainingOptIn") } set { UserDefaults.standard.set(newValue, forKey: "TrainingOptIn") } } // Firebase secondary backup — metadata only (no card images). // Default: false. Users opt-in via the Cloud Backup section in Library settings. static var isFirebaseBackupEnabled: Bool { get { UserDefaults.standard.bool(forKey: "FirebaseBackupEnabled") } set { UserDefaults.standard.set(newValue, forKey: "FirebaseBackupEnabled") } } static var scryfallUserAgent: String { return "IYmtg/\(appVersion) (\(contactEmail))" } static func validate() { #if DEBUG let knownPlaceholderDomains = ["yourdomain.com", "example.com", "yourapp.com"] if knownPlaceholderDomains.contains(where: { contactEmail.contains($0) }) || contactEmail.isEmpty { fatalError("🛑 SETUP ERROR: Change 'contactEmail' in AppConfig.swift to your real email.") } if tipJarProductIDs.isEmpty { print("⚠️ CONFIG WARNING: 'tipJarProductIDs' is empty. Tip Jar will not be available.") } else if let first = tipJarProductIDs.first, (first.contains("yourname") || first == "com.iymtg.app.tip") { print("⚠️ CONFIG WARNING: 'tipJarProductIDs' contains placeholder. IAP will not load.") } #endif } }