c0b485387d
- Target MealMoodWatch (watchOS 10, SwiftUI): vista de hoy y de la semana en TabView vertical; recibe el snapshot del iPhone por WatchConnectivity (updateApplicationContext) y lo guarda en su app group para la complicacion - Target MealMoodWatchWidget: complicacion accessoryRectangular/ Circular/Inline con las comidas de hoy (heuristica comida/cena por hora); icono del watch generado desde el logo - WatchWeekPayload compartido entre iOS app, widget iOS, watch app y complicacion — llega ya localizado desde el iPhone - Widget iOS nuevo "Semana" (systemMedium/Large) con los 7 dias; el widget de hoy pasa a WidgetBundle - Targets creados via gema xcodeproj (sin abrir Xcode); embed del watch antes del script de Crashlytics para evitar ciclo de build Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013H6bXqGX1ygwib1Dm3n3UG
54 lines
1.9 KiB
Swift
54 lines
1.9 KiB
Swift
import Foundation
|
||
|
||
/// Snapshot of the week the iPhone pushes to the Watch (WatchConnectivity) and
|
||
/// the watch widget reads from the watch-side app group. Labels and day titles
|
||
/// arrive already localized — the watch never formats, only renders.
|
||
/// Member of the iOS app, watch app and watch widget targets.
|
||
struct WatchWeekPayload: Codable {
|
||
struct Meal: Codable {
|
||
let type: String // MealType rawValue, for the icon
|
||
let label: String // localized ("Comida", "Cena"…)
|
||
let name: String? // dish (+ secondary), "Comer fuera", or nil if empty
|
||
}
|
||
|
||
struct Day: Codable {
|
||
let dayOfWeek: Int // 0=Monday … 6=Sunday
|
||
let title: String // localized short title ("Lun 8")
|
||
let isToday: Bool
|
||
let meals: [Meal]
|
||
}
|
||
|
||
let weekTitle: String // localized week range ("8 – 14 sep")
|
||
let days: [Day]
|
||
let updatedAt: Date
|
||
|
||
static let appGroupID = "group.com.alexandrevazquez.mealmood"
|
||
static let storageKey = "watch_week_payload_v1"
|
||
|
||
func encoded() -> Data? { try? JSONEncoder().encode(self) }
|
||
|
||
static func decode(_ data: Data) -> WatchWeekPayload? {
|
||
try? JSONDecoder().decode(WatchWeekPayload.self, from: data)
|
||
}
|
||
|
||
/// Reads the last snapshot stored on this device's app group.
|
||
static func stored() -> WatchWeekPayload? {
|
||
guard let data = UserDefaults(suiteName: appGroupID)?.data(forKey: storageKey) else { return nil }
|
||
return decode(data)
|
||
}
|
||
|
||
func store() {
|
||
UserDefaults(suiteName: Self.appGroupID)?.set(encoded(), forKey: Self.storageKey)
|
||
}
|
||
|
||
static func icon(for mealType: String) -> String {
|
||
switch mealType {
|
||
case "breakfast": return "cup.and.saucer.fill"
|
||
case "lunch": return "sun.max.fill"
|
||
case "snack": return "carrot.fill"
|
||
case "dinner": return "moon.stars.fill"
|
||
default: return "fork.knife"
|
||
}
|
||
}
|
||
}
|