bd8090c845
- El primer push se descartaba: updateApplicationContext se llamaba antes de que WCSession terminara de activarse (activacion asincrona). Ahora la sesion se activa al arrancar la app (ContentView), el payload pendiente se envia al completarse la activacion, y ademas el reloj PIDE los datos al abrirse (sendMessage despierta al iPhone en segundo plano y responde con el snapshot del app group) - Rediseno: Hoy con cabecera del dia en coral y tarjetas degradadas por comida (estilo Weather); Semana con circulo de dia a la izquierda y hoy relleno en coral (estilo Calendar); complicacion con iconos tintados por comida y widgetAccentable - Verificado con capturas en simulador de Watch sembrando el app group Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013H6bXqGX1ygwib1Dm3n3UG
79 lines
2.9 KiB
Swift
79 lines
2.9 KiB
Swift
import SwiftUI
|
|
|
|
/// Week page — Calendar-app style: day number in a circle on the left (today
|
|
/// filled in coral), meals with tinted icons on the right.
|
|
struct WeekView: View {
|
|
@EnvironmentObject private var store: WatchWeekStore
|
|
|
|
var body: some View {
|
|
Group {
|
|
if let payload = store.payload {
|
|
ScrollView {
|
|
VStack(alignment: .leading, spacing: 6) {
|
|
Text(payload.weekTitle)
|
|
.font(.system(.footnote, design: .rounded, weight: .bold))
|
|
.foregroundStyle(WatchTheme.coral)
|
|
.padding(.horizontal, 2)
|
|
|
|
ForEach(payload.days, id: \.dayOfWeek) { day in
|
|
DayRow(day: day)
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
EmptySyncView()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct DayRow: View {
|
|
let day: WatchWeekPayload.Day
|
|
|
|
/// "Lun 8" → ("Lun", "8")
|
|
private var parts: (name: String, number: String) {
|
|
let pieces = day.title.split(separator: " ", maxSplits: 1)
|
|
guard pieces.count == 2 else { return (day.title, "") }
|
|
return (String(pieces[0]), String(pieces[1]))
|
|
}
|
|
|
|
var body: some View {
|
|
HStack(alignment: .top, spacing: 8) {
|
|
VStack(spacing: 0) {
|
|
Text(parts.name.uppercased())
|
|
.font(.system(size: 9, weight: .bold, design: .rounded))
|
|
.foregroundStyle(day.isToday ? WatchTheme.coral : .secondary)
|
|
Text(parts.number)
|
|
.font(.system(size: 15, weight: .bold, design: .rounded))
|
|
.foregroundStyle(day.isToday ? .white : .primary)
|
|
.frame(width: 26, height: 26)
|
|
.background(
|
|
Circle().fill(day.isToday ? WatchTheme.coral : .clear)
|
|
)
|
|
}
|
|
.frame(width: 32)
|
|
|
|
VStack(alignment: .leading, spacing: 3) {
|
|
ForEach(Array(day.meals.enumerated()), id: \.offset) { _, meal in
|
|
HStack(spacing: 4) {
|
|
Image(systemName: WatchWeekPayload.icon(for: meal.type))
|
|
.font(.system(size: 9, weight: .semibold))
|
|
.foregroundStyle(WatchTheme.accent(for: meal.type))
|
|
.frame(width: 12)
|
|
Text(meal.name ?? "—")
|
|
.font(.system(size: 13, design: .rounded))
|
|
.lineLimit(1)
|
|
}
|
|
}
|
|
}
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.padding(.vertical, 5)
|
|
.padding(.horizontal, 7)
|
|
.background(
|
|
day.isToday ? WatchTheme.coral.opacity(0.16) : Color.white.opacity(0.07),
|
|
in: RoundedRectangle(cornerRadius: 9)
|
|
)
|
|
}
|
|
}
|
|
}
|