import 'package:flutter/material.dart'; import 'package:geosector_app/core/services/theme_service.dart'; /// Widget pour basculer entre les thèmes clair/sombre/automatique class ThemeSwitcher extends StatelessWidget { /// Style d'affichage du sélecteur final ThemeSwitcherStyle style; /// Afficher le texte descriptif final bool showLabel; /// Callback optionnel appelé après changement de thème final VoidCallback? onThemeChanged; const ThemeSwitcher({ super.key, this.style = ThemeSwitcherStyle.iconButton, this.showLabel = false, this.onThemeChanged, }); @override Widget build(BuildContext context) { return AnimatedBuilder( animation: ThemeService.instance, builder: (context, child) { switch (style) { case ThemeSwitcherStyle.iconButton: return _buildIconButton(context); case ThemeSwitcherStyle.dropdown: return _buildDropdown(context); case ThemeSwitcherStyle.segmentedButton: return _buildSegmentedButton(context); case ThemeSwitcherStyle.toggleButtons: return _buildToggleButtons(context); } }, ); } /// Bouton icône simple (bascule entre clair/sombre) Widget _buildIconButton(BuildContext context) { final themeService = ThemeService.instance; return IconButton( icon: Icon(themeService.themeModeIcon), tooltip: 'Changer le thème (${themeService.themeModeDescription})', onPressed: () async { await themeService.toggleTheme(); onThemeChanged?.call(); }, ); } /// Dropdown avec toutes les options Widget _buildDropdown(BuildContext context) { final themeService = ThemeService.instance; final theme = Theme.of(context); return DropdownButton( value: themeService.themeMode, icon: Icon(Icons.arrow_drop_down, color: theme.colorScheme.onSurface), underline: Container(), items: [ DropdownMenuItem( value: ThemeMode.system, child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.brightness_auto, size: 20), const SizedBox(width: 8), const Text('Automatique'), if (showLabel) ...[ const SizedBox(width: 4), Text( '(${themeService.isSystemDark ? 'sombre' : 'clair'})', style: theme.textTheme.bodySmall, ), ], ], ), ), const DropdownMenuItem( value: ThemeMode.light, child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.light_mode, size: 20), SizedBox(width: 8), Text('Clair'), ], ), ), const DropdownMenuItem( value: ThemeMode.dark, child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.dark_mode, size: 20), SizedBox(width: 8), Text('Sombre'), ], ), ), ], onChanged: (ThemeMode? mode) async { if (mode != null) { await themeService.setThemeMode(mode); onThemeChanged?.call(); } }, ); } /// Boutons segmentés (Material 3) Widget _buildSegmentedButton(BuildContext context) { final themeService = ThemeService.instance; return SegmentedButton( segments: const [ ButtonSegment( value: ThemeMode.light, icon: Icon(Icons.light_mode, size: 16), label: Text('Clair'), ), ButtonSegment( value: ThemeMode.system, icon: Icon(Icons.brightness_auto, size: 16), label: Text('Auto'), ), ButtonSegment( value: ThemeMode.dark, icon: Icon(Icons.dark_mode, size: 16), label: Text('Sombre'), ), ], selected: {themeService.themeMode}, onSelectionChanged: (Set selection) async { if (selection.isNotEmpty) { await themeService.setThemeMode(selection.first); onThemeChanged?.call(); } }, ); } /// Boutons à bascule Widget _buildToggleButtons(BuildContext context) { final themeService = ThemeService.instance; final theme = Theme.of(context); return ToggleButtons( borderRadius: BorderRadius.circular(8), constraints: const BoxConstraints(minHeight: 40, minWidth: 60), isSelected: [ themeService.themeMode == ThemeMode.light, themeService.themeMode == ThemeMode.system, themeService.themeMode == ThemeMode.dark, ], onPressed: (int index) async { final modes = [ThemeMode.light, ThemeMode.system, ThemeMode.dark]; await themeService.setThemeMode(modes[index]); onThemeChanged?.call(); }, children: const [ Icon(Icons.light_mode, size: 20), Icon(Icons.brightness_auto, size: 20), Icon(Icons.dark_mode, size: 20), ], ); } } /// Widget d'information sur le thème actuel class ThemeInfo extends StatelessWidget { const ThemeInfo({super.key}); @override Widget build(BuildContext context) { return AnimatedBuilder( animation: ThemeService.instance, builder: (context, child) { final themeService = ThemeService.instance; final theme = Theme.of(context); return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: theme.colorScheme.surfaceContainerHighest.withOpacity(0.5), borderRadius: BorderRadius.circular(8), border: Border.all( color: theme.colorScheme.outline.withOpacity(0.3), ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( themeService.themeModeIcon, size: 16, color: theme.colorScheme.primary, ), const SizedBox(width: 8), Text( themeService.themeModeDescription, style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onSurface, fontWeight: FontWeight.w500, ), ), ], ), ); }, ); } } /// Styles d'affichage pour le ThemeSwitcher enum ThemeSwitcherStyle { /// Bouton icône simple qui bascule entre clair/sombre iconButton, /// Menu déroulant avec toutes les options dropdown, /// Boutons segmentés (Material 3) segmentedButton, /// Boutons à bascule toggleButtons, }