106 lines
3.8 KiB
Swift
106 lines
3.8 KiB
Swift
import Foundation
|
|
import SwiftData
|
|
|
|
struct AppLaunchContext {
|
|
enum LaunchTab: String {
|
|
case today
|
|
case rituals
|
|
case insights
|
|
case history
|
|
case settings
|
|
}
|
|
|
|
let isRunningTests: Bool
|
|
let isUITesting: Bool
|
|
let shouldResetUserDefaults: Bool
|
|
let hasCompletedSetupWizardOverride: Bool?
|
|
let shouldSeedThreePresets: Bool
|
|
let shouldPreloadDemoData: Bool
|
|
let requestedInitialTab: LaunchTab?
|
|
|
|
init(environment: [String: String] = ProcessInfo.processInfo.environment) {
|
|
isRunningTests = environment["XCTestConfigurationFilePath"] != nil
|
|
isUITesting = Self.isEnabled(environment["UITEST_MODE"])
|
|
shouldResetUserDefaults = Self.isEnabled(environment["UITEST_RESET_USER_DEFAULTS"])
|
|
hasCompletedSetupWizardOverride = Self.optionalBool(environment["UITEST_HAS_COMPLETED_SETUP_WIZARD"])
|
|
shouldSeedThreePresets = Self.isEnabled(environment["UITEST_SEED_THREE_PRESETS"])
|
|
shouldPreloadDemoData = Self.isEnabled(environment["UITEST_PRELOAD_DEMO_DATA"])
|
|
requestedInitialTab = Self.parseTab(environment["UITEST_INITIAL_TAB"])
|
|
}
|
|
|
|
func applyUserDefaultsOverrides(bundleIdentifier: String?) {
|
|
guard isUITesting else { return }
|
|
|
|
if shouldResetUserDefaults, let bundleIdentifier {
|
|
UserDefaults.standard.removePersistentDomain(forName: bundleIdentifier)
|
|
}
|
|
|
|
if let hasCompletedSetupWizardOverride {
|
|
UserDefaults.standard.set(hasCompletedSetupWizardOverride, forKey: "hasCompletedSetupWizard")
|
|
}
|
|
}
|
|
|
|
func modelConfiguration(for schema: Schema) -> ModelConfiguration {
|
|
if isUITesting {
|
|
// UI tests should always run with isolated in-memory persistence.
|
|
return ModelConfiguration(
|
|
schema: schema,
|
|
isStoredInMemoryOnly: true,
|
|
cloudKitDatabase: .none
|
|
)
|
|
}
|
|
|
|
// Use App Group for shared container between app and widget.
|
|
// Disable CloudKit mirroring under XCTest to keep simulator tests deterministic.
|
|
let storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: AppIdentifiers.appGroupIdentifier)?
|
|
.appendingPathComponent("Andromida.sqlite") ?? URL.documentsDirectory.appendingPathComponent("Andromida.sqlite")
|
|
|
|
return ModelConfiguration(
|
|
schema: schema,
|
|
url: storeURL,
|
|
cloudKitDatabase: isRunningTests ? .none : .private(AppIdentifiers.cloudKitContainerIdentifier)
|
|
)
|
|
}
|
|
|
|
func applyUITestSeeding(to ritualStore: RitualStore) {
|
|
guard isUITesting else { return }
|
|
|
|
if shouldSeedThreePresets {
|
|
ritualStore.createRitualFromPreset(RitualPresetLibrary.healthPresets[0]) // morning
|
|
ritualStore.createRitualFromPreset(RitualPresetLibrary.healthPresets[1]) // midday
|
|
ritualStore.createRitualFromPreset(RitualPresetLibrary.healthPresets[3]) // evening
|
|
}
|
|
|
|
#if DEBUG
|
|
if shouldPreloadDemoData {
|
|
ritualStore.preloadDemoData()
|
|
}
|
|
#endif
|
|
}
|
|
|
|
var initialTabOverride: RootView.RootTab? {
|
|
guard let requestedInitialTab else { return nil }
|
|
switch requestedInitialTab {
|
|
case .today: return .today
|
|
case .rituals: return .rituals
|
|
case .insights: return .insights
|
|
case .history: return .history
|
|
case .settings: return .settings
|
|
}
|
|
}
|
|
|
|
private static func isEnabled(_ value: String?) -> Bool {
|
|
optionalBool(value) ?? false
|
|
}
|
|
|
|
private static func optionalBool(_ value: String?) -> Bool? {
|
|
guard let value else { return nil }
|
|
return value == "1" || value.lowercased() == "true"
|
|
}
|
|
|
|
private static func parseTab(_ value: String?) -> LaunchTab? {
|
|
guard let value else { return nil }
|
|
return LaunchTab(rawValue: value.lowercased())
|
|
}
|
|
}
|