Implement system theme support and dark mode infrastructure

Add comprehensive theme management system with iOS system integration:

- System theme detection: App follows iOS dark/light mode preferences via ThemeMode.system
- Theme provider: Centralized theme state management with Riverpod (defaults to dark mode)
- Settings toggle: Segmented button UI for Light/Dark/Auto theme selection
- iOS system UI: Status bar and navigation bar adapt to current theme brightness

Dark mode map styling (Android-ready):
- DarkModeMapComponent: Reactive theme change detection with didChangeDependencies
- Map style application: Custom dark JSON style for navigation maps
- Theme-aware styling: Automatically applies/resets map style on theme changes
- Note: Map styling currently Android-only due to iOS SDK limitations

Updates:
- main.dart: System UI overlay styling for iOS, theme provider integration
- settings_page.dart: SegmentedButton theme toggle with icons
- providers.dart: themeModeProvider for app-wide theme state
- dark_mode_map.dart: Theme reactivity and style application logic
- navigation_page.dart: Theme detection infrastructure (prepared for future use)

Design philosophy:
- Follow system preferences by default for native iOS experience
- Manual override available for user preference
- Clean separation between Flutter UI theming and native map styling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jean-Philippe Brule
2025-11-16 00:52:14 -05:00
parent fcf8c9bd94
commit 96c9e59cf0
5 changed files with 273 additions and 40 deletions
+35
View File
@@ -9,6 +9,7 @@ class SettingsPage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final userProfile = ref.watch(userProfileProvider);
final language = ref.watch(languageProvider);
final themeMode = ref.watch(themeModeProvider);
return Scaffold(
appBar: AppBar(
@@ -109,6 +110,40 @@ class SettingsPage extends ConsumerWidget {
],
),
),
const SizedBox(height: 16),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Theme',
style: Theme.of(context).textTheme.titleSmall,
),
const SizedBox(height: 8),
SegmentedButton<ThemeMode>(
selected: {themeMode},
onSelectionChanged: (Set<ThemeMode> newSelection) {
ref.read(themeModeProvider.notifier).state = newSelection.first;
},
segments: const [
ButtonSegment<ThemeMode>(
value: ThemeMode.light,
label: Text('Light'),
icon: Icon(Icons.light_mode),
),
ButtonSegment<ThemeMode>(
value: ThemeMode.dark,
label: Text('Dark'),
icon: Icon(Icons.dark_mode),
),
ButtonSegment<ThemeMode>(
value: ThemeMode.system,
label: Text('Auto'),
icon: Icon(Icons.brightness_auto),
),
],
),
],
),
],
),
),