Add category and recipe sorting with multiple modes and order inversion

Categories on the main page can be sorted by Recently Used, Alphabetical,
or Manual (drag-to-reorder). The sort menu appears inline next to the
Categories header. All Recipes is included in the sort order and manual
reorder sheet. Recipes within category and all-recipes lists can be sorted
by Recently Added or Alphabetical, with the sort button in the toolbar.
All non-manual sort modes support order inversion via a Reverse/Default
Order toggle. Date parsing handles both formatted strings and Unix
timestamps, with recipe_id as fallback when dates are unavailable.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-15 07:46:23 +01:00
parent fb6b16c1fc
commit 5307b502e9
10 changed files with 694 additions and 48 deletions

View File

@@ -18,6 +18,8 @@ import UIKit
@Published var timers: [String: RecipeTimer] = [:]
@Published var categoryImages: [String: UIImage] = [:]
@Published var recentRecipes: [Recipe] = []
@Published var categoryAccessDates: [String: Date] = [:]
@Published var manualCategoryOrder: [String] = []
var recipeImages: [Int: [String: UIImage]] = [:]
var imagesNeedUpdate: [Int: [String: Bool]] = [:]
var lastUpdates: [String: Date] = [:]
@@ -347,6 +349,34 @@ import UIKit
dataStore.delete(path: "recent_recipes.data")
}
// MARK: - Category sorting
func trackCategoryAccess(_ categoryName: String) {
categoryAccessDates[categoryName] = Date()
Task {
await saveLocal(categoryAccessDates, path: "category_access_dates.data")
}
}
func loadCategoryAccessDates() async {
if let loaded: [String: Date] = await loadLocal(path: "category_access_dates.data") {
self.categoryAccessDates = loaded
}
}
func updateManualCategoryOrder(_ order: [String]) {
manualCategoryOrder = order
Task {
await saveLocal(manualCategoryOrder, path: "manual_category_order.data")
}
}
func loadManualCategoryOrder() async {
if let loaded: [String] = await loadLocal(path: "manual_category_order.data") {
self.manualCategoryOrder = loaded
}
}
// MARK: - Data management
func deleteAllData() {