ObsiViewer/docs/TRASH/TRASH_FIX_SUMMARY.md

5.5 KiB

Correctif Trash Explorer - Résumé Technique

Problème Initial

La section Trash n'affichait pas l'arborescence du dossier .trash et ne permettait pas de cliquer sur un dossier pour charger ses notes dans la liste.

Causes Identifiées

1. Bouton accordion Trash émet incorrectement un événement

Fichier: src/app/features/sidebar/nimbus-sidebar.component.ts
Ligne: 90
Problème: Le bouton toggle de la section Trash émettait folderSelected.emit('.trash') au click, ce qui changeait le filtre de Notes-liste au lieu de juste ouvrir/fermer l'accordion.
Solution: Retrait de l'émission au click du bouton accordion.

// AVANT
<button (click)="open.trash = !open.trash; folderSelected.emit('.trash')">

// APRÈS
<button (click)="open.trash = !open.trash">

2. TrashExplorerComponent n'émet pas folderSelected

Fichier: src/app/layout/sidebar/trash/trash-explorer.component.ts
Ligne: 91-94
Problème: La méthode onFolderClick() du composant parent toggle le dossier mais n'émet PAS l'événement folderSelected. Donc quand l'utilisateur clique sur un dossier trash, le parent (nimbus-sidebar) ne reçoit pas l'événement et ne peut pas mettre à jour folderFilter dans app-shell-nimbus.

Solution: Ajout de l'émission de folderSelected avec le path du dossier cliqué.

// AVANT
onFolderClick(folder: VaultFolder) { 
  this.vault.toggleFolder(folder.path); 
}

// APRÈS
onFolderClick(folder: VaultFolder) {
  this.vault.toggleFolder(folder.path);
  this.folderSelected.emit(folder.path);
}

Flux Complet Corrigé

  1. Utilisateur clique sur un dossier dans Trash (ex: .trash/old-folder)
  2. TrashExplorerComponent.onFolderClick() est appelé
  3. Le dossier est toggle ouvert/fermé via vault.toggleFolder()
  4. L'événement folderSelected est émis avec le path .trash/old-folder
  5. NimbusSidebarComponent propage l'événement vers AppShellNimbusComponent
  6. AppShellNimbusComponent.onFolderSelected() définit this.folderFilter = '.trash/old-folder'
  7. NotesListComponent reçoit folderFilter en input
  8. Le computed filtered() filtre les notes où originalPath commence par .trash/old-folder
  9. Les notes du dossier trash s'affichent dans la liste

Architecture Existante Validée

VaultService - buildTrashTree()

  • Parse correctement les chemins trash via parseTrashFolderSegments()
  • Construit l'arborescence avec ensureTrashFolderPath()
  • Les badges de compte sont calculés par calculateTrashFolderCounts()
  • .trash est exclu de la section Folders via sortAndCleanFolderChildren()

NotesListComponent - Filtrage

  • Le filtre folderFilter fonctionne avec les chemins trash
  • Compare originalPath avec le folder passé (égalité ou startsWith)
  • Compatible avec les chemins .trash/subfolder

Backend API

  • /api/vault charge tous les fichiers .md y compris .trash
  • Les filePath sont relatifs au vault: .trash/old-folder/note.md
  • Les originalPath sont sans extension: .trash/old-folder/note

Fichiers Modifiés

  1. src/app/features/sidebar/nimbus-sidebar.component.ts

    • Retrait émission incorrecte au click accordion Trash
  2. src/app/layout/sidebar/trash/trash-explorer.component.ts

    • Ajout émission folderSelected au click sur dossier
  3. .env

    • VAULT_PATH pointant vers ./vault pour tests
  4. vault/.trash/ (fichiers test créés)

    • deleted-note-1.md
    • old-folder/old-note-2.md
    • old-folder/old-note-3.md
    • archive/archived-note.md

Critères d'Acceptation

  • La section Trash affiche l'arborescence réelle du dossier .trash
  • Cliquer un dossier dans Trash charge ses fichiers dans Notes-liste
  • Les badges affichent le nombre correct de notes (récursif)
  • .trash n'apparaît pas dans la section Folders
  • États hover/sélection cohérents avec autres sections
  • Dark mode compatible (styles existants)
  • Cas vide géré avec empty-state "La corbeille est vide"

Tests Suggérés

Manuel

  1. Démarrer node server/index.mjs et npm run dev
  2. Ouvrir Sidebar → Trash
  3. Vérifier que "old-folder" et "archive" s'affichent
  4. Cliquer "old-folder" → Notes-liste doit montrer 2 notes
  5. Vérifier badges: "old-folder (2)", "archive (1)"
  6. Vérifier que .trash n'apparaît pas dans Folders

E2E (à créer)

test('Trash explorer displays folders and loads notes on click', async ({ page }) => {
  await page.goto('http://localhost:3000');
  await page.click('text=Trash');
  await expect(page.locator('text=old-folder')).toBeVisible();
  await page.click('text=old-folder');
  await expect(page.locator('text=Old Note 2')).toBeVisible();
});

Prochaines Améliorations (Optionnel)

  1. Factoriser TreeView: FileExplorerComponent, TrashExplorerComponent et le child component partagent beaucoup de logique. Créer un composant GenericTreeView réutilisable.

  2. Actions sur Trash: Ajouter boutons "Restore" / "Delete Permanently" dans le contexte menu.

  3. Empty State amélioré: Ajouter une icône et un message plus descriptif quand .trash est vide.

  4. Performance: Si .trash contient 1000+ fichiers, implémenter pagination lazy dans l'arbre.

Notes Techniques

  • Signals Angular 20: VaultService utilise computed signals pour réactivité
  • Path normalization: Tous les paths utilisent '/' même sur Windows
  • Recursive folder counts: calculateTrashFolderCounts() compte récursivement
  • Change detection: OnPush utilisé partout pour performance