feat: Gestion des secteurs et migration v3.0.4+304
- Ajout système complet de gestion des secteurs avec contours géographiques - Import des contours départementaux depuis GeoJSON - API REST pour la gestion des secteurs (/api/sectors) - Service de géolocalisation pour déterminer les secteurs - Migration base de données avec tables x_departements_contours et sectors_adresses - Interface Flutter pour visualisation et gestion des secteurs - Ajout thème sombre dans l'application - Corrections diverses et optimisations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
161
app/lib/core/services/theme_service.dart
Executable file
161
app/lib/core/services/theme_service.dart
Executable file
@@ -0,0 +1,161 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
/// Service pour gérer les préférences de thème de l'application
|
||||
/// Supporte la détection automatique du mode sombre/clair du système
|
||||
class ThemeService extends ChangeNotifier {
|
||||
static ThemeService? _instance;
|
||||
static ThemeService get instance => _instance ??= ThemeService._();
|
||||
|
||||
ThemeService._() {
|
||||
_init();
|
||||
}
|
||||
|
||||
// Préférences stockées
|
||||
SharedPreferences? _prefs;
|
||||
|
||||
// Mode de thème actuel
|
||||
ThemeMode _themeMode = ThemeMode.system;
|
||||
|
||||
// Clé pour stocker les préférences
|
||||
static const String _themeModeKey = 'theme_mode';
|
||||
|
||||
/// Mode de thème actuel
|
||||
ThemeMode get themeMode => _themeMode;
|
||||
|
||||
/// Détecte si le système est en mode sombre
|
||||
bool get isSystemDark {
|
||||
final brightness = SchedulerBinding.instance.platformDispatcher.platformBrightness;
|
||||
return brightness == Brightness.dark;
|
||||
}
|
||||
|
||||
/// Détermine si l'app doit utiliser le mode sombre
|
||||
bool get isDarkMode {
|
||||
switch (_themeMode) {
|
||||
case ThemeMode.light:
|
||||
return false;
|
||||
case ThemeMode.dark:
|
||||
return true;
|
||||
case ThemeMode.system:
|
||||
return isSystemDark;
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialise le service
|
||||
Future<void> _init() async {
|
||||
try {
|
||||
_prefs = await SharedPreferences.getInstance();
|
||||
await _loadThemeMode();
|
||||
|
||||
// Observer les changements du système
|
||||
SchedulerBinding.instance.platformDispatcher.onPlatformBrightnessChanged = () {
|
||||
_onSystemBrightnessChanged();
|
||||
};
|
||||
|
||||
debugPrint('🎨 ThemeService initialisé - Mode: $_themeMode, Système sombre: $isSystemDark');
|
||||
} catch (e) {
|
||||
debugPrint('❌ Erreur initialisation ThemeService: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Charge le mode de thème depuis les préférences
|
||||
Future<void> _loadThemeMode() async {
|
||||
try {
|
||||
final savedMode = _prefs?.getString(_themeModeKey);
|
||||
if (savedMode != null) {
|
||||
_themeMode = ThemeMode.values.firstWhere(
|
||||
(mode) => mode.name == savedMode,
|
||||
orElse: () => ThemeMode.system,
|
||||
);
|
||||
}
|
||||
debugPrint('🎨 Mode de thème chargé: $_themeMode');
|
||||
} catch (e) {
|
||||
debugPrint('❌ Erreur chargement thème: $e');
|
||||
_themeMode = ThemeMode.system;
|
||||
}
|
||||
}
|
||||
|
||||
/// Sauvegarde le mode de thème
|
||||
Future<void> _saveThemeMode() async {
|
||||
try {
|
||||
await _prefs?.setString(_themeModeKey, _themeMode.name);
|
||||
debugPrint('💾 Mode de thème sauvegardé: $_themeMode');
|
||||
} catch (e) {
|
||||
debugPrint('❌ Erreur sauvegarde thème: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Appelée quand la luminosité du système change
|
||||
void _onSystemBrightnessChanged() {
|
||||
if (_themeMode == ThemeMode.system) {
|
||||
debugPrint('🌗 Changement luminosité système détecté - Sombre: $isSystemDark');
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// Change le mode de thème
|
||||
Future<void> setThemeMode(ThemeMode mode) async {
|
||||
if (_themeMode != mode) {
|
||||
_themeMode = mode;
|
||||
await _saveThemeMode();
|
||||
notifyListeners();
|
||||
debugPrint('🎨 Mode de thème changé: $mode');
|
||||
}
|
||||
}
|
||||
|
||||
/// Basculer entre clair et sombre
|
||||
Future<void> toggleTheme() async {
|
||||
switch (_themeMode) {
|
||||
case ThemeMode.light:
|
||||
await setThemeMode(ThemeMode.dark);
|
||||
break;
|
||||
case ThemeMode.dark:
|
||||
await setThemeMode(ThemeMode.light);
|
||||
break;
|
||||
case ThemeMode.system:
|
||||
// Si système, basculer vers l'opposé du mode actuel du système
|
||||
await setThemeMode(isSystemDark ? ThemeMode.light : ThemeMode.dark);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Retourner au mode système
|
||||
Future<void> useSystemTheme() async {
|
||||
await setThemeMode(ThemeMode.system);
|
||||
}
|
||||
|
||||
/// Forcer le mode clair
|
||||
Future<void> useLightTheme() async {
|
||||
await setThemeMode(ThemeMode.light);
|
||||
}
|
||||
|
||||
/// Forcer le mode sombre
|
||||
Future<void> useDarkTheme() async {
|
||||
await setThemeMode(ThemeMode.dark);
|
||||
}
|
||||
|
||||
/// Obtenir une description textuelle du mode actuel
|
||||
String get themeModeDescription {
|
||||
switch (_themeMode) {
|
||||
case ThemeMode.light:
|
||||
return 'Clair';
|
||||
case ThemeMode.dark:
|
||||
return 'Sombre';
|
||||
case ThemeMode.system:
|
||||
return 'Automatique (${isSystemDark ? 'sombre' : 'clair'})';
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtenir l'icône appropriée pour le mode actuel
|
||||
IconData get themeModeIcon {
|
||||
switch (_themeMode) {
|
||||
case ThemeMode.light:
|
||||
return Icons.light_mode;
|
||||
case ThemeMode.dark:
|
||||
return Icons.dark_mode;
|
||||
case ThemeMode.system:
|
||||
return Icons.brightness_auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user