6.4 KiB
Fix de la Sauvegarde Excalidraw - Diagnostic et Solution
Problème Initial
- Bouton Sauvegarde ne déclenchait aucune requête réseau
- 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 :
ngAfterViewInit()s'exécute- Tente de binder les listeners sur
<excalidraw-editor> - Mais l'élément n'existe pas encore car il est derrière
*ngIf="!isLoading()" - Les listeners ne sont jamais attachés
- L'événement
scene-changen'est jamais capturé excalidrawReadyrestefalse- Les exports restent désactivés
Solution Implémentée
1. Binding au bon moment
Avant :
ngAfterViewInit(): void {
this.bindEditorHostListeners(); // ❌ Trop tôt
setTimeout(() => this.bindEditorHostListeners(), 0);
}
Après :
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 :
fromEvent<CustomEvent>(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
- Spinner de chargement
- GET
/api/files?path=tests.excalidraw.md 🎨 Excalidraw Ready - Binding listeners🔗 Binding Excalidraw host listeners- Indicateur : ⚫ Gris "Sauvegardé"
- Exports : activés
Pendant l'Édition
- Ajout d'un élément
📝 Scene changed- Indicateur : 🔴 Rouge "Non sauvegardé"
- Attente de 2 secondes
💾 Autosaving...- PUT
/api/files?path=... ✅ Autosave successful- Indicateur : ⚫ Gris "Sauvegardé"
Après Clic Sauvegarde
💾 Manual save triggered📤 Sending save request...- PUT
/api/files?path=... ✅ Manual save successful- Toast : "Sauvegarde réussie"
- 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) :
- Retirer les logs de debug dans
drawings-editor.component.ts - Tester la sauvegarde intensive (ajouter/supprimer rapidement des éléments)
- Tester les conflits (modifier le fichier externellement)
- Vérifier la performance (fichiers avec 100+ éléments)
- 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