# Plan Complet de Correction des Bugs - Memento/Keep **Date:** 2026-01-15 **Version:** 1.0 **Statut:** Prêt pour correction --- ## RÉSUMÉ EXÉCUTIF **Bugs Critiques Confirmés par Tests Playwright:** 3 **Bugs Critiques Identifiés par Analyse de Code:** 5 **Bugs High Priorité:** 0 **Total Bugs à Corriger:** 8 --- ## PRIORITÉS DE CORRECTION ### 🔴 CRITIQUE (Doit être corrigé immédiatement) 1. **TriggerRefresh ne fonctionne pas** - Confirmé par tests 2. **Refresh excessif router.refresh()** - Cause flash et perte de scroll 3. **Reload complet window.location.reload()** - Force page reload complète 4. **Mobile drag non fonctionnel** - Muuri incompatible avec touch ### 🟡 HIGH (Corriger rapidement) 5. **Doublons boutons fermeture** - Confusion UI 6. **Performance re-renders** - useEffect mal gérés --- ## DÉTAIL DES CORRECTIONS PAR BUG ### 🔴 Bug #1: triggerRefresh() Non Fonctionnel **Confirmation par tests:** - `bug-move-direct.spec.ts` ligne 168-174 - `bug-note-move-refresh.spec.ts` ligne 105-109, 123-136 - Les tests confirment: "triggerRefresh() didn't work!" **Cause Racine:** ```typescript // keep-notes/context/NoteRefreshContext.tsx const NoteRefreshContext = createContext(undefined) export function NoteRefreshProvider({ children }: { children: React.ReactNode }) { const [refreshKey, setRefreshKey] = useState(0) const triggerRefresh = useCallback(() => { setRefreshKey(prev => prev + 1) // ❌ INCORRECT! Ne déclenche pas de re-render global }, [refreshKey]) // ❌ DÉPENDANCE INCORRECT! return ( {children} ) } ``` **Correction:** ```typescript // CORRECT: utiliser useRef pour éviter les cycles de dépendances export function NoteRefreshProvider({ children }: { children: React.ReactNode }) { const [refreshKey, setRefreshKey] = useState(0) const refreshKeyRef = useRef(refreshKey) const triggerRefresh = useCallback(() => { const newKey = refreshKeyRef.current + 1 refreshKeyRef.current = newKey setRefreshKey(newKey) // ✅ Déclenche le re-render }, []) // ✅ Pas de dépendances return ( {children} ) } ``` **Fichiers à modifier:** - `keep-notes/context/NoteRefreshContext.tsx` --- ### 🔴 Bug #2: router.refresh() Excessif **Fichiers affectés:** - `keep-notes/components/note-card.tsx` (lignes 200, 208, 216, 224, 235) - `keep-notes/app/(main)/page.tsx` (lignes 171, 185) **Cause Racine:** ```typescript // Chaque action déclenche un refresh complet de la page const handleTogglePin = async () => { startTransition(async () => { addOptimisticNote({ isPinned: !note.isPinned }) await togglePin(note.id, !note.isPinned) router.refresh() // ❌ FORCE RELOAD COMPLET }) } ``` **Correction:** ```typescript // CORRECT: Supprimer router.refresh() et laisser le state React se mettre à jour const handleTogglePin = async () => { addOptimisticNote({ isPinned: !note.isPinned }) await togglePin(note.id, !note.isPinned) // ✅ Pas de refresh - l'état optimiste gère l'UI } ``` **Fichiers à modifier:** - `keep-notes/components/note-card.tsx` - `keep-notes/app/(main)/page.tsx` --- ### 🔴 Bug #3: window.location.reload() dans notebooks-context.tsx **Fichier affecté:** - `keep-notes/context/notebooks-context.tsx` (lignes 141, 154, 169) **Cause Racine:** ```typescript // Création, mise à jour, suppression de notebook déclenche un reload complet const updateNotebook = async (notebookId: string, data: UpdateNotebookInput) => { const response = await fetch(`/api/notebooks/${notebookId}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }) if (!response.ok) { throw new Error('Failed to update notebook') } // Recharger les notebooks après mise à jour window.location.reload() // ❌ FORCE RELOAD COMPLET } ``` **Correction:** ```typescript // CORRECT: Utiliser triggerRefresh() à la place const updateNotebook = async (notebookId: string, data: UpdateNotebookInput) => { const response = await fetch(`/api/notebooks/${notebookId}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }) if (!response.ok) { throw new Error('Failed to update notebook') } // ✅ Rafraîchissement optimiste du state React triggerRefresh() } ``` **Fichiers à modifier:** - `keep-notes/context/notebooks-context.tsx` --- ### 🔴 Bug #4: Mobile Drag Non Fonctionnel **Fichier affecté:** - `keep-notes/components/masonry-grid.tsx` (lignes 160-185) **Cause Racine:** ```typescript // Détection mobile insuffisante const isMobile = window.matchMedia('(pointer: coarse)').matches; // Configuration Muuri avec dragHandle qui conflict avec touch events const layoutOptions = { dragEnabled: true, dragHandle: '.muuri-drag-handle', // ❌ Problématique sur mobile dragContainer: document.body, dragStartPredicate: { distance: 10, delay: 0, }, // ... } ``` **Correction:** ```typescript // CORRECT 1: Désactiver drag sur mobile const isMobile = window.innerWidth < 768; // ✅ Détection fiable const isTouchDevice = 'ontouchstart' in window; // ✅ Détection fiable const layoutOptions = { dragEnabled: !isMobile && !isTouchDevice, // ✅ Désactiver sur mobile dragHandle: isMobile ? undefined : '.muuri-drag-handle', // ✅ Pas de handle sur mobile // ... } ``` **Correction Alternative (Recommandée):** ```typescript // CORRECT 2: Utiliser @dnd-kit/core qui supporte nativement le touch // Remplacer Muuri par @dnd-kit/core import { DndContext, DndProvider } from '@dnd-kit/core' // Ceci résoudra définitivement les problèmes de mobile drag ``` **Fichiers à modifier:** - `keep-notes/components/masonry-grid.tsx` - Éventuellement: `package.json` (si changement de librairie) --- ### 🟡 Bug #5: Doublons Boutons Fermeture **Fichier affecté:** - `keep-notes/components/note-card.tsx` (lignes 351-357, 411-413) **Cause Racine:** ```typescript // Bouton "Leave Share" avec icône X // Bouton "Remove Fused Badge" avec icône X ``` **Correction:** ```typescript // CORRECT: Utiliser des icônes différentes pour chaque action import { X, Trash2, FolderOpen, LogOut } from 'lucide-react' // Bouton "Remove Fused Badge" - utiliser icône différente // Bouton "Leave Share" - utiliser icône différente ``` **Fichiers à modifier:** - `keep-notes/components/note-card.tsx` --- ### 🟡 Bug #6: Re-renders Inutiles (Performance) **Fichiers affectés:** - `keep-notes/components/note-card.tsx` (lignes 151-154, 162-180) - `keep-notes/hooks/use-debounce.ts` (lignes 6-14) **Cause Racine #1: useDebounce mal implémenté** ```typescript export function useDebounce(value: T, delay: number): T { const [debouncedValue, setDebouncedValue] = useState(value) useEffect(() => { const timer = setTimeout(() => { setDebouncedValue(value) }, delay) return () => { clearTimeout(timer) } }, [value, delay]) // ❌ Recrée l'effet à chaque render // ❌ Même si value ne change pas, l'effet se recrée // ❌ Provoque des cascades de re-renders return debouncedValue } ``` **Cause Racine #2: useEffect mal géré** ```typescript useEffect(() => { const loadCollaborators = async () => { // ... } loadCollaborators() }, [note.id, note.userId]) // ❌ Se déclenche trop souvent // ❌ Même si les collaborateurs n'ont pas changé // ❌ Provoque des cascades de re-renders ``` **Correction #1:** ```typescript export function useDebounce(value: T, delay: number): T { const [debouncedValue, setDebouncedValue] = useState(value) const timerRef = useRef() useEffect(() => { if (timerRef.current) { clearTimeout(timerRef.current) } timerRef.current = setTimeout(() => { setDebouncedValue(value) }, delay) return () => { if (timerRef.current) { clearTimeout(timerRef.current) } } }, [value, delay]) // ✅ Recrée uniquement quand value change return debouncedValue } ``` **Correction #2:** ```typescript useEffect(() => { const loadCollaborators = async () => { // ... } loadCollaborators() }, [note.id, note.userId, isOwner, isSharedNote]) // ✅ Dépendances complètes // ✅ Se déclenche uniquement quand une de ces valeurs change vraiment ``` **Fichiers à modifier:** - `keep-notes/hooks/use-debounce.ts` - `keep-notes/components/note-card.tsx` --- ## ORDRE DES CORRECTIONS RECOMMANDÉ ### Phase 1: Critique (Doit être corrigé immédiatement) 1. **Corriger triggerRefresh()** - Bug #1 2. **Supprimer router.refresh()** - Bug #2 3. **Supprimer window.location.reload()** - Bug #3 4. **Corriger mobile drag** - Bug #4 ### Phase 2: High (Corriger rapidement) 5. **Doublons boutons** - Bug #5 6. **Performance re-renders** - Bug #6 ### Phase 3: Validation (Tests) 7. **Rejouer tous les tests** pour confirmer les corrections 8. **Tests manuels** pour vérifier chaque bug corrigé --- ## INSTRUCTIONS D'EXÉCUTION ### Étape 1: Sauvegarder l'état actuel ```bash git add . git commit -m "Backup avant correction des bugs" ``` ### Étape 2: Corriger Bug #1 (triggerRefresh) **Fichier:** `keep-notes/context/NoteRefreshContext.tsx` 1. Remplacer l'implémentation actuelle 2. Tester avec les tests Playwright existants 3. Confirmer que triggerRefresh fonctionne ### Étape 3: Corriger Bug #2 (router.refresh excessif) **Fichiers:** - `keep-notes/components/note-card.tsx` - `keep-notes/app/(main)/page.tsx` 1. Supprimer tous les appels à `router.refresh()` 2. Laisser l'état optimiste gérer l'UI 3. Tester que les actions se font sans refresh ### Étape 4: Corriger Bug #3 (window.location.reload()) **Fichier:** `keep-notes/context/notebooks-context.tsx` 1. Remplacer tous les `window.location.reload()` par `triggerRefresh()` 2. Tester que les actions sur notebooks se font sans reload complet ### Étape 5: Corriger Bug #4 (Mobile drag) **Fichier:** `keep-notes/components/masonry-grid.tsx` **Option A (Simple):** 1. Désactiver drag sur mobile 2. Améliorer la détection mobile **Option B (Recommandée):** 1. Remplacer Muuri par @dnd-kit/core 2. Implémenter un drag handler mobile-friendly ### Étape 6: Corriger Bug #5 (Doublons boutons) **Fichier:** `keep-notes/components/note-card.tsx` 1. Remplacer les icônes X par des icônes spécifiques 2. Ajouter des tooltips explicites 3. Utiliser des couleurs sémantiques ### Étape 7: Corriger Bug #6 (Performance) **Fichiers:** - `keep-notes/hooks/use-debounce.ts` - `keep-notes/components/note-card.tsx` 1. Corriger useDebounce avec useRef 2. Corriger les dépendances useEffect 3. Utiliser useMemo pour éviter les recréations ### Étape 8: Validation ```bash # Rejouer tous les tests npx playwright test tests/bug-*.spec.ts # Tests manuels 1. Ouvrir l'application 2. Créer une note 3. Toggle pin, archive, color 4. Vérifier: pas de flash, pas de perte de scroll 5. Déplacer la note vers un notebook 6. Vérifier: la note disparaît de la page principale 7. Sur mobile: tester le drag and drop 8. Vérifier: pas de bugs de scroll sur mobile ``` --- ## CRITÈRES DE VALIDATION ### Pour chaque bug corrigé: - ✅ Le bug ne se produit plus - ✅ Aucun effet secondaire indésirable - ✅ Les tests Playwright passent - ✅ Performance améliorée (mesurable) - ✅ Code propre et bien documenté ### Pour l'application entière: - ✅ Aucun flash d'écran inutile - ✅ Aucune perte de scroll - ✅ Drag and drop fonctionne sur desktop - ✅ Drag and drop fonctionne/ou est désactivé proprement sur mobile - ✅ Toutes les actions UI sont optimistes - ✅ L'UI reste réactive sans re-renders inutiles --- ## SUITE APRÈS CORRECTIONS ### Améliorations UX: 1. **Animations fluides** lors des actions 2. **Feedback visuel** (loading states, success toasts) 3. **Indicateurs de progression** pour les actions longues 4. **Undo/Redo** pour les actions destructrices ### Améliorations Mobile: 1. **Touch gestures** pour swipe actions 2. **Pull-to-refresh** pour synchronisation 3. **Double-tap** pour quick actions 4. **Responsive design** amélioré ### Améliorations Techniques: 1. **Optimisation des re-renders** (React.memo, useMemo, useCallback) 2. **Lazy loading** des composants lourds 3. **Virtual scrolling** pour les grandes listes de notes 4. **Code splitting** pour réduire la taille du bundle --- ## RISQUES ET ATTENTIONS ### Risques: - **Casser des fonctionnalités existantes** en modifiant le state - **Introduction de nouveaux bugs** pendant la correction - **Régression** de bugs déjà corrigés ### Atténuations: - Faire les corrections une par une avec validation - Commencer par les bugs critiques les plus simples - Tester minutieusement après chaque correction - Avoir un plan de rollback prêt --- ## DOCUMENTS DE RÉFÉRENCE - Analyse complète: `_bmad-output/BUG-ANALYSIS-REPORT.md` - Tests Playwright: `keep-notes/tests/bug-*.spec.ts` - Documentation existante: `docs/` (à mettre à jour après corrections) --- ## TIMELINE ESTIMÉE **Phase 1 (Critique):** 2-4 heures **Phase 2 (High):** 1-2 heures **Phase 3 (Validation):** 1-2 heures **Total estimé:** 4-8 heures **Note:** Les corrections sont relativement simples car les bugs sont bien localisés et documentés. --- ## STATUT **État:** ✅ Prêt pour l'exécution **Fichiers à modifier:** 6 fichiers principaux **Bugs à corriger:** 8 **Tests à rejouer:** 3 tests Playwright --- *Ce plan doit être exécuté après validation par le développeur.*