ce88d7b265
- ShoppingItem model (per-week lines; dish-derived or free-text) + schema. - ShoppingListService.reconcile mirrors planned dishes' ingredients into the list, preserving check-off state and user items; plain-text export helper. - ShoppingListView: grouped by dish, check-off, swipe-delete, free-text adds, clear-checked, ShareLink export, and inline on-device "Generate" for planned dishes without ingredients (paywall after 3 free generations, source=ingredient_generation). - Home toolbar: cart entry point (all users) + sheet. - Analytics: shopping_list_opened, shopping_item_added, ingredients_generated. - Localized in all 6 languages. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BkanrydYtrme8wipTzWssG
51 lines
1.4 KiB
Swift
51 lines
1.4 KiB
Swift
import SwiftUI
|
|
import SwiftData
|
|
import FirebaseCore
|
|
import FirebaseCrashlytics
|
|
#if canImport(GoogleMobileAds)
|
|
import GoogleMobileAds
|
|
#endif
|
|
|
|
@main
|
|
struct MealMoodApp: App {
|
|
private let modelContainer: ModelContainer = {
|
|
let schema = Schema([
|
|
AppSettings.self,
|
|
Tag.self,
|
|
Dish.self,
|
|
WeekPlan.self,
|
|
MealSlot.self,
|
|
ShoppingItem.self
|
|
])
|
|
let configuration = ModelConfiguration(cloudKitDatabase: .none)
|
|
do {
|
|
return try ModelContainer(for: schema, configurations: [configuration])
|
|
} catch {
|
|
// Migration failed — reset the store to avoid a crash loop
|
|
let storeURL = configuration.url
|
|
for ext in ["", "-shm", "-wal"] {
|
|
try? FileManager.default.removeItem(at: URL(fileURLWithPath: storeURL.path + ext))
|
|
}
|
|
do {
|
|
return try ModelContainer(for: schema, configurations: [configuration])
|
|
} catch {
|
|
fatalError("Cannot create ModelContainer after reset: \(error)")
|
|
}
|
|
}
|
|
}()
|
|
|
|
init() {
|
|
FirebaseApp.configure()
|
|
#if canImport(GoogleMobileAds)
|
|
GADMobileAds.sharedInstance().start(completionHandler: nil)
|
|
#endif
|
|
}
|
|
|
|
var body: some Scene {
|
|
WindowGroup {
|
|
ContentView()
|
|
}
|
|
.modelContainer(modelContainer)
|
|
}
|
|
}
|