- Added UrlStateService to sync app state with URL parameters for note selection, tags, folders, and search - Implemented URL state effects in AppComponent to handle navigation from URL parameters - Updated sidebar and layout components to reflect URL state changes in UI - Added URL state updates when navigating via note selection, tag clicks, and search - Modified note sharing to use URL parameters instead of route paths - Added auto-opening of relevant
		
			
				
	
	
	
		
			11 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	UrlStateService - Exemples d'URL et Cas d'Usage
📌 Table des matières
- Exemples simples
 - Exemples combinés
 - Cas d'usage réels
 - Partage de liens
 - Gestion des erreurs
 - Bonnes pratiques
 
Exemples Simples
1. Ouvrir une note
URL:
https://app.example.com/viewer?note=Docs/Architecture.md
Résultat:
- La note 
Docs/Architecture.mds'ouvre dans la vue note - Le contenu est chargé et affiché
 - La note est mise en surbrillance dans la liste
 
Code:
await this.urlState.openNote('Docs/Architecture.md');
2. Filtrer par tag
URL:
https://app.example.com/viewer?tag=Ideas
Résultat:
- Affiche toutes les notes avec le tag 
Ideas - Le tag est mis en surbrillance dans la liste des tags
 - La liste des notes est filtrée
 
Code:
await this.urlState.filterByTag('Ideas');
3. Filtrer par dossier
URL:
https://app.example.com/viewer?folder=Notes/Meetings
Résultat:
- Affiche toutes les notes du dossier 
Notes/Meetings - Le dossier est mis en surbrillance dans l'arborescence
 - La liste des notes est filtrée
 
Code:
await this.urlState.filterByFolder('Notes/Meetings');
4. Afficher un quick link
URL:
https://app.example.com/viewer?quick=Favoris
Résultat:
- Affiche les notes marquées comme favoris
 - Le quick link est mis en surbrillance
 - La liste des notes est filtrée
 
Code:
await this.urlState.filterByQuickLink('Favoris');
5. Rechercher
URL:
https://app.example.com/viewer?search=performance
Résultat:
- Affiche les résultats de recherche pour "performance"
 - Les notes contenant le terme sont listées
 - Le terme est mis en surbrillance
 
Code:
await this.urlState.updateSearch('performance');
Exemples Combinés
1. Note avec recherche
URL:
https://app.example.com/viewer?note=Docs/Architecture.md&search=performance
Résultat:
- Ouvre la note 
Docs/Architecture.md - Met en surbrillance les occurrences de "performance"
 - Permet de naviguer entre les occurrences
 
Code:
await this.urlState.openNote('Docs/Architecture.md');
await this.urlState.updateSearch('performance');
2. Dossier avec tag
URL:
https://app.example.com/viewer?folder=Notes/Meetings&tag=Important
Résultat:
- Affiche les notes du dossier 
Notes/Meetings - Filtre par le tag 
Important - Affiche l'intersection des deux filtres
 
Code:
await this.urlState.filterByFolder('Notes/Meetings');
await this.urlState.filterByTag('Important');
3. Quick link avec recherche
URL:
https://app.example.com/viewer?quick=Archive&search=2024
Résultat:
- Affiche les notes archivées
 - Filtre par le terme "2024"
 - Affiche les notes archivées contenant "2024"
 
Code:
await this.urlState.filterByQuickLink('Archive');
await this.urlState.updateSearch('2024');
4. Dossier avec recherche
URL:
https://app.example.com/viewer?folder=Journal&search=2025
Résultat:
- Affiche les notes du dossier 
Journal - Filtre par le terme "2025"
 - Affiche les notes du journal contenant "2025"
 
Code:
await this.urlState.filterByFolder('Journal');
await this.urlState.updateSearch('2025');
Cas d'Usage Réels
1. Documentation d'Architecture
Scénario: Vous travaillez sur l'architecture et voulez partager une note spécifique avec votre équipe.
URL:
https://app.example.com/viewer?note=Docs/Architecture.md
Avantages:
- Lien direct vers la note
 - Pas besoin de naviguer manuellement
 - Contexte clair pour l'équipe
 
