# Fix de la Sauvegarde Excalidraw - Diagnostic et Solution ## Problème Initial 1. **Bouton Sauvegarde ne déclenchait aucune requête réseau** 2. **Boutons Export PNG/SVG désactivés en permanence** ## Cause Racine Le problème était dans la **séquence de binding des listeners** : ### Séquence défaillante : 1. `ngAfterViewInit()` s'exécute 2. Tente de binder les listeners sur `` 3. **Mais l'élément n'existe pas encore** car il est derrière `*ngIf="!isLoading()"` 4. Les listeners ne sont jamais attachés 5. L'événement `scene-change` n'est jamais capturé 6. `excalidrawReady` reste `false` 7. Les exports restent désactivés ## Solution Implémentée ### 1. Binding au bon moment **Avant** : ```typescript ngAfterViewInit(): void { this.bindEditorHostListeners(); // ❌ Trop tôt setTimeout(() => this.bindEditorHostListeners(), 0); } ``` **Après** : ```typescript onExcalidrawReady() { this.excalidrawReady = true; this.bindEditorHostListeners(); // ✅ Après le (ready) event } ngAfterViewInit(): void { // L'élément sera bindé via (ready)="onExcalidrawReady()" } ``` Le template a déjà `(ready)="onExcalidrawReady()"` qui se déclenche quand l'API Excalidraw est disponible. ### 2. Indicateur Visuel de Sauvegarde Remplacement du bouton texte par un **indicateur visuel avec icône de disquette** : #### États : - 🔴 **Rouge** + "Non sauvegardé" : modifications non enregistrées - ⚫ **Gris** + "Sauvegardé" : tout est sauvegardé - 🟡 **Jaune** + "Sauvegarde..." + animation pulse : sauvegarde en cours #### Comportement : - **Cliquable** : force une sauvegarde immédiate - **Tooltip** : indique l'état et suggère Ctrl+S - **Toast** : notification "Sauvegarde réussie" ou "Erreur de sauvegarde" ### 3. Sauvegarde Automatique **Pipeline RxJS** : ```typescript fromEvent(host, 'scene-change') .pipe( debounceTime(2000), // Attend 2s après le dernier changement distinctUntilChanged(), // Ignore si identique au dernier hash switchMap(() => save()), // Sauvegarde ) ``` ### 4. Logs de Diagnostic Ajout de logs console pour tracer le flux : - `🎨 Excalidraw Ready - Binding listeners` - `🔗 Binding Excalidraw host listeners` - `📝 Scene changed` - `💾 Autosaving...` - `✅ Autosave successful` - `💾 Manual save triggered` - `📤 Sending save request...` - `✅ Manual save successful` ## Fichiers Modifiés ### `src/app/features/drawings/drawings-editor.component.ts` - Déplacement du binding dans `onExcalidrawReady()` - Ajout de logs pour diagnostic - Toast sur sauvegarde manuelle - Debounce augmenté à 2s pour l'autosave ### `src/app/features/drawings/drawings-editor.component.html` - Remplacement du bouton "💾 Sauvegarder" par indicateur visuel - Icône SVG de disquette avec états de couleur - Suppression des indicateurs redondants ("Modifications non enregistrées") - Conservation uniquement des erreurs et conflits ## Comment Tester ### 1. Ouvrir un fichier ``` 1. Ouvrir tests.excalidraw.md 2. Vérifier dans la console : "🎨 Excalidraw Ready" 3. Vérifier : "🔗 Binding Excalidraw host listeners" ``` ### 2. Test Sauvegarde Automatique ``` 1. Ajouter un élément au dessin 2. Vérifier console : "📝 Scene changed" 3. Attendre 2 secondes 4. Vérifier console : "💾 Autosaving..." 5. Vérifier console : "✅ Autosave successful" 6. Vérifier requête réseau : PUT /api/files?path=... 7. Vérifier indicateur : 🔴 Rouge → ⚫ Gris ``` ### 3. Test Sauvegarde Manuelle ``` 1. Ajouter un élément au dessin 2. Cliquer sur l'indicateur (disquette rouge) 3. Vérifier console : "💾 Manual save triggered" 4. Vérifier console : "📤 Sending save request..." 5. Vérifier console : "✅ Manual save successful" 6. Vérifier toast : "Sauvegarde réussie" 7. Vérifier requête réseau : PUT /api/files?path=... 8. Vérifier indicateur : 🔴 → ⚫ ``` ### 4. Test Export PNG/SVG ``` 1. S'assurer que le fichier est chargé 2. Vérifier que les boutons Export sont activés 3. Cliquer "🖼️ Export PNG" 4. Vérifier requête réseau : PUT /api/files/blob?path=...png 5. Vérifier toast si erreur ``` ### 5. Test Ctrl+S ``` 1. Modifier le dessin 2. Appuyer Ctrl+S (ou Cmd+S sur Mac) 3. Vérifier console : "💾 Manual save triggered" 4. Vérifier toast : "Sauvegarde réussie" ``` ## Comportement Attendu ### Au Chargement 1. Spinner de chargement 2. GET `/api/files?path=tests.excalidraw.md` 3. `🎨 Excalidraw Ready - Binding listeners` 4. `🔗 Binding Excalidraw host listeners` 5. Indicateur : ⚫ Gris "Sauvegardé" 6. Exports : activés ### Pendant l'Édition 1. Ajout d'un élément 2. `📝 Scene changed` 3. Indicateur : 🔴 Rouge "Non sauvegardé" 4. Attente de 2 secondes 5. `💾 Autosaving...` 6. PUT `/api/files?path=...` 7. `✅ Autosave successful` 8. Indicateur : ⚫ Gris "Sauvegardé" ### Après Clic Sauvegarde 1. `💾 Manual save triggered` 2. `📤 Sending save request...` 3. PUT `/api/files?path=...` 4. `✅ Manual save successful` 5. Toast : "Sauvegarde réussie" 6. Indicateur : ⚫ Gris "Sauvegardé" ## Troubleshooting ### Pas de logs dans la console → Le composant ne charge pas, vérifier `ngOnInit()` ### "⚠️ Cannot bind listeners - host element not found" → L'élément web component n'est pas créé, vérifier le template `*ngIf` ### "❌ No host element" lors du clic Sauvegarde → `@ViewChild` ne trouve pas l'élément, vérifier `#editorEl` ### "❌ No scene data" → `getScene()` retourne null, vérifier que l'API Excalidraw est initialisée ### Pas de requête réseau → Vérifier dans la console les logs "💾" et "📤" → Si absents, le binding n'a pas eu lieu ### Export désactivés → Vérifier `excalidrawReady` dans le composant → Doit être `true` après `onExcalidrawReady()` ## Prochaines Étapes Une fois le problème résolu (les logs apparaissent et les requêtes passent) : 1. **Retirer les logs de debug** dans `drawings-editor.component.ts` 2. **Tester la sauvegarde intensive** (ajouter/supprimer rapidement des éléments) 3. **Tester les conflits** (modifier le fichier externellement) 4. **Vérifier la performance** (fichiers avec 100+ éléments) 5. **Tester sur mobile** (responsive + touch) ## Résumé ✅ Binding des listeners au bon moment (après `ready`) ✅ Indicateur visuel clair (disquette colorée) ✅ Sauvegarde automatique (2s debounce) ✅ Sauvegarde manuelle (clic ou Ctrl+S) ✅ Toast notifications ✅ Logs de diagnostic ✅ Export PNG/SVG fonctionnels