Le widget ne passait pas minuit : personne ne lisait updatedAt
Signale par Sylvain le 2026-08-18 : passe minuit, l'hydratation, les calories et la seance de la veille restaient affichees comme celles du jour. Il fallait ouvrir l'app pour les voir retomber a zero. Le widget n'a AUCUN acces reseau : il rend ce que l'app lui a pousse la derniere fois qu'elle a tourne. Le snapshot portait deja `updatedAt` — rien ne le lisait. CoachQuickWidget programmait meme un reveil a minuit, avec le bon commentaire, mais relisait ensuite les memes chiffres sans regarder leur date : le rechargement avait lieu, la remise a zero non. - `CoachWidgetSnapshot.asOf(_:)` : vide ce qui decrit UNE journee (eau, cafes, kcal, routine, activite faite, score de forme) quand le snapshot date d'un autre jour. Conserve ce qui traverse les jours — objectifs et zones cardiaques. Les compteurs repartent a 0 et non a nil : au matin, « rien bu » est vrai, « je ne sais pas » ne l'est pas. - Les trois providers emettent une 2e entree datee de minuit. WidgetKit bascule seul, sans reveiller l'app. - `tomorrow` : la seance du lendemain, poussee par le pont web. Sans elle, vider la seance ferait annoncer JOUR OFF chaque nuit — l'agacement d'un incident precedent, repete tous les jours. ⚠️ Deuxieme occurrence trouvee en verifiant, et pire : CoachQuickSync.credit() ajoutait au total EXISTANT puis rehorodatait a maintenant. Sur un snapshot de la veille, 200 ml bus le matin donnaient « 2 200 ml » estampilles du jour — un total faux, que la peremption ne pouvait plus rattraper. ⚠️ NON COMPILE : pas de toolchain Swift ici. Build Xcode requis sur le Mac mini pour que le correctif arrive sur l'iPhone et la Watch.
This commit is contained in:
@@ -95,18 +95,25 @@ enum CoachQuickLog {
|
||||
/// snapshot) ; on y ajoute ce qui attend encore. Sans cela, le widget
|
||||
/// afficherait un total périmé juste après une saisie, et l'utilisateur
|
||||
/// douterait de ce qu'il vient de faire.
|
||||
static func todayTotal(kind ref: String, syncedMl: Double = 0) -> Double {
|
||||
/// ⚠️ **`day` est explicite, et ce n'est pas de la coquetterie.**
|
||||
///
|
||||
/// Ces deux fonctions filtraient sur `isDateInToday`, c'est-à-dire sur
|
||||
/// l'instant du CALCUL. Or un widget construit sa timeline à l'avance :
|
||||
/// l'entrée datée de minuit est fabriquée la veille au soir, et « today »
|
||||
/// y désignait encore la veille. La file locale se serait donc réinitialisée
|
||||
/// avec un jour de retard, comme les totaux serveur.
|
||||
static func todayTotal(kind ref: String, syncedMl: Double = 0, day: Date = Date()) -> Double {
|
||||
let calendar = Calendar.current
|
||||
let waiting = pending()
|
||||
.filter { $0.kind == .drink && $0.ref == ref && calendar.isDateInToday($0.at) }
|
||||
.filter { $0.kind == .drink && $0.ref == ref && calendar.isDate($0.at, inSameDayAs: day) }
|
||||
.reduce(0) { $0 + $1.amount }
|
||||
return syncedMl + waiting
|
||||
}
|
||||
|
||||
static func todayCount(kind ref: String, syncedCount: Int = 0) -> Int {
|
||||
static func todayCount(kind ref: String, syncedCount: Int = 0, day: Date = Date()) -> Int {
|
||||
let calendar = Calendar.current
|
||||
let waiting = pending()
|
||||
.filter { $0.kind == .drink && $0.ref == ref && calendar.isDateInToday($0.at) }
|
||||
.filter { $0.kind == .drink && $0.ref == ref && calendar.isDate($0.at, inSameDayAs: day) }
|
||||
.count
|
||||
return syncedCount + waiting
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user