diff --git a/lib/application.dart b/lib/application.dart index a8a27db..7a5c822 100644 --- a/lib/application.dart +++ b/lib/application.dart @@ -30,20 +30,21 @@ class Application extends StatelessWidget { return MultiProvider( providers: [ Provider(create: (_) => UserPreferencesService(snapshot.data!)), - Provider(create: (_) => HapticsService()), + Provider(create: (_) => const HapticsService()), + Provider(create: (_) => PermissionsService()), Provider.value(value: evSource), ], - child: Provider( - create: (_) => PermissionsService(), - child: StopTypeProvider( - child: ThemeProvider( - initialPrimaryColor: const Color(0xFF2196f3), - builder: (context, child) => AnnotatedRegion( + child: StopTypeProvider( + child: ThemeProvider( + builder: (context, _) { + final systemIconsBrightness = + ThemeData.estimateBrightnessForColor(context.watch().colorScheme.onSurface); + return AnnotatedRegion( value: SystemUiOverlayStyle( statusBarColor: Colors.transparent, - statusBarIconBrightness: - ThemeData.estimateBrightnessForColor(context.watch().colorScheme.onSurface), + statusBarIconBrightness: systemIconsBrightness, systemNavigationBarColor: context.watch().colorScheme.surface, + systemNavigationBarIconBrightness: systemIconsBrightness, ), child: MaterialApp( theme: context.watch(), @@ -64,8 +65,8 @@ class Application extends StatelessWidget { "settings": (context) => const SettingsScreen(), }, ), - ), - ), + ); + }, ), ), ); diff --git a/lib/data/haptics_service.dart b/lib/data/haptics_service.dart index 0b6e7c3..aa7511b 100644 --- a/lib/data/haptics_service.dart +++ b/lib/data/haptics_service.dart @@ -1,6 +1,8 @@ import 'package:vibration/vibration.dart'; class HapticsService { + const HapticsService(); + Future quickVibration() async => _tryVibrate(duration: 25, amplitude: 96); Future responseVibration() async => _tryVibrate(duration: 50, amplitude: 128); diff --git a/lib/res/theme.dart b/lib/res/theme.dart index 376e86c..0fc2f0c 100644 --- a/lib/res/theme.dart +++ b/lib/res/theme.dart @@ -1,3 +1,4 @@ +import 'package:dynamic_color/dynamic_color.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:lightmeter/data/models/theme_type.dart'; @@ -7,12 +8,10 @@ import 'package:material_color_utilities/material_color_utilities.dart'; import 'package:provider/provider.dart'; class ThemeProvider extends StatefulWidget { - final Color initialPrimaryColor; final Widget? child; final TransitionBuilder? builder; const ThemeProvider({ - required this.initialPrimaryColor, this.child, this.builder, super.key, @@ -28,7 +27,10 @@ class ThemeProvider extends StatefulWidget { class ThemeProviderState extends State { late ThemeType _themeType; - late Color _primaryColor = widget.initialPrimaryColor; + Color _primaryColor = const Color(0xFF2196f3); + bool _allowDynamicColors = false; + + bool get allowDynamicColors => _allowDynamicColors; @override void initState() { @@ -38,16 +40,29 @@ class ThemeProviderState extends State { @override Widget build(BuildContext context) { - return Provider.value( - value: _themeType, - child: Provider.value( - value: _themeFromColor( - _primaryColor, - _mapThemeTypeToBrightness(_themeType), - ), - builder: widget.builder, - child: widget.child, - ), + return DynamicColorBuilder( + builder: (lightDynamic, darkDynamic) { + _allowDynamicColors = lightDynamic != null && darkDynamic != null; + if (_allowDynamicColors) { + final dynamicColorScheme = _themeBrightness == Brightness.light ? lightDynamic : darkDynamic; + if (dynamicColorScheme != null) { + _primaryColor = dynamicColorScheme.primary; + } + } + return Provider.value( + value: _themeType, + child: Provider.value( + value: _themeFromColorScheme( + _colorSchemeFromColor( + _primaryColor, + _themeBrightness, + ), + ), + builder: widget.builder, + child: widget.child, + ), + ); + }, ); } @@ -62,6 +77,17 @@ class ThemeProviderState extends State { context.read().themeType = themeType; } + Brightness get _themeBrightness { + switch (_themeType) { + case ThemeType.light: + return Brightness.light; + case ThemeType.dark: + return Brightness.dark; + case ThemeType.systemDefault: + return SchedulerBinding.instance.platformDispatcher.platformBrightness; + } + } + void setPrimaryColor(Color color) { if (color == _primaryColor) { return; @@ -72,20 +98,9 @@ class ThemeProviderState extends State { }); } - Brightness _mapThemeTypeToBrightness(ThemeType themeType) { - switch (themeType) { - case ThemeType.light: - return Brightness.light; - case ThemeType.dark: - return Brightness.dark; - case ThemeType.systemDefault: - return SchedulerBinding.instance.platformDispatcher.platformBrightness; - } - } - - ThemeData _themeFromColor(Color color, Brightness brightness) { + ColorScheme _colorSchemeFromColor(Color color, Brightness brightness) { final scheme = brightness == Brightness.light ? Scheme.light(color.value) : Scheme.dark(color.value); - final colorScheme = ColorScheme( + return ColorScheme( brightness: brightness, primary: Color(scheme.primary), onPrimary: Color(scheme.onPrimary), @@ -102,9 +117,18 @@ class ThemeProviderState extends State { surfaceVariant: Color.alphaBlend(Color(scheme.primary).withOpacity(0.5), Color(scheme.background)), onSurfaceVariant: Color(scheme.onSurfaceVariant), ); + } + + ThemeData _themeFromColorScheme(ColorScheme scheme) { return ThemeData( useMaterial3: true, - colorScheme: colorScheme, + bottomAppBarColor: scheme.surface, + brightness: scheme.brightness, + colorScheme: scheme, + dialogBackgroundColor: scheme.surface, + dialogTheme: DialogTheme(backgroundColor: scheme.surface), + scaffoldBackgroundColor: scheme.surface, + toggleableActiveColor: scheme.primary, ); } } diff --git a/lib/screens/settings/screen_settings.dart b/lib/screens/settings/screen_settings.dart index 956a47c..b040f3e 100644 --- a/lib/screens/settings/screen_settings.dart +++ b/lib/screens/settings/screen_settings.dart @@ -13,7 +13,6 @@ class SettingsScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: Theme.of(context).colorScheme.surface, body: SafeArea( top: false, child: CustomScrollView( diff --git a/pubspec.yaml b/pubspec.yaml index d916082..7db6864 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,6 +9,7 @@ environment: dependencies: camera: 0.10.0+4 exif: 3.1.2 + dynamic_color: 1.5.4 flutter: sdk: flutter flutter_bloc: 8.1.1 @@ -28,7 +29,6 @@ dev_dependencies: flutter_launcher_icons: 0.11.0 flutter_lints: 2.0.0 flutter_native_splash: 2.2.16 - test: 1.21.6 dependency_overrides: material_color_utilities: 0.2.0