fix: refresh Android widget after sync push and pull (#65) #66

Merged
maximus merged 1 commit from issue-65-widget-sync-refresh into master 2026-04-09 13:37:07 +00:00
Owner

Fixes #65

Problème

Le sync client (syncClient.ts) écrit directement dans la DB via drizzle, contournant les fonctions du repository (tasks.ts) qui appellent normalement syncWidgetData(). Résultat : les changements venant du web ne rafraîchissaient jamais le widget Android.

Fix

  • Appel unique à syncWidgetData() à la fin de pullChanges() après application de tous les changements distants
  • Appel unique à syncWidgetData() après un pushChanges() réussi

Un seul appel par cycle de sync pour éviter le spam de mises à jour widget.

Test plan

  • Modifier le statut d'une tâche depuis le web → le widget mobile reflète le changement après le prochain pull
  • Modifier une tâche localement sur mobile → le widget continue d'être mis à jour comme avant
  • Aucune boucle infinie ou spam de refresh widget
Fixes #65 ## Problème Le sync client (`syncClient.ts`) écrit directement dans la DB via drizzle, contournant les fonctions du repository (`tasks.ts`) qui appellent normalement `syncWidgetData()`. Résultat : les changements venant du web ne rafraîchissaient jamais le widget Android. ## Fix - Appel unique à `syncWidgetData()` à la fin de `pullChanges()` après application de tous les changements distants - Appel unique à `syncWidgetData()` après un `pushChanges()` réussi Un seul appel par cycle de sync pour éviter le spam de mises à jour widget. ## Test plan - [ ] Modifier le statut d'une tâche depuis le web → le widget mobile reflète le changement après le prochain pull - [ ] Modifier une tâche localement sur mobile → le widget continue d'être mis à jour comme avant - [ ] Aucune boucle infinie ou spam de refresh widget
maximus added 1 commit 2026-04-09 13:03:34 +00:00
The sync client writes directly to the DB via drizzle, bypassing the
repository functions that normally trigger syncWidgetData(). As a
result, changes coming from the web (or any remote source) never
refreshed the home screen widget.

Call syncWidgetData() once at the end of pullChanges (after all remote
changes are applied) and after a successful pushChanges (to reflect
synced state). Single call per cycle avoids spamming widget updates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

Review — APPROVE

Resume

Correctif simple et cible qui ajoute deux appels a syncWidgetData() dans syncClient.ts — un apres un push reussi, un apres un pull ayant applique au moins un changement. Resout directement l'incoherence ou le widget Android ne refletait pas les changements venant du web, car le sync client ecrit directement via drizzle en contournant le repository qui appelle habituellement syncWidgetData().

Points positifs

  • Logique conforme a l'intent : un seul appel par cycle de sync, aucun risque de spam.
  • Guard appliedChanges > 0 dans pullChanges() evite les refreshs inutiles.
  • .catch(() => {}) fire-and-forget : coherent avec la nature non-critique du widget, ne bloque pas le flux de sync en cas d'erreur.
  • Cross-platform safe : syncWidgetData() est deja no-op sur iOS (Platform.OS !== 'android').
  • Pas de risque de boucle infinie : syncWidgetData() lit seulement depuis la DB et ecrit dans AsyncStorage, jamais dans les tables synchronisees — donc ne declenche pas d'outbox entry.
  • Pas de secret, pas de migration, pas de string user-facing (i18n N/A), pas de modification de schema.

Suggestions non bloquantes

  1. initialReset() appelle maintenant indirectement syncWidgetData() via pullChanges() — comportement correct et gratuit, juste a noter.
  2. A terme, typer pushChanges() en Promise<boolean> pourrait permettre au caller de savoir si un refresh a eu lieu, mais hors scope.

LGTM, pret a merger.

## Review — APPROVE ### Resume Correctif simple et cible qui ajoute deux appels a `syncWidgetData()` dans `syncClient.ts` — un apres un push reussi, un apres un pull ayant applique au moins un changement. Resout directement l'incoherence ou le widget Android ne refletait pas les changements venant du web, car le sync client ecrit directement via drizzle en contournant le repository qui appelle habituellement `syncWidgetData()`. ### Points positifs - **Logique conforme a l'intent** : un seul appel par cycle de sync, aucun risque de spam. - **Guard `appliedChanges > 0`** dans `pullChanges()` evite les refreshs inutiles. - **`.catch(() => {})` fire-and-forget** : coherent avec la nature non-critique du widget, ne bloque pas le flux de sync en cas d'erreur. - **Cross-platform safe** : `syncWidgetData()` est deja no-op sur iOS (`Platform.OS !== 'android'`). - **Pas de risque de boucle infinie** : `syncWidgetData()` lit seulement depuis la DB et ecrit dans AsyncStorage, jamais dans les tables synchronisees — donc ne declenche pas d'outbox entry. - Pas de secret, pas de migration, pas de string user-facing (i18n N/A), pas de modification de schema. ### Suggestions non bloquantes 1. `initialReset()` appelle maintenant indirectement `syncWidgetData()` via `pullChanges()` — comportement correct et gratuit, juste a noter. 2. A terme, typer `pushChanges()` en `Promise<boolean>` pourrait permettre au caller de savoir si un refresh a eu lieu, mais hors scope. LGTM, pret a merger.
maximus merged commit 1a1eddfd68 into master 2026-04-09 13:37:07 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/simpl-liste#66
No description provided.