110807d239
- Eating out: tap any empty slot → "Mark as eating out"; shows teal indicator, skipped by auto-assign, counts as complete, tap again to unmark - Rule violations panel: access via wand long-press context menu when conflicts exist; shows all isRuleOverridden slots with Fix (clear) or Ignore (acknowledge) actions - Firebase Crashlytics integrated: CrashlyticsService + dSYM upload build phase, isPremium property tracked per session - PremiumSyncService: extracted premium state machine, StoreKit Transaction.updates listener, isPremium no longer synced via iCloud to avoid stale state - StoreManager: analytics on purchase/restore, bundle ID fallback for product ID lookup - Search bar contrast bug fixed: TextField now has explicit foreground color for dark mode - WelcomeStepView: redesigned onboarding welcome screen with week preview - Version bump: 1.0.5 build 22 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
56 lines
2.1 KiB
Swift
56 lines
2.1 KiB
Swift
import Foundation
|
|
import WidgetKit
|
|
|
|
struct TodayMealData: Codable {
|
|
let lunch: String?
|
|
let dinner: String?
|
|
let lunchLabel: String
|
|
let dinnerLabel: String
|
|
let weekdayName: String
|
|
let updatedAt: Date
|
|
}
|
|
|
|
enum WidgetDataStore {
|
|
static let appGroupID = "group.com.alexandrevazquez.mealmood"
|
|
private static let key = "mealmood.today_meals"
|
|
|
|
static func update(plan: WeekPlan?, dishes: [Dish], settings: AppSettings) {
|
|
let today = Date()
|
|
let weekday = Calendar.current.component(.weekday, from: today)
|
|
// weekday: 1=Sun,2=Mon..7=Sat → appDayOfWeek: 0=Mon..6=Sun
|
|
let appDayOfWeek = (weekday + 5) % 7
|
|
|
|
let lunchId = plan?.slots.first { $0.dayOfWeek == appDayOfWeek && $0.mealType == MealType.lunch.rawValue }?.dishId
|
|
let dinnerId = plan?.slots.first { $0.dayOfWeek == appDayOfWeek && $0.mealType == MealType.dinner.rawValue }?.dishId
|
|
|
|
let lunch = lunchId.flatMap { id in dishes.first { $0.id == id }?.name }
|
|
let dinner = dinnerId.flatMap { id in dishes.first { $0.id == id }?.name }
|
|
|
|
let locale = Locale(identifier: settings.languageEnum.resolved().localeIdentifier)
|
|
let formatter = DateFormatter()
|
|
formatter.locale = locale
|
|
formatter.dateFormat = "EEEE"
|
|
let weekdayName = formatter.string(from: today).capitalized(with: locale)
|
|
|
|
let data = TodayMealData(
|
|
lunch: lunch,
|
|
dinner: dinner,
|
|
lunchLabel: String(localized: "lunch"),
|
|
dinnerLabel: String(localized: "dinner"),
|
|
weekdayName: weekdayName,
|
|
updatedAt: today
|
|
)
|
|
|
|
guard let defaults = UserDefaults(suiteName: appGroupID),
|
|
let encoded = try? JSONEncoder().encode(data) else { return }
|
|
defaults.set(encoded, forKey: key)
|
|
WidgetCenter.shared.reloadAllTimelines()
|
|
}
|
|
|
|
static func read() -> TodayMealData? {
|
|
guard let defaults = UserDefaults(suiteName: appGroupID),
|
|
let data = defaults.data(forKey: key) else { return nil }
|
|
return try? JSONDecoder().decode(TodayMealData.self, from: data)
|
|
}
|
|
}
|