2. Réunion d'équipe
Scénario: Vous voulez afficher les notes de réunion d'un mois spécifique.
URL:
https://app.example.com/viewer?folder=Notes/Meetings/2025-01&tag=Important
Avantages:
- Filtre par dossier et tag
 - Affiche uniquement les réunions importantes
 - Facile à partager avec l'équipe
 
3. Recherche de bug
Scénario: Vous cherchez des notes contenant "bug" dans le dossier "Issues".
URL:
https://app.example.com/viewer?folder=Issues&search=bug
Avantages:
- Recherche ciblée dans un dossier
 - Résultats pertinents
 - Facile à reproduire
 
4. Favoris du projet
Scénario: Vous voulez afficher les notes favorites du projet "ProjectX".
URL:
https://app.example.com/viewer?quick=Favoris&search=ProjectX
Avantages:
- Affiche les favoris
 - Filtre par projet
 - Vue d'ensemble rapide
 
5. Tâches urgentes
Scénario: Vous voulez voir les tâches urgentes du jour.
URL:
https://app.example.com/viewer?quick=Tâches&tag=Urgent
Avantages:
- Affiche les tâches
 - Filtre par urgence
 - Priorisation facile
 
6. Brouillons à publier
Scénario: Vous voulez voir les brouillons prêts à être publiés.
URL:
https://app.example.com/viewer?quick=Brouillons&tag=Prêt
Avantages:
- Affiche les brouillons
 - Filtre par statut
 - Workflow clair
 
7. Archive par année
Scénario: Vous voulez consulter l'archive de 2024.
URL:
https://app.example.com/viewer?folder=Archive/2024
Avantages:
- Affiche l'archive d'une année
 - Navigation facile
 - Historique accessible
 
Partage de Liens
1. Partage simple
Scénario: Vous voulez partager une note avec un collègue.
// Générer le lien
const shareUrl = this.urlState.generateShareUrl();
// Copier dans le presse-papiers
await this.urlState.copyCurrentUrlToClipboard();
// Afficher un toast
this.toast.success('Lien copié!');
Résultat:
https://app.example.com/viewer?note=Docs/Architecture.md
2. Partage avec contexte
Scénario: Vous voulez partager une note avec un contexte de recherche.
// Générer le lien avec contexte
const shareUrl = this.urlState.generateShareUrl({
  note: 'Docs/Architecture.md',
  search: 'performance'
});
// Partager
await navigator.clipboard.writeText(shareUrl);
Résultat:
https://app.example.com/viewer?note=Docs/Architecture.md&search=performance
3. Partage de filtre
Scénario: Vous voulez partager un filtre avec votre équipe.
// Appliquer le filtre
await this.urlState.filterByTag('Ideas');
// Générer et copier le lien
const shareUrl = this.urlState.generateShareUrl();
await navigator.clipboard.writeText(shareUrl);
Résultat:
https://app.example.com/viewer?tag=Ideas
4. Bouton de partage
Scénario: Vous voulez ajouter un bouton de partage dans l'interface.
@Component({
  selector: 'app-share-button',
  template: `
    <button (click)="shareCurrentState()" class="share-btn">
      📤 Partager
    </button>
  `
})
export class ShareButtonComponent {
  urlState = inject(UrlStateService);
  toast = inject(ToastService);
  
  async shareCurrentState(): Promise<void> {
    try {
      await this.urlState.copyCurrentUrlToClipboard();
      this.toast.success('Lien copié!');
    } catch (error) {
      this.toast.error('Erreur lors de la copie');
    }
  }
}
Gestion des Erreurs
1. Note introuvable
URL:
https://app.example.com/viewer?note=NonExistent.md
Résultat:
- Message d'avertissement dans la console
 - L'état n'est pas mis à jour
 - L'interface reste dans l'état précédent
 
