Moved ThemeProvider functionality to EnumProviders

This commit is contained in:
Vadim 2023-08-13 16:46:13 +02:00
parent c8c96b851e
commit d2d57f5fb9
10 changed files with 271 additions and 324 deletions

View file

@ -6,9 +6,9 @@ import 'package:lightmeter/environment.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers.dart'; import 'package:lightmeter/providers.dart';
import 'package:lightmeter/providers/enum_providers.dart'; import 'package:lightmeter/providers/enum_providers.dart';
import 'package:lightmeter/res/theme.dart';
import 'package:lightmeter/screens/metering/flow_metering.dart'; import 'package:lightmeter/screens/metering/flow_metering.dart';
import 'package:lightmeter/screens/settings/flow_settings.dart'; import 'package:lightmeter/screens/settings/flow_settings.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
class Application extends StatelessWidget { class Application extends StatelessWidget {
final Environment env; final Environment env;
@ -19,10 +19,25 @@ class Application extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return LightmeterProviders( return LightmeterProviders(
env: env, env: env,
builder: (context, ready) => ready builder: (context, ready) {
? _AnnotatedRegionWrapper( if (ready) {
final theme = themeFrom(
EnumProviders.primaryColorOf(context),
EnumProviders.brightnessOf(context),
);
final systemIconsBrightness =
ThemeData.estimateBrightnessForColor(theme.colorScheme.onSurface);
return AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarBrightness:
systemIconsBrightness == Brightness.light ? Brightness.dark : Brightness.light,
statusBarIconBrightness: systemIconsBrightness,
systemNavigationBarColor: Colors.transparent,
systemNavigationBarIconBrightness: systemIconsBrightness,
),
child: MaterialApp( child: MaterialApp(
theme: context.listen<ThemeData>(), theme: theme,
locale: Locale(EnumProviders.localeOf(context).intlName), locale: Locale(EnumProviders.localeOf(context).intlName),
localizationsDelegates: const [ localizationsDelegates: const [
S.delegate, S.delegate,
@ -41,32 +56,11 @@ class Application extends StatelessWidget {
"settings": (context) => const SettingsFlow(), "settings": (context) => const SettingsFlow(),
}, },
), ),
) );
: const SizedBox(), } else {
); return const SizedBox();
} }
} },
class _AnnotatedRegionWrapper extends StatelessWidget {
final Widget child;
const _AnnotatedRegionWrapper({required this.child});
@override
Widget build(BuildContext context) {
final systemIconsBrightness = ThemeData.estimateBrightnessForColor(
context.listen<ThemeData>().colorScheme.onSurface,
);
return AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarBrightness:
systemIconsBrightness == Brightness.light ? Brightness.dark : Brightness.light,
statusBarIconBrightness: systemIconsBrightness,
systemNavigationBarColor: Colors.transparent,
systemNavigationBarIconBrightness: systemIconsBrightness,
),
child: child,
); );
} }
} }

View file

