import { debug, debugError } from './debug.js'; /** * SidebarSections - Gère les sections rétractables de la sidebar * Permet de replier/déplier les favoris et le répertoire de notes */ class SidebarSections { constructor() { this.sections = { favorites: { key: 'sidebar-favorites-expanded', defaultState: true }, notes: { key: 'sidebar-notes-expanded', defaultState: true } }; this.init(); } init() { debug('SidebarSections: Initialisation...'); // Restaurer l'état sauvegardé au démarrage this.restoreStates(); // Écouter les événements HTMX pour réattacher les handlers après les swaps document.body.addEventListener('htmx:afterSwap', (event) => { const targetId = event.detail?.target?.id; if (targetId === 'favorites-list') { debug('Favoris rechargés, restauration de l\'état...'); setTimeout(() => this.restoreSectionState('favorites'), 50); } if (targetId === 'file-tree') { debug('File-tree rechargé, restauration de l\'état...'); setTimeout(() => this.restoreSectionState('notes'), 50); } }); document.body.addEventListener('htmx:oobAfterSwap', (event) => { const targetId = event.detail?.target?.id; // Ne restaurer l'état que pour les swaps du file-tree complet // Les swaps de statut (auto-save-status) ne doivent pas déclencher la restauration if (targetId === 'file-tree') { debug('File-tree rechargé (oob), restauration de l\'état...'); setTimeout(() => this.restoreSectionState('notes'), 50); } }); // Écouter les restaurations d'historique (bouton retour du navigateur) document.body.addEventListener('htmx:historyRestore', () => { debug('SidebarSections: History restored, restoring section states...'); // Restaurer les états des sections après restauration de l'historique setTimeout(() => { this.restoreSectionState('favorites'); this.restoreSectionState('notes'); }, 100); }); debug('SidebarSections: Initialisé'); } /** * Récupère l'état sauvegardé d'une section */ getSectionState(sectionName) { const section = this.sections[sectionName]; if (!section) return true; const saved = localStorage.getItem(section.key); return saved !== null ? saved === 'true' : section.defaultState; } /** * Sauvegarde l'état d'une section */ setSectionState(sectionName, isExpanded) { const section = this.sections[sectionName]; if (!section) return; localStorage.setItem(section.key, isExpanded.toString()); debug(`État sauvegardé: ${sectionName} = ${isExpanded}`); } /** * Toggle une section (ouvert/fermé) */ toggleSection(sectionName, headerElement) { if (!headerElement) { console.error(`Header element not found for section: ${sectionName}`); return; } const contentElement = headerElement.nextElementSibling; const toggleIcon = headerElement.querySelector('.section-toggle'); if (!contentElement) { console.error(`Content element not found for section: ${sectionName}`); return; } const isCurrentlyExpanded = contentElement.style.display !== 'none'; const newState = !isCurrentlyExpanded; if (newState) { // Ouvrir contentElement.style.display = 'block'; if (toggleIcon) { toggleIcon.classList.add('expanded'); } } else { // Fermer contentElement.style.display = 'none'; if (toggleIcon) { toggleIcon.classList.remove('expanded'); } } this.setSectionState(sectionName, newState); debug(`Section ${sectionName} ${newState ? 'ouverte' : 'fermée'}`); } /** * Restaure l'état d'une section depuis localStorage */ restoreSectionState(sectionName) { const isExpanded = this.getSectionState(sectionName); const header = document.querySelector(`[data-section="${sectionName}"]`); if (!header) { console.warn(`Header not found for section: ${sectionName}`); return; } const content = header.nextElementSibling; const toggleIcon = header.querySelector('.section-toggle'); if (!content) { console.warn(`Content not found for section: ${sectionName}`); return; } if (isExpanded) { content.style.display = 'block'; if (toggleIcon) { toggleIcon.classList.add('expanded'); } } else { content.style.display = 'none'; if (toggleIcon) { toggleIcon.classList.remove('expanded'); } } debug(`État restauré: ${sectionName} = ${isExpanded ? 'ouvert' : 'fermé'}`); } /** * Restaure tous les états au démarrage */ restoreStates() { // Attendre que le DOM soit complètement chargé et que HTMX ait fini de charger les contenus // Délai augmenté pour correspondre aux délais des triggers HTMX (250ms + marge) setTimeout(() => { this.restoreSectionState('favorites'); this.restoreSectionState('notes'); }, 400); } } /** * Fonction globale pour toggle une section (appelée depuis le HTML) */ window.toggleSidebarSection = function(sectionName, event) { if (event) { event.preventDefault(); event.stopPropagation(); } const headerElement = event?.currentTarget || document.querySelector(`[data-section="${sectionName}"]`); if (window.sidebarSections && headerElement) { window.sidebarSections.toggleSection(sectionName, headerElement); } }; /** * Initialisation automatique */ if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { window.sidebarSections = new SidebarSections(); }); } else { // DOM déjà chargé window.sidebarSections = new SidebarSections(); }