195 lines
6.3 KiB
JavaScript
195 lines
6.3 KiB
JavaScript
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();
|
|
}
|