118 lines
4.6 KiB
Swift
118 lines
4.6 KiB
Swift
import SwiftUI
|
|
import SwiftData
|
|
import Bedrock
|
|
|
|
@main
|
|
struct BusinessCardApp: App {
|
|
private let modelContainer: ModelContainer
|
|
@State private var appState: AppState
|
|
|
|
init() {
|
|
let schema = Schema([BusinessCard.self, Contact.self, ContactField.self])
|
|
let cloudKitDatabase: ModelConfiguration.CloudKitDatabase =
|
|
AppIdentifiers.isCloudKitSyncEnabled
|
|
? .private(AppIdentifiers.cloudKitContainerIdentifier)
|
|
: .none
|
|
|
|
// Register app theme for Bedrock semantic text/surface colors.
|
|
Theme.register(
|
|
text: AppThemeText.self,
|
|
surface: AppSurface.self,
|
|
accent: AppThemeAccent.self,
|
|
status: AppStatus.self
|
|
)
|
|
Theme.register(border: AppBorder.self)
|
|
|
|
// Primary strategy: App Group-backed persistent store.
|
|
var container: ModelContainer?
|
|
|
|
func makeContainer(storeURL: URL, cloudKitDatabase: ModelConfiguration.CloudKitDatabase) -> ModelContainer? {
|
|
let config = ModelConfiguration(
|
|
schema: schema,
|
|
url: storeURL,
|
|
cloudKitDatabase: cloudKitDatabase
|
|
)
|
|
return try? ModelContainer(for: schema, configurations: [config])
|
|
}
|
|
|
|
if let appGroupURL = FileManager.default.containerURL(
|
|
forSecurityApplicationGroupIdentifier: AppIdentifiers.appGroupIdentifier
|
|
) {
|
|
let storeURL = appGroupURL.appending(path: "BusinessCard.store")
|
|
container = makeContainer(storeURL: storeURL, cloudKitDatabase: cloudKitDatabase)
|
|
if container == nil {
|
|
Design.debugLog("Failed to create container in App Group.")
|
|
}
|
|
}
|
|
|
|
// Fallback: Default location (Application Support)
|
|
if container == nil {
|
|
let storeURL = URL.applicationSupportDirectory.appending(path: "BusinessCard.store")
|
|
container = makeContainer(storeURL: storeURL, cloudKitDatabase: cloudKitDatabase)
|
|
if container == nil {
|
|
Design.debugLog("Failed to create container in Application Support.")
|
|
}
|
|
}
|
|
|
|
// If CloudKit mode fails, force local-on-disk fallback before in-memory.
|
|
if container == nil && AppIdentifiers.isCloudKitSyncEnabled {
|
|
if let appGroupURL = FileManager.default.containerURL(
|
|
forSecurityApplicationGroupIdentifier: AppIdentifiers.appGroupIdentifier
|
|
) {
|
|
let storeURL = appGroupURL.appending(path: "BusinessCard.store")
|
|
container = makeContainer(storeURL: storeURL, cloudKitDatabase: .none)
|
|
if container == nil {
|
|
Design.debugLog("Failed to create local-only container in App Group.")
|
|
}
|
|
}
|
|
|
|
if container == nil {
|
|
let storeURL = URL.applicationSupportDirectory.appending(path: "BusinessCard.store")
|
|
container = makeContainer(storeURL: storeURL, cloudKitDatabase: .none)
|
|
if container == nil {
|
|
Design.debugLog("Failed to create local-only container in Application Support.")
|
|
}
|
|
}
|
|
}
|
|
|
|
// Last resort: In-memory (data won't persist but app will work)
|
|
if container == nil {
|
|
Design.debugLog("WARNING: Using in-memory store - data will not persist!")
|
|
let config = ModelConfiguration(
|
|
schema: schema,
|
|
isStoredInMemoryOnly: true,
|
|
cloudKitDatabase: .none
|
|
)
|
|
container = try? ModelContainer(for: schema, configurations: [config])
|
|
}
|
|
|
|
guard let container else {
|
|
fatalError("Failed to create ModelContainer with all strategies")
|
|
}
|
|
|
|
self.modelContainer = container
|
|
let context = container.mainContext
|
|
self._appState = State(initialValue: AppState(modelContext: context))
|
|
|
|
// Activate WatchConnectivity session
|
|
_ = WatchConnectivityService.shared
|
|
}
|
|
|
|
var body: some Scene {
|
|
WindowGroup {
|
|
ZStack {
|
|
// Base background matching launch screen - prevents white flash
|
|
Color.Branding.primary
|
|
.ignoresSafeArea()
|
|
|
|
AppLaunchView(config: .businessCard) {
|
|
RootTabView()
|
|
.environment(appState)
|
|
.preferredColorScheme(appState.preferredColorScheme)
|
|
}
|
|
}
|
|
}
|
|
.modelContainer(modelContainer)
|
|
}
|
|
}
|