watch: enviar la semana aunque todavia no este planificada

Faltaba la otra mitad del "no se actualiza": makePayload devolvia nil cuando la
semana en curso no tenia plan creado, asi que el iPhone no mandaba nada — ni
respondia cuando el reloj pedia datos — y el reloj se quedaba con el ultimo
snapshot, el del miercoles. Ahora la semana viaja igualmente, vacia, y el reloj
dice que no hay nada planificado en vez de enseñar lo de hace dias.

Ademas el reloj muestra cuando se actualizo por ultima vez. Sin eso, un
snapshot viejo y uno recien llegado se ven igual, y no hay forma de saber si
el problema es el envio o lo que se pinta.

Refs #34, #35

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013su1ttRiMeMYxkZJ1Y3246
This commit is contained in:
alexandrev-tibco
2026-09-12 16:32:34 +02:00
parent 649fe6d453
commit 4579b9bb69
10 changed files with 76 additions and 7 deletions
@@ -483,3 +483,4 @@
"watch_empty_meal" = "Nicht geplant";
"watch_empty_day" = "Für heute ist nichts geplant";
"watch_stale" = "Öffne MealMood auf dem iPhone, um diese Woche zu sehen";
"watch_updated" = "Aktualisiert";
@@ -483,3 +483,4 @@
"watch_empty_meal" = "Not planned";
"watch_empty_day" = "Nothing planned for today";
"watch_stale" = "Open MealMood on your iPhone to see this week";
"watch_updated" = "Updated";
@@ -483,3 +483,4 @@
"watch_empty_meal" = "Sin planificar";
"watch_empty_day" = "Hoy no hay nada planificado";
"watch_stale" = "Abre MealMood en el iPhone para ver esta semana";
"watch_updated" = "Actualizado";
@@ -483,3 +483,4 @@
"watch_empty_meal" = "Non planifié";
"watch_empty_day" = "Rien de prévu aujourd'hui";
"watch_stale" = "Ouvrez MealMood sur l'iPhone pour voir cette semaine";
"watch_updated" = "Mis à jour";
@@ -483,3 +483,4 @@
"watch_empty_meal" = "Non pianificato";
"watch_empty_day" = "Oggi non c'è niente di pianificato";
"watch_stale" = "Apri MealMood sull'iPhone per vedere questa settimana";
"watch_updated" = "Aggiornato";
@@ -483,3 +483,4 @@
"watch_empty_meal" = "Sem planejamento";
"watch_empty_day" = "Nada planejado para hoje";
"watch_stale" = "Abra o MealMood no iPhone para ver esta semana";
"watch_updated" = "Atualizado";
+14 -7
View File
@@ -46,7 +46,8 @@ final class WatchSyncService: NSObject, WCSessionDelegate, @unchecked Sendable {
let descriptor = FetchDescriptor<WeekPlan>(
predicate: #Predicate<WeekPlan> { plan in plan.weekStartDate == weekStart }
)
guard let plan = try? context.fetch(descriptor).first else { return nil }
// No plan for this week yet? Answer with the empty week anyway.
let plan = try? context.fetch(descriptor).first
let dishes = (try? context.fetch(FetchDescriptor<Dish>())) ?? []
return Self.makePayload(plan: plan, dishes: dishes, settings: settings)?.encoded()
@@ -67,8 +68,13 @@ final class WatchSyncService: NSObject, WCSessionDelegate, @unchecked Sendable {
try? WCSession.default.updateApplicationContext([WatchWeekPayload.storageKey: data])
}
/// Builds the snapshot for a week. A missing plan is NOT a reason to stay
/// quiet: without this the watch keeps whatever it had which is how it
/// went on showing Wednesday's dinner on Saturday. An empty week travels
/// too, and the watch says there's nothing planned.
static func makePayload(plan: WeekPlan?, dishes: [Dish], settings: AppSettings) -> WatchWeekPayload? {
guard let plan else { return nil }
let weekStart = plan?.weekStartDate ?? Date().startOfWeek()
let slots = plan?.slotList ?? []
let locale = Locale(identifier: settings.languageEnum.resolved().localeIdentifier)
let dishById = Dictionary(dishes.map { ($0.id, $0) }, uniquingKeysWith: { first, _ in first })
let dayFormatter = DateFormatter()
@@ -76,12 +82,12 @@ final class WatchSyncService: NSObject, WCSessionDelegate, @unchecked Sendable {
dayFormatter.setLocalizedDateFormatFromTemplate("EEE d")
let todayOffset = (Calendar.current.component(.weekday, from: Date()) + 5) % 7
let isCurrentWeek = plan.weekStartDate == Date().startOfWeek()
let isCurrentWeek = weekStart == Date().startOfWeek()
let schedule = settings.schedule(for: plan)
let days: [WatchWeekPayload.Day] = schedule.dayRange.map { day in
let meals: [WatchWeekPayload.Meal] = schedule.mealTypes.map { meal in
let slot = plan.slotList.first { $0.dayOfWeek == day && $0.mealType == meal.rawValue }
let slot = slots.first { $0.dayOfWeek == day && $0.mealType == meal.rawValue }
let label = String(localized: String.LocalizationValue(meal.localizedKey))
var name: String?
if let slot {
@@ -98,7 +104,7 @@ final class WatchSyncService: NSObject, WCSessionDelegate, @unchecked Sendable {
}
return WatchWeekPayload.Meal(type: meal.rawValue, label: label, name: name)
}
let dayDate = plan.weekStartDate.addingDays(day)
let dayDate = weekStart.addingDays(day)
return WatchWeekPayload.Day(
dayOfWeek: day,
title: dayFormatter.string(from: dayDate).capitalized(with: locale),
@@ -111,12 +117,13 @@ final class WatchSyncService: NSObject, WCSessionDelegate, @unchecked Sendable {
}
return WatchWeekPayload(
weekTitle: plan.weekStartDate.formattedWeekRange(),
weekTitle: weekStart.formattedWeekRange(),
days: days,
updatedAt: Date(),
emptyMealText: String(localized: "watch_empty_meal"),
emptyDayText: String(localized: "watch_empty_day"),
staleText: String(localized: "watch_stale")
staleText: String(localized: "watch_stale"),
updatedLabel: String(localized: "watch_updated")
)
}
+3
View File
@@ -56,6 +56,9 @@ struct WatchWeekPayload: Codable {
var emptyMealText: String?
var emptyDayText: String?
var staleText: String?
/// "Updated" shown next to `updatedAt` so it's visible at a glance when
/// the watch is holding an old snapshot.
var updatedLabel: String?
static let appGroupID = "group.com.alexandrevazquez.mealmood"
static let storageKey = "watch_week_payload_v1"