@ -10,7 +10,6 @@ import 'package:lightmeter/providers/enum_providers.dart';
import 'package:lightmeter/providers/equipment_profile_provider.dart'; import 'package:lightmeter/providers/equipment_profile_provider.dart';
import 'package:lightmeter/providers/metering_screen_layout_provider.dart'; import 'package:lightmeter/providers/metering_screen_layout_provider.dart';
import 'package:lightmeter/providers/service_providers.dart'; import 'package:lightmeter/providers/service_providers.dart';
import 'package:lightmeter/providers/theme_provider.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -40,14 +39,12 @@ class LightmeterProviders extends StatelessWidget {
child: EnumProviders( child: EnumProviders(
child: MeteringScreenLayoutProvider( child: MeteringScreenLayoutProvider(
child: EquipmentProfileProvider( child: EquipmentProfileProvider(
child: ThemeProvider(
child: Builder( child: Builder(
builder: (context) => builder(context, true), builder: (context) => builder(context, true),
), ),
), ),
), ),
), ),
),
); );
} else if (snapshot.error != null) { } else if (snapshot.error != null) {
return Center(child: Text(snapshot.error!.toString())); return Center(child: Text(snapshot.error!.toString()));

View file

@ -1,4 +1,7 @@
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:lightmeter/data/models/dynamic_colors_state.dart';
import 'package:lightmeter/data/models/ev_source_type.dart'; import 'package:lightmeter/data/models/ev_source_type.dart';
import 'package:lightmeter/data/models/supported_locale.dart'; import 'package:lightmeter/data/models/supported_locale.dart';
import 'package:lightmeter/data/models/theme_type.dart'; import 'package:lightmeter/data/models/theme_type.dart';
@ -8,8 +11,11 @@ import 'package:lightmeter/providers/service_providers.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
enum _ListenableAspect { enum _ListenableAspect {
brightness,
dynamicColorState,
evSourceType, evSourceType,
locale, locale,
primaryColor,
stopType, stopType,
themeType, themeType,
} }
@ -23,6 +29,22 @@ class EnumProviders extends StatefulWidget {
return context.findAncestorStateOfType<_EnumProvidersState>()!; return context.findAncestorStateOfType<_EnumProvidersState>()!;
} }
static Brightness brightnessOf(BuildContext context) {
return InheritedModel.inheritFrom<_EnumProvidersModel>(
context,
aspect: _ListenableAspect.brightness,
)!
.brightness;
}
static DynamicColorState dynamicColorStateOf(BuildContext context) {
return InheritedModel.inheritFrom<_EnumProvidersModel>(
context,
aspect: _ListenableAspect.dynamicColorState,
)!
.dynamicColorState;
}
static EvSourceType evSourceTypeOf(BuildContext context) { static EvSourceType evSourceTypeOf(BuildContext context) {
return InheritedModel.inheritFrom<_EnumProvidersModel>( return InheritedModel.inheritFrom<_EnumProvidersModel>(
context, context,
@ -39,6 +61,14 @@ class EnumProviders extends StatefulWidget {
.locale; .locale;
} }
static Color primaryColorOf(BuildContext context) {
return InheritedModel.inheritFrom<_EnumProvidersModel>(
context,
aspect: _ListenableAspect.primaryColor,
)!
.primaryColor;
}
static StopType stopTypeOf(BuildContext context) { static StopType stopTypeOf(BuildContext context) {
return InheritedModel.inheritFrom<_EnumProvidersModel>( return InheritedModel.inheritFrom<_EnumProvidersModel>(
context, context,
@ -59,11 +89,13 @@ class EnumProviders extends StatefulWidget {
State<EnumProviders> createState() => _EnumProvidersState(); State<EnumProviders> createState() => _EnumProvidersState();
} }
class _EnumProvidersState extends State<EnumProviders> { class _EnumProvidersState extends State<EnumProviders> with WidgetsBindingObserver {
UserPreferencesService get userPreferencesService => UserPreferencesService get userPreferencesService =>
ServiceProviders.userPreferencesServiceOf(context); ServiceProviders.userPreferencesServiceOf(context);
late bool dynamicColor = userPreferencesService.dynamicColor;
late EvSourceType evSourceType; late EvSourceType evSourceType;
late Color primaryColor = userPreferencesService.primaryColor;
late StopType stopType = userPreferencesService.stopType; late StopType stopType = userPreferencesService.stopType;
late SupportedLocale locale = userPreferencesService.locale; late SupportedLocale locale = userPreferencesService.locale;
late ThemeType themeType = userPreferencesService.themeType; late ThemeType themeType = userPreferencesService.themeType;
@ -76,17 +108,59 @@ class _EnumProvidersState extends State<EnumProviders> {
!ServiceProviders.environmentOf(context).hasLightSensor !ServiceProviders.environmentOf(context).hasLightSensor
? EvSourceType.camera ? EvSourceType.camera
: evSourceType; : evSourceType;
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangePlatformBrightness() {
super.didChangePlatformBrightness();
setState(() {});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DynamicColorBuilder(
builder: (lightDynamic, darkDynamic) {
late final DynamicColorState state;
late final Color? dynamicPrimaryColor;
if (lightDynamic != null && darkDynamic != null) {
if (dynamicColor) {
dynamicPrimaryColor =
(_themeBrightness == Brightness.light ? lightDynamic : darkDynamic).primary;
state = DynamicColorState.enabled;
} else {
dynamicPrimaryColor = null;
state = DynamicColorState.disabled;
}
} else {
dynamicPrimaryColor = null;
state = DynamicColorState.unavailable;
}
return _EnumProvidersModel( return _EnumProvidersModel(
brightness: _themeBrightness,
dynamicColorState: state,
evSourceType: evSourceType, evSourceType: evSourceType,
locale: locale, locale: locale,
primaryColor: dynamicPrimaryColor ?? primaryColor,
stopType: stopType, stopType: stopType,
themeType: themeType, themeType: themeType,
child: widget.child, child: widget.child,
); );
},
);
}
void enableDynamicColor(bool enable) {
setState(() {
dynamicColor = enable;
});
ServiceProviders.userPreferencesServiceOf(context).dynamicColor = enable;
} }
void toggleEvSourceType() { void toggleEvSourceType() {
@ -113,6 +187,13 @@ class _EnumProvidersState extends State<EnumProviders> {
}); });
} }
void setPrimaryColor(Color primaryColor) {
setState(() {
this.primaryColor = primaryColor;
});
ServiceProviders.userPreferencesServiceOf(context).primaryColor = primaryColor;
}
void setStopType(StopType stopType) { void setStopType(StopType stopType) {
setState(() { setState(() {
this.stopType = stopType; this.stopType = stopType;
@ -126,17 +207,34 @@ class _EnumProvidersState extends State<EnumProviders> {
}); });
ServiceProviders.userPreferencesServiceOf(context).themeType = themeType; ServiceProviders.userPreferencesServiceOf(context).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;
}
}
} }
class _EnumProvidersModel extends InheritedModel<_ListenableAspect> { class _EnumProvidersModel extends InheritedModel<_ListenableAspect> {
final Brightness brightness;
final DynamicColorState dynamicColorState;
final EvSourceType evSourceType; final EvSourceType evSourceType;
final SupportedLocale locale; final SupportedLocale locale;
final Color primaryColor;
final StopType stopType; final StopType stopType;
final ThemeType themeType; final ThemeType themeType;
const _EnumProvidersModel({ const _EnumProvidersModel({
required this.brightness,
required this.dynamicColorState,
required this.evSourceType, required this.evSourceType,
required this.locale, required this.locale,
required this.primaryColor,
required this.stopType, required this.stopType,
required this.themeType, required this.themeType,
required super.child, required super.child,
@ -144,8 +242,11 @@ class _EnumProvidersModel extends InheritedModel<_ListenableAspect> {
@override @override
bool updateShouldNotify(_EnumProvidersModel oldWidget) { bool updateShouldNotify(_EnumProvidersModel oldWidget) {
return evSourceType != oldWidget.evSourceType || return brightness != oldWidget.brightness ||
dynamicColorState != oldWidget.dynamicColorState ||
evSourceType != oldWidget.evSourceType ||
locale != oldWidget.locale || locale != oldWidget.locale ||
primaryColor != oldWidget.primaryColor ||
stopType != oldWidget.stopType || stopType != oldWidget.stopType ||
themeType != oldWidget.themeType; themeType != oldWidget.themeType;
} }
@ -155,9 +256,15 @@ class _EnumProvidersModel extends InheritedModel<_ListenableAspect> {
_EnumProvidersModel oldWidget, _EnumProvidersModel oldWidget,
Set<_ListenableAspect> dependencies, Set<_ListenableAspect> dependencies,
) { ) {
return (evSourceType != oldWidget.evSourceType && return (brightness != oldWidget.brightness &&
dependencies.contains(_ListenableAspect.brightness)) ||
(dynamicColorState != oldWidget.dynamicColorState &&
dependencies.contains(_ListenableAspect.dynamicColorState)) ||
(evSourceType != oldWidget.evSourceType &&
dependencies.contains(_ListenableAspect.evSourceType)) || dependencies.contains(_ListenableAspect.evSourceType)) ||
(locale != oldWidget.locale && dependencies.contains(_ListenableAspect.locale)) || (locale != oldWidget.locale && dependencies.contains(_ListenableAspect.locale)) ||
(primaryColor != oldWidget.primaryColor &&
dependencies.contains(_ListenableAspect.primaryColor)) ||
(stopType != oldWidget.stopType && dependencies.contains(_ListenableAspect.stopType)) || (stopType != oldWidget.stopType && dependencies.contains(_ListenableAspect.stopType)) ||
(themeType != oldWidget.themeType && dependencies.contains(_ListenableAspect.themeType)); (themeType != oldWidget.themeType && dependencies.contains(_ListenableAspect.themeType));
} }

View file

@ -1,246 +0,0 @@
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:lightmeter/data/models/dynamic_colors_state.dart';
import 'package:lightmeter/data/models/theme_type.dart';
import 'package:lightmeter/data/shared_prefs_service.dart';
import 'package:lightmeter/providers/enum_providers.dart';
import 'package:lightmeter/providers/service_providers.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:material_color_utilities/material_color_utilities.dart';
class ThemeProvider extends StatefulWidget {
final Widget child;
const ThemeProvider({
required this.child,
super.key,
});
static ThemeProviderState of(BuildContext context) {
return context.findAncestorStateOfType<ThemeProviderState>()!;
}
static const primaryColorsList = [
Color(0xfff44336),
Color(0xffe91e63),
Color(0xff9c27b0),
Color(0xff673ab7),
Color(0xff3f51b5),
Color(0xff2196f3),
Color(0xff03a9f4),
Color(0xff00bcd4),
Color(0xff009688),
Color(0xff4caf50),
Color(0xff8bc34a),
Color(0xffcddc39),
Color(0xffffeb3b),
Color(0xffffc107),
Color(0xffff9800),
Color(0xffff5722),
];
@override
State<ThemeProvider> createState() => ThemeProviderState();
}
class ThemeProviderState extends State<ThemeProvider> with WidgetsBindingObserver {
UserPreferencesService get _prefs => ServiceProviders.userPreferencesServiceOf(context);
late final _dynamicColorNotifier = ValueNotifier<bool>(_prefs.dynamicColor);
late final _primaryColorNotifier = ValueNotifier<Color>(_prefs.primaryColor);
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangePlatformBrightness() {
super.didChangePlatformBrightness();
setState(() {});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
_dynamicColorNotifier.dispose();
_primaryColorNotifier.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: _dynamicColorNotifier,
builder: (_, useDynamicColor, __) => _DynamicColorProvider(
useDynamicColor: useDynamicColor,
themeBrightness: _themeBrightness,
builder: (_, dynamicPrimaryColor) => ValueListenableBuilder(
valueListenable: _primaryColorNotifier,
builder: (_, primaryColor, __) => _ThemeDataProvider(
primaryColor: dynamicPrimaryColor ?? primaryColor,
brightness: _themeBrightness,
child: widget.child,
),
),
),
);
}
Brightness get _themeBrightness {
switch (EnumProviders.themeTypeOf(context)) {
case ThemeType.light:
return Brightness.light;
case ThemeType.dark:
return Brightness.dark;
case ThemeType.systemDefault:
return SchedulerBinding.instance.platformDispatcher.platformBrightness;
}
}
void setPrimaryColor(Color color) {
_primaryColorNotifier.value = color;
_prefs.primaryColor = color;
}
void enableDynamicColor(bool enable) {
_dynamicColorNotifier.value = enable;
_prefs.dynamicColor = enable;
}
}
class _DynamicColorProvider extends StatelessWidget {
final bool useDynamicColor;
final Brightness themeBrightness;
final Widget Function(BuildContext context, Color? primaryColor) builder;
const _DynamicColorProvider({
required this.useDynamicColor,
required this.themeBrightness,
required this.builder,
});
@override
Widget build(BuildContext context) {
return DynamicColorBuilder(
builder: (lightDynamic, darkDynamic) {
late final DynamicColorState state;
late final Color? dynamicPrimaryColor;
if (lightDynamic != null && darkDynamic != null) {
if (useDynamicColor) {
dynamicPrimaryColor =
(themeBrightness == Brightness.light ? lightDynamic : darkDynamic).primary;
state = DynamicColorState.enabled;
} else {
dynamicPrimaryColor = null;
state = DynamicColorState.disabled;
}
} else {
dynamicPrimaryColor = null;
state = DynamicColorState.unavailable;
}
return InheritedWidgetBase<DynamicColorState>(
data: state,
child: builder(context, dynamicPrimaryColor),
);
},
);
}
}
class _ThemeDataProvider extends StatelessWidget {
final Color primaryColor;
final Brightness brightness;
final Widget child;
const _ThemeDataProvider({
required this.primaryColor,
required this.brightness,
required this.child,
});
@override
Widget build(BuildContext context) {
return InheritedWidgetBase<ThemeData>(
data: _themeFromColorScheme(_colorSchemeFromColor()),
child: child,
);
}
ThemeData _themeFromColorScheme(ColorScheme scheme) {
return ThemeData(
useMaterial3: true,
brightness: scheme.brightness,
primaryColor: primaryColor,
colorScheme: scheme,
appBarTheme: AppBarTheme(
elevation: 4,
color: scheme.surface,
surfaceTintColor: scheme.surfaceTint,
),
cardTheme: CardTheme(
clipBehavior: Clip.antiAlias,
color: scheme.surface,
elevation: 4,
margin: EdgeInsets.zero,
shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(Dimens.borderRadiusL)),
surfaceTintColor: scheme.surfaceTint,
),
dialogBackgroundColor: scheme.surface,
dialogTheme: DialogTheme(
backgroundColor: scheme.surface,
surfaceTintColor: scheme.surfaceTint,
elevation: 6,
),
dividerColor: scheme.outlineVariant,
dividerTheme: DividerThemeData(
color: scheme.outlineVariant,
space: 0,
),
listTileTheme: ListTileThemeData(
style: ListTileStyle.list,
iconColor: scheme.onSurface,
textColor: scheme.onSurface,
),
scaffoldBackgroundColor: scheme.surface,
);
}
ColorScheme _colorSchemeFromColor() {
final scheme = brightness == Brightness.light
? Scheme.light(primaryColor.value)
: Scheme.dark(primaryColor.value);
return ColorScheme(
brightness: brightness,
background: Color(scheme.background),
error: Color(scheme.error),
errorContainer: Color(scheme.errorContainer),
onBackground: Color(scheme.onBackground),
onError: Color(scheme.onError),
onErrorContainer: Color(scheme.onErrorContainer),
primary: Color(scheme.primary),
onPrimary: Color(scheme.onPrimary),
primaryContainer: Color(scheme.primaryContainer),
onPrimaryContainer: Color(scheme.onPrimaryContainer),
secondary: Color(scheme.secondary),
onSecondary: Color(scheme.onSecondary),
surface: Color.alphaBlend(
Color(scheme.primary).withOpacity(0.05),
Color(scheme.background),
),
onSurface: Color(scheme.onSurface),
surfaceVariant: Color.alphaBlend(
Color(scheme.primary).withOpacity(0.5),
Color(scheme.background),
),
onSurfaceVariant: Color(scheme.onSurfaceVariant),
outline: Color(scheme.outline),
outlineVariant: Color(scheme.outlineVariant),
);
}
}

97
lib/res/theme.dart Normal file
View file

@ -0,0 +1,97 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:material_color_utilities/material_color_utilities.dart';
const primaryColorsList = [
Color(0xfff44336),
Color(0xffe91e63),
Color(0xff9c27b0),
Color(0xff673ab7),
Color(0xff3f51b5),
Color(0xff2196f3),
Color(0xff03a9f4),
Color(0xff00bcd4),
Color(0xff009688),
Color(0xff4caf50),
Color(0xff8bc34a),
Color(0xffcddc39),
Color(0xffffeb3b),
Color(0xffffc107),
Color(0xffff9800),
Color(0xffff5722),
];
ThemeData themeFrom(Color primaryColor, Brightness brightness) {
final scheme = _colorSchemeFromColor(primaryColor, brightness);
return ThemeData(
useMaterial3: true,
brightness: scheme.brightness,
primaryColor: primaryColor,
colorScheme: scheme,
appBarTheme: AppBarTheme(
elevation: 4,
color: scheme.surface,
surfaceTintColor: scheme.surfaceTint,
),
cardTheme: CardTheme(
clipBehavior: Clip.antiAlias,
color: scheme.surface,
elevation: 4,
margin: EdgeInsets.zero,
shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(Dimens.borderRadiusL)),
surfaceTintColor: scheme.surfaceTint,
),
dialogBackgroundColor: scheme.surface,
dialogTheme: DialogTheme(
backgroundColor: scheme.surface,
surfaceTintColor: scheme.surfaceTint,
elevation: 6,
),
dividerColor: scheme.outlineVariant,
dividerTheme: DividerThemeData(
color: scheme.outlineVariant,
space: 0,
),
listTileTheme: ListTileThemeData(
style: ListTileStyle.list,
iconColor: scheme.onSurface,
textColor: scheme.onSurface,
),
scaffoldBackgroundColor: scheme.surface,
);
}
ColorScheme _colorSchemeFromColor(Color primaryColor, Brightness brightness) {
final scheme = brightness == Brightness.light
? Scheme.light(primaryColor.value)
: Scheme.dark(primaryColor.value);
return ColorScheme(
brightness: brightness,
background: Color(scheme.background),
error: Color(scheme.error),
errorContainer: Color(scheme.errorContainer),
onBackground: Color(scheme.onBackground),
onError: Color(scheme.onError),
onErrorContainer: Color(scheme.onErrorContainer),
primary: Color(scheme.primary),
onPrimary: Color(scheme.onPrimary),
primaryContainer: Color(scheme.primaryContainer),
onPrimaryContainer: Color(scheme.onPrimaryContainer),
secondary: Color(scheme.secondary),
onSecondary: Color(scheme.onSecondary),
surface: Color.alphaBlend(
Color(scheme.primary).withOpacity(0.05),
Color(scheme.background),
),
onSurface: Color(scheme.onSurface),
surfaceVariant: Color.alphaBlend(
Color(scheme.primary).withOpacity(0.5),
Color(scheme.background),
),
onSurfaceVariant: Color(scheme.onSurfaceVariant),
outline: Color(scheme.outline),
outlineVariant: Color(scheme.outlineVariant),
);
}

View file

@ -1,9 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/dynamic_colors_state.dart'; import 'package:lightmeter/data/models/dynamic_colors_state.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/theme_provider.dart'; import 'package:lightmeter/providers/enum_providers.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
class DynamicColorListTile extends StatelessWidget { class DynamicColorListTile extends StatelessWidget {
const DynamicColorListTile({super.key}); const DynamicColorListTile({super.key});
@ -13,8 +12,8 @@ class DynamicColorListTile extends StatelessWidget {
return SwitchListTile( return SwitchListTile(
secondary: const Icon(Icons.colorize), secondary: const Icon(Icons.colorize),
title: Text(S.of(context).dynamicColor), title: Text(S.of(context).dynamicColor),
value: context.listen<DynamicColorState>() == DynamicColorState.enabled, value: EnumProviders.dynamicColorStateOf(context) == DynamicColorState.enabled,
onChanged: ThemeProvider.of(context).enableDynamicColor, onChanged: EnumProviders.of(context).enableDynamicColor,
contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM), contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
); );
} }

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/theme_provider.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/res/theme.dart';
import 'package:lightmeter/screens/shared/filled_circle/widget_circle_filled.dart'; import 'package:lightmeter/screens/shared/filled_circle/widget_circle_filled.dart';
class PrimaryColorDialogPicker extends StatefulWidget { class PrimaryColorDialogPicker extends StatefulWidget {
@ -38,9 +38,9 @@ class _PrimaryColorDialogPickerState extends State<PrimaryColorDialogPicker> {
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
child: Row( child: Row(
children: List.generate( children: List.generate(
ThemeProvider.primaryColorsList.length, primaryColorsList.length,
(index) { (index) {
final color = ThemeProvider.primaryColorsList[index]; final color = primaryColorsList[index];
return Padding( return Padding(
padding: EdgeInsets.only(left: index == 0 ? 0 : Dimens.paddingS), padding: EdgeInsets.only(left: index == 0 ? 0 : Dimens.paddingS),
child: _SelectableColorItem( child: _SelectableColorItem(

View file

@ -1,17 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/dynamic_colors_state.dart'; import 'package:lightmeter/data/models/dynamic_colors_state.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/theme_provider.dart'; import 'package:lightmeter/providers/enum_providers.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/settings/components/theme/components/primary_color/components/primary_color_picker_dialog/widget_dialog_picker_primary_color.dart'; import 'package:lightmeter/screens/settings/components/theme/components/primary_color/components/primary_color_picker_dialog/widget_dialog_picker_primary_color.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
class PrimaryColorListTile extends StatelessWidget { class PrimaryColorListTile extends StatelessWidget {
const PrimaryColorListTile({super.key}); const PrimaryColorListTile({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (context.listen<DynamicColorState>() == DynamicColorState.enabled) { if (EnumProviders.dynamicColorStateOf(context) == DynamicColorState.enabled) {
return Opacity( return Opacity(
opacity: Dimens.disabledOpacity, opacity: Dimens.disabledOpacity,
child: IgnorePointer( child: IgnorePointer(
@ -31,7 +30,7 @@ class PrimaryColorListTile extends StatelessWidget {
builder: (_) => const PrimaryColorDialogPicker(), builder: (_) => const PrimaryColorDialogPicker(),
).then((value) { ).then((value) {
if (value != null) { if (value != null) {
ThemeProvider.of(context).setPrimaryColor(value); EnumProviders.of(context).setPrimaryColor(value);
} }
}); });
}, },

View file

@ -1,11 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/dynamic_colors_state.dart'; import 'package:lightmeter/data/models/dynamic_colors_state.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/enum_providers.dart';
import 'package:lightmeter/screens/settings/components/shared/settings_section/widget_settings_section.dart'; import 'package:lightmeter/screens/settings/components/shared/settings_section/widget_settings_section.dart';
import 'package:lightmeter/screens/settings/components/theme/components/dynamic_color/widget_list_tile_dynamic_color.dart'; import 'package:lightmeter/screens/settings/components/theme/components/dynamic_color/widget_list_tile_dynamic_color.dart';
import 'package:lightmeter/screens/settings/components/theme/components/primary_color/widget_list_tile_primary_color.dart'; import 'package:lightmeter/screens/settings/components/theme/components/primary_color/widget_list_tile_primary_color.dart';
import 'package:lightmeter/screens/settings/components/theme/components/theme_type/widget_list_tile_theme_type.dart'; import 'package:lightmeter/screens/settings/components/theme/components/theme_type/widget_list_tile_theme_type.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
class ThemeSettingsSection extends StatelessWidget { class ThemeSettingsSection extends StatelessWidget {
const ThemeSettingsSection({super.key}); const ThemeSettingsSection({super.key});
@ -17,7 +17,7 @@ class ThemeSettingsSection extends StatelessWidget {
children: [ children: [
const ThemeTypeListTile(), const ThemeTypeListTile(),
const PrimaryColorListTile(), const PrimaryColorListTile(),
if (context.get<DynamicColorState>() != DynamicColorState.unavailable) if (EnumProviders.dynamicColorStateOf(context) != DynamicColorState.unavailable)
const DynamicColorListTile(), const DynamicColorListTile(),
], ],
); );

View file

@ -6,7 +6,7 @@ import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
import 'package:lightmeter/data/models/supported_locale.dart'; import 'package:lightmeter/data/models/supported_locale.dart';
import 'package:lightmeter/data/models/theme_type.dart'; import 'package:lightmeter/data/models/theme_type.dart';
import 'package:lightmeter/data/shared_prefs_service.dart'; import 'package:lightmeter/data/shared_prefs_service.dart';
import 'package:lightmeter/providers/theme_provider.dart'; import 'package:lightmeter/res/theme.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import 'package:mocktail/mocktail.dart'; import 'package:mocktail/mocktail.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -348,13 +348,13 @@ void main() {
group('primaryColor', () { group('primaryColor', () {
test('get default', () { test('get default', () {
when(() => sharedPreferences.getInt(UserPreferencesService.primaryColorKey)).thenReturn(null); when(() => sharedPreferences.getInt(UserPreferencesService.primaryColorKey)).thenReturn(null);
expect(service.primaryColor, ThemeProvider.primaryColorsList[5]); expect(service.primaryColor, primaryColorsList[5]);
}); });
test('get', () { test('get', () {
when(() => sharedPreferences.getInt(UserPreferencesService.primaryColorKey)) when(() => sharedPreferences.getInt(UserPreferencesService.primaryColorKey))
.thenReturn(0xff9c27b0); .thenReturn(0xff9c27b0);
expect(service.primaryColor, ThemeProvider.primaryColorsList[2]); expect(service.primaryColor, primaryColorsList[2]);
}); });
test('set', () { test('set', () {