widget - afficher sous-taches est tres lents #71

Closed
opened 2026-04-19 13:52:41 +00:00 by maximus · 0 comments
Owner

Contexte

Quand l'utilisateur tape sur le bouton « expand » d'une tache dans le widget Android pour voir ses sous-taches, l'operation prend plusieurs secondes. Les sous-taches sont deja prechargees dans widget:state (cf. widgetSync.ts:176-186) — la lenteur n'est donc pas due a un fetch SQLite a chaud.

Trois sources de latence possibles :

  1. Cold start du service headless Android (suspicion principale de l'utilisateur)
  2. Round-trips AsyncStorage (read + write d'un JSON potentiellement gros)
  3. Debounce de 2s qui bloque les re-taps perçus comme « ne fait rien »

Travail a faire

  • Phase 1 — Mesurer : ajouter console.time / timeEnd autour de chaque etape du handler TOGGLE_EXPAND (entree handler, getWidgetState(), mutation, setWidgetState(), renderWithState()). Lancer un build dev sur appareil reel, taper expand, lire les logs via adb logcat. Confirmer ou va le temps.
  • Phase 2 — Optimiser selon les mesures : appliquer le pattern « render optimiste » aux 3 handlers (TOGGLE_EXPAND, TOGGLE_COMPLETE, TOGGLE_SUBTASK) — appeler renderWithState / renderWidget AVANT le await setWidgetState() (write async non-bloquant pour le rendu). Evaluer si le debounce 2s peut tomber a 300-500ms.
  • Phase 3 — Re-mesurer apres optimisation pour valider le gain.

Fichiers concernes

  • src/widgets/widgetTaskHandler.ts — instrumentation Phase 1 + render optimiste Phase 2 (handlers TOGGLE_EXPAND ligne 83-105, TOGGLE_COMPLETE ligne 65-81, TOGGLE_SUBTASK ligne 107-133)
  • src/services/widgetSync.ts — eventuellement separer expandedTaskIds dans son propre key AsyncStorage si Phase 2 montre que la serialisation JSON est le bottleneck

Surface de test

  • Tests existants touchant les fichiers : aucun (src/widgets/** n'a pas de tests)
  • Tests manquants identifies : aucun ajout requis (logique trop couplee a l'OS Android, difficilement unit-testable)
  • Test de regression manuel :
    1. Expand affiche les sous-taches en moins d'1s
    2. Toggle subtask coche bien dans la DB
    3. Double-tap accidentel ne replie pas immediatement (debounce court mais present)

Options

Option A — Quick win : render optimiste sur les 3 TOGGLE_*

  • Pros : simple, gain perceptible immediat (epargne le await setWidgetState), pas de risque de regression sur le format de stockage
  • Cons : ne regle pas le cold start OS si c'est la vraie cause

Option B — Split state : widget:expanded separe du widget:state

  • Pros : payload AsyncStorage ~10x plus petit pour les toggles, gain mesurable
  • Cons : plus complexe (2 sources de verite), migration a gerer, peut ne rien changer si le bottleneck est ailleurs

Option C — Non actionnable cote JS : cold start OS

  • Si Phase 1 montre que tout le temps part dans le cold start headless, on ne peut rien faire en JS. Solution : documenter et fermer.

Criteres d'acceptation

  • Logs de mesure publies (Phase 1) montrant la decomposition du temps par etape
  • Si optimisation possible : expand d'une tache < 1s sur appareil de reference apres le fix
  • Aucune regression sur TOGGLE_COMPLETE et TOGGLE_SUBTASK
  • Double-tap accidentel ne provoque pas un toggle/untoggle visible

Complexite estimee

Medium — Phase 1 (mesure) est simple. Phase 2 depend des resultats : Option A est simple, Option B est medium.

Decisions

  • Scope confirme : appliquer l'optimisation aux 3 TOGGLE_* (pas seulement TOGGLE_EXPAND) pour coherence
  • Demarche : mesurer d'abord (cold start suspecte), optimiser ensuite selon les chiffres
## Contexte Quand l'utilisateur tape sur le bouton « expand » d'une tache dans le widget Android pour voir ses sous-taches, l'operation prend plusieurs secondes. Les sous-taches sont deja prechargees dans `widget:state` (cf. `widgetSync.ts:176-186`) — la lenteur n'est donc pas due a un fetch SQLite a chaud. Trois sources de latence possibles : 1. Cold start du service headless Android (suspicion principale de l'utilisateur) 2. Round-trips AsyncStorage (read + write d'un JSON potentiellement gros) 3. Debounce de 2s qui bloque les re-taps perçus comme « ne fait rien » ## Travail a faire - [ ] **Phase 1 — Mesurer** : ajouter `console.time` / `timeEnd` autour de chaque etape du handler `TOGGLE_EXPAND` (entree handler, `getWidgetState()`, mutation, `setWidgetState()`, `renderWithState()`). Lancer un build dev sur appareil reel, taper expand, lire les logs via `adb logcat`. Confirmer ou va le temps. - [ ] **Phase 2 — Optimiser selon les mesures** : appliquer le pattern « render optimiste » aux 3 handlers (`TOGGLE_EXPAND`, `TOGGLE_COMPLETE`, `TOGGLE_SUBTASK`) — appeler `renderWithState` / `renderWidget` AVANT le `await setWidgetState()` (write async non-bloquant pour le rendu). Evaluer si le debounce 2s peut tomber a 300-500ms. - [ ] **Phase 3 — Re-mesurer** apres optimisation pour valider le gain. ## Fichiers concernes - `src/widgets/widgetTaskHandler.ts` — instrumentation Phase 1 + render optimiste Phase 2 (handlers `TOGGLE_EXPAND` ligne 83-105, `TOGGLE_COMPLETE` ligne 65-81, `TOGGLE_SUBTASK` ligne 107-133) - `src/services/widgetSync.ts` — eventuellement separer `expandedTaskIds` dans son propre key AsyncStorage si Phase 2 montre que la serialisation JSON est le bottleneck ## Surface de test - Tests existants touchant les fichiers : **aucun** (`src/widgets/**` n'a pas de tests) - Tests manquants identifies : aucun ajout requis (logique trop couplee a l'OS Android, difficilement unit-testable) - Test de regression manuel : 1. Expand affiche les sous-taches en moins d'1s 2. Toggle subtask coche bien dans la DB 3. Double-tap accidentel ne replie pas immediatement (debounce court mais present) ## Options **Option A — Quick win : render optimiste sur les 3 TOGGLE_*** - Pros : simple, gain perceptible immediat (epargne le `await setWidgetState`), pas de risque de regression sur le format de stockage - Cons : ne regle pas le cold start OS si c'est la vraie cause **Option B — Split state : `widget:expanded` separe du `widget:state`** - Pros : payload AsyncStorage ~10x plus petit pour les toggles, gain mesurable - Cons : plus complexe (2 sources de verite), migration a gerer, peut ne rien changer si le bottleneck est ailleurs **Option C — Non actionnable cote JS : cold start OS** - Si Phase 1 montre que tout le temps part dans le cold start headless, on ne peut rien faire en JS. Solution : documenter et fermer. ## Criteres d'acceptation - [ ] Logs de mesure publies (Phase 1) montrant la decomposition du temps par etape - [ ] Si optimisation possible : expand d'une tache < 1s sur appareil de reference apres le fix - [ ] Aucune regression sur TOGGLE_COMPLETE et TOGGLE_SUBTASK - [ ] Double-tap accidentel ne provoque pas un toggle/untoggle visible ## Complexite estimee **Medium** — Phase 1 (mesure) est simple. Phase 2 depend des resultats : Option A est simple, Option B est medium. ## Decisions - Scope confirme : appliquer l'optimisation aux 3 TOGGLE_* (pas seulement TOGGLE_EXPAND) pour coherence - Demarche : mesurer d'abord (cold start suspecte), optimiser ensuite selon les chiffres
maximus added the
status:ready
type:bug
labels 2026-04-19 20:13:53 +00:00
maximus added
status:review
and removed
status:ready
labels 2026-04-19 20:18:38 +00:00
maximus added
status:approved
and removed
status:review
labels 2026-04-19 20:21:08 +00:00
Sign in to join this conversation.
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#71
No description provided.