Add user-facing appearance setting (System/Light/Dark) wired via preferredColorScheme at the app root. Replace hardcoded .black tints and foreground styles with .primary so toolbar buttons and text remain visible in dark mode. Remove profile picture from settings and SwiftSoup from acknowledgements. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
105 lines
3.8 KiB
Swift
105 lines
3.8 KiB
Swift
//
|
|
// AllRecipesListView.swift
|
|
// Nextcloud Cookbook iOS Client
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct AllRecipesListView: View {
|
|
@EnvironmentObject var appState: AppState
|
|
@EnvironmentObject var groceryList: GroceryListManager
|
|
@EnvironmentObject var mealPlan: MealPlanManager
|
|
var onCreateNew: () -> Void
|
|
var onImportFromURL: () -> Void
|
|
@State private var allRecipes: [Recipe] = []
|
|
@State private var searchText: String = ""
|
|
|
|
private let gridColumns = [GridItem(.adaptive(minimum: 160), spacing: 12)]
|
|
|
|
var body: some View {
|
|
Group {
|
|
let recipes = recipesFiltered()
|
|
if !recipes.isEmpty {
|
|
ScrollView {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
Text("\(recipes.count) recipes")
|
|
.font(.subheadline)
|
|
.foregroundStyle(.secondary)
|
|
.padding(.horizontal)
|
|
|
|
LazyVGrid(columns: gridColumns, spacing: 12) {
|
|
ForEach(recipes, id: \.recipe_id) { recipe in
|
|
NavigationLink(value: recipe) {
|
|
RecipeCardView(recipe: recipe)
|
|
}
|
|
.buttonStyle(.plain)
|
|
}
|
|
}
|
|
.padding(.horizontal)
|
|
}
|
|
.padding(.vertical)
|
|
}
|
|
} else {
|
|
VStack(spacing: 16) {
|
|
Image(systemName: "fork.knife")
|
|
.font(.system(size: 48))
|
|
.foregroundStyle(.secondary)
|
|
Text("No recipes found")
|
|
.font(.headline)
|
|
.foregroundStyle(.secondary)
|
|
Button {
|
|
Task {
|
|
allRecipes = await appState.getRecipes()
|
|
}
|
|
} label: {
|
|
Label("Refresh", systemImage: "arrow.clockwise")
|
|
.bold()
|
|
}
|
|
.buttonStyle(.bordered)
|
|
.tint(.primary)
|
|
}.padding()
|
|
}
|
|
}
|
|
.searchable(text: $searchText, prompt: "Search recipes/keywords")
|
|
.navigationTitle(String(localized: "All Recipes"))
|
|
.navigationDestination(for: Recipe.self) { recipe in
|
|
RecipeView(viewModel: RecipeView.ViewModel(recipe: recipe))
|
|
.environmentObject(appState)
|
|
.environmentObject(groceryList)
|
|
.environmentObject(mealPlan)
|
|
}
|
|
.toolbar {
|
|
ToolbarItem(placement: .topBarTrailing) {
|
|
Menu {
|
|
Button {
|
|
onCreateNew()
|
|
} label: {
|
|
Label("Create New Recipe", systemImage: "square.and.pencil")
|
|
}
|
|
Button {
|
|
onImportFromURL()
|
|
} label: {
|
|
Label("Import from URL", systemImage: "link")
|
|
}
|
|
} label: {
|
|
Image(systemName: "plus.circle.fill")
|
|
}
|
|
}
|
|
}
|
|
.task {
|
|
allRecipes = await appState.getRecipes()
|
|
}
|
|
.refreshable {
|
|
allRecipes = await appState.getRecipes()
|
|
}
|
|
}
|
|
|
|
private func recipesFiltered() -> [Recipe] {
|
|
guard !searchText.isEmpty else { return allRecipes }
|
|
return allRecipes.filter { recipe in
|
|
recipe.name.lowercased().contains(searchText.lowercased()) ||
|
|
(recipe.keywords != nil && recipe.keywords!.lowercased().contains(searchText.lowercased()))
|
|
}
|
|
}
|
|
}
|