Code:
try {
  await this.urlState.openNote('NonExistent.md');
} catch (error) {
  console.error('Note not found');
  this.toast.error('Note introuvable');
}
2. Tag inexistant
URL:
https://app.example.com/viewer?tag=NonExistent
Résultat:
- Message d'avertissement dans la console
 - L'état n'est pas mis à jour
 - L'interface reste dans l'état précédent
 
Code:
try {
  await this.urlState.filterByTag('NonExistent');
} catch (error) {
  console.error('Tag not found');
  this.toast.warning('Tag inexistant');
}
3. Dossier inexistant
URL:
https://app.example.com/viewer?folder=NonExistent
Résultat:
- Message d'avertissement dans la console
 - L'état n'est pas mis à jour
 - L'interface reste dans l'état précédent
 
Code:
try {
  await this.urlState.filterByFolder('NonExistent');
} catch (error) {
  console.error('Folder not found');
  this.toast.warning('Dossier inexistant');
}
4. Quick link invalide
URL:
https://app.example.com/viewer?quick=Invalid
Résultat:
- Message d'avertissement dans la console
 - L'état n'est pas mis à jour
 - L'interface reste dans l'état précédent
 
Code:
try {
  await this.urlState.filterByQuickLink('Invalid');
} catch (error) {
  console.error('Invalid quick link');
  this.toast.warning('Quick link invalide');
}
Bonnes Pratiques
1. Toujours valider les données
// ❌ Mauvais - Pas de validation
await this.urlState.openNote(userInput);
// ✅ Bon - Validation
const note = this.vault.allNotes().find(n => n.filePath === userInput);
if (note) {
  await this.urlState.openNote(userInput);
} else {
  this.toast.error('Note introuvable');
}
2. Gérer les erreurs
// ❌ Mauvais - Pas de gestion d'erreur
await this.urlState.filterByTag(userInput);
// ✅ Bon - Gestion d'erreur
try {
  await this.urlState.filterByTag(userInput);
} catch (error) {
  console.error('Error:', error);
  this.toast.error('Erreur lors du filtrage');
}
3. Utiliser les signaux
// ❌ Mauvais - Pas réactif
const tag = this.urlState.currentState().tag;
// ✅ Bon - Réactif
const tag = this.urlState.activeTag;
4. Écouter les changements
// ❌ Mauvais - Pas d'écoute
this.urlState.openNote('Note.md');
// ✅ Bon - Écouter les changements
effect(() => {
  const note = this.urlState.currentNote();
  if (note) {
    console.log('Note changed:', note.title);
  }
});
5. Nettoyer les ressources
// ❌ Mauvais - Pas de nettoyage
this.urlState.stateChange$.subscribe(event => {
  console.log('State changed:', event);
});
// ✅ Bon - Nettoyage
private destroy$ = new Subject<void>();
constructor() {
  this.urlState.stateChange$
    .pipe(takeUntil(this.destroy$))
    .subscribe(event => {
      console.log('State changed:', event);
    });
}
ngOnDestroy() {
  this.destroy$.next();
  this.destroy$.complete();
}
6. Utiliser les types
// ❌ Mauvais - Pas de types
const state = this.urlState.currentState();
// ✅ Bon - Avec types
const state: UrlState = this.urlState.currentState();
7. Documenter les URLs
/**
 * Ouvre une note spécifique
 * 
 * URL: /viewer?note=Docs/Architecture.md
 * 
 * @param notePath - Chemin de la note (ex: 'Docs/Architecture.md')
 */
async openNote(notePath: string): Promise<void> {
  // ...
}
Résumé
Le UrlStateService offre une solution flexible pour gérer l'état de l'interface via l'URL:
- ✅ Exemples simples pour les cas courants
 - ✅ Exemples combinés pour les cas complexes
 - ✅ Cas d'usage réels pour l'inspiration
 - ✅ Partage de liens facile
 - ✅ Gestion des erreurs robuste
 - ✅ Bonnes pratiques pour la qualité du code
 
Utilisez ces exemples comme base pour intégrer le service dans votre application.