Add meal plan feature with cross-device sync and automatic stale data cleanup

Introduces weekly meal planning with a calendar-based tab view, per-recipe
date assignments synced via Nextcloud Cookbook custom metadata, and 30-day
automatic pruning of old entries on load, save, and sync merge.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-15 05:23:29 +01:00
parent 5890dbcad4
commit 8b23652f10
17 changed files with 1332 additions and 6 deletions

View File

@@ -10,6 +10,7 @@ import SwiftUI
struct MainView: View {
@StateObject var appState = AppState()
@StateObject var groceryList = GroceryListManager()
@StateObject var mealPlan = MealPlanManager()
// Tab ViewModels
@StateObject var recipeViewModel = RecipeTabView.ViewModel()
@@ -20,7 +21,7 @@ struct MainView: View {
@State private var selectedTab: Tab = .recipes
enum Tab {
case recipes, search, groceryList
case recipes, search, mealPlan, groceryList
}
var body: some View {
@@ -30,6 +31,7 @@ struct MainView: View {
.environmentObject(recipeViewModel)
.environmentObject(appState)
.environmentObject(groceryList)
.environmentObject(mealPlan)
}
SwiftUI.Tab("Search", systemImage: "magnifyingglass", value: .search, role: .search) {
@@ -37,6 +39,14 @@ struct MainView: View {
.environmentObject(searchViewModel)
.environmentObject(appState)
.environmentObject(groceryList)
.environmentObject(mealPlan)
}
SwiftUI.Tab("Meal Plan", systemImage: "calendar", value: .mealPlan) {
MealPlanTabView()
.environmentObject(mealPlan)
.environmentObject(appState)
.environmentObject(groceryList)
}
if userSettings.groceryListMode != GroceryListMode.appleReminders.rawValue {
@@ -85,6 +95,11 @@ struct MainView: View {
if UserSettings.shared.grocerySyncEnabled {
await groceryList.syncManager?.performInitialSync()
}
await mealPlan.load()
mealPlan.configureSyncManager(appState: appState)
if UserSettings.shared.mealPlanSyncEnabled {
await mealPlan.syncManager?.performInitialSync()
}
recipeViewModel.presentLoadingIndicator = false
}
}