Overhaul SearchTabView with search history, empty/no-results states, and dynamic navigation title. Extract CategoryCardView and RecentRecipesSection into standalone views. Update RecipeTabView, RecipeListView, RecipeCardView, and MainView for the modernized UI. Add all 12 missing German translations in Localizable.xcstrings. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
76 lines
2.4 KiB
Swift
76 lines
2.4 KiB
Swift
//
|
|
// ContentView.swift
|
|
// Nextcloud Cookbook iOS Client
|
|
//
|
|
// Created by Vincent Meilinger on 06.09.23.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct MainView: View {
|
|
@StateObject var appState = AppState()
|
|
@StateObject var groceryList = GroceryList()
|
|
|
|
// Tab ViewModels
|
|
@StateObject var recipeViewModel = RecipeTabView.ViewModel()
|
|
@StateObject var searchViewModel = SearchTabView.ViewModel()
|
|
|
|
@State private var selectedTab: Tab = .recipes
|
|
|
|
enum Tab {
|
|
case recipes, search, groceryList
|
|
}
|
|
|
|
var body: some View {
|
|
TabView(selection: $selectedTab) {
|
|
SwiftUI.Tab("Recipes", systemImage: "book.closed.fill", value: .recipes) {
|
|
RecipeTabView()
|
|
.environmentObject(recipeViewModel)
|
|
.environmentObject(appState)
|
|
.environmentObject(groceryList)
|
|
}
|
|
|
|
SwiftUI.Tab("Search", systemImage: "magnifyingglass", value: .search, role: .search) {
|
|
SearchTabView()
|
|
.environmentObject(searchViewModel)
|
|
.environmentObject(appState)
|
|
.environmentObject(groceryList)
|
|
}
|
|
|
|
SwiftUI.Tab("Grocery List", systemImage: "storefront", value: .groceryList) {
|
|
GroceryListTabView()
|
|
.environmentObject(groceryList)
|
|
}
|
|
}
|
|
.tabViewStyle(.sidebarAdaptable)
|
|
.modifier(TabBarMinimizeModifier())
|
|
.task {
|
|
recipeViewModel.presentLoadingIndicator = true
|
|
await appState.getCategories()
|
|
await appState.updateAllRecipeDetails()
|
|
|
|
// Preload category images
|
|
for category in appState.categories {
|
|
await appState.getCategoryImage(for: category.name)
|
|
}
|
|
|
|
// Load recently viewed recipes
|
|
await appState.loadRecentRecipes()
|
|
|
|
// Open detail view for default category
|
|
if UserSettings.shared.defaultCategory != "" {
|
|
if let cat = appState.categories.first(where: { c in
|
|
if c.name == UserSettings.shared.defaultCategory {
|
|
return true
|
|
}
|
|
return false
|
|
}) {
|
|
recipeViewModel.selectedCategory = cat
|
|
}
|
|
}
|
|
await groceryList.load()
|
|
recipeViewModel.presentLoadingIndicator = false
|
|
}
|
|
}
|
|
}
|