Initial commit: FuZip - Application de fusion interactive de fichiers ZIP
- Backend PHP: architecture MVC avec API REST (upload, merge, preview, extract) - Frontend JavaScript: composants modulaires (arborescence, upload, themes, i18n) - Fonctionnalités: drag&drop, sélection exclusive, détection conflits, persistance état - Sécurité: validation stricte, isolation sessions, sanitization chemins - UI/UX: responsive, thèmes clair/sombre, multi-langue (FR/EN) - Documentation: README complet avec installation et utilisation
This commit is contained in:
112
assets/js/ThemeManager.js
Normal file
112
assets/js/ThemeManager.js
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* FuZip - Gestionnaire de thème (Option E: Dark Mode)
|
||||
* Gère le toggle entre thème clair et sombre avec persistance localStorage
|
||||
*/
|
||||
|
||||
class ThemeManager {
|
||||
constructor() {
|
||||
this.storageKey = 'fuzip_theme';
|
||||
this.currentTheme = this.loadTheme();
|
||||
this.btnToggle = document.getElementById('btn-theme-toggle');
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise le gestionnaire de thème
|
||||
*/
|
||||
init() {
|
||||
// Applique le thème initial
|
||||
this.applyTheme(this.currentTheme);
|
||||
|
||||
// Écoute le clic sur le bouton toggle
|
||||
if (this.btnToggle) {
|
||||
this.btnToggle.addEventListener('click', () => this.toggle());
|
||||
}
|
||||
|
||||
// Écoute les changements de préférence système
|
||||
this.watchSystemPreference();
|
||||
|
||||
console.log(`[ThemeManager] Initialized with theme: ${this.currentTheme}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge le thème depuis localStorage ou détecte la préférence système
|
||||
* @returns {string} 'light' ou 'dark'
|
||||
*/
|
||||
loadTheme() {
|
||||
// Vérifie localStorage en premier
|
||||
const saved = localStorage.getItem(this.storageKey);
|
||||
if (saved === 'light' || saved === 'dark') {
|
||||
return saved;
|
||||
}
|
||||
|
||||
// Sinon détecte la préférence système
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
return 'dark';
|
||||
}
|
||||
|
||||
return 'light'; // Par défaut
|
||||
}
|
||||
|
||||
/**
|
||||
* Applique un thème
|
||||
* @param {string} theme - 'light' ou 'dark'
|
||||
*/
|
||||
applyTheme(theme) {
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
this.currentTheme = theme;
|
||||
localStorage.setItem(this.storageKey, theme);
|
||||
|
||||
// Log pour debug
|
||||
console.log(`[ThemeManager] Theme applied: ${theme}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle entre light et dark
|
||||
*/
|
||||
toggle() {
|
||||
const newTheme = this.currentTheme === 'light' ? 'dark' : 'light';
|
||||
this.applyTheme(newTheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Écoute les changements de préférence système
|
||||
* (seulement si l'utilisateur n'a pas explicitement choisi un thème)
|
||||
*/
|
||||
watchSystemPreference() {
|
||||
if (!window.matchMedia) return;
|
||||
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
|
||||
mediaQuery.addEventListener('change', (e) => {
|
||||
// Ne change automatiquement que si pas de préférence explicite
|
||||
const hasExplicitPreference = localStorage.getItem(this.storageKey) !== null;
|
||||
if (!hasExplicitPreference) {
|
||||
const newTheme = e.matches ? 'dark' : 'light';
|
||||
this.applyTheme(newTheme);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le thème actuel
|
||||
* @returns {string}
|
||||
*/
|
||||
getTheme() {
|
||||
return this.currentTheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit un thème spécifique (utilisé par LanguageManager si besoin)
|
||||
* @param {string} theme - 'light' ou 'dark'
|
||||
*/
|
||||
setTheme(theme) {
|
||||
if (theme === 'light' || theme === 'dark') {
|
||||
this.applyTheme(theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export pour utilisation dans app.js
|
||||
window.ThemeManager = ThemeManager;
|
||||
Reference in New Issue
Block a user