Moved MeteringScreenLayoutProvider functionality to UserPreferencesProvider

This commit is contained in:
Vadim 2023-08-13 21:14:12 +02:00
parent a8aabcc5b8
commit 7dc3f22c66
8 changed files with 90 additions and 98 deletions

View file

@ -6,10 +6,9 @@ import 'package:lightmeter/data/permissions_service.dart';
import 'package:lightmeter/data/shared_prefs_service.dart'; import 'package:lightmeter/data/shared_prefs_service.dart';
import 'package:lightmeter/data/volume_events_service.dart'; import 'package:lightmeter/data/volume_events_service.dart';
import 'package:lightmeter/environment.dart'; import 'package:lightmeter/environment.dart';
import 'package:lightmeter/providers/user_preferences_provider.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/service_provider.dart'; import 'package:lightmeter/providers/service_provider.dart';
import 'package:lightmeter/providers/user_preferences_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';
@ -37,11 +36,9 @@ class LightmeterProviders extends StatelessWidget {
userPreferencesService: UserPreferencesService(snapshot.data![0] as SharedPreferences), userPreferencesService: UserPreferencesService(snapshot.data![0] as SharedPreferences),
volumeEventsService: const VolumeEventsService(LocalPlatform()), volumeEventsService: const VolumeEventsService(LocalPlatform()),
child: UserPreferencesProvider( child: UserPreferencesProvider(
child: MeteringScreenLayoutProvider( child: EquipmentProfileProvider(
child: EquipmentProfileProvider( child: Builder(
child: Builder( builder: (context) => builder(context, true),
builder: (context) => builder(context, true),
),
), ),
), ),
), ),

View file

@ -1,60 +0,0 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
import 'package:lightmeter/providers/service_provider.dart';
import 'package:lightmeter/utils/inherited_generics.dart';
class MeteringScreenLayoutProvider extends StatefulWidget {
final Widget child;
const MeteringScreenLayoutProvider({required this.child, super.key});
static MeteringScreenLayoutProviderState of(BuildContext context) {
return context.findAncestorStateOfType<MeteringScreenLayoutProviderState>()!;
}
@override
State<MeteringScreenLayoutProvider> createState() => MeteringScreenLayoutProviderState();
}
class MeteringScreenLayoutProviderState extends State<MeteringScreenLayoutProvider> {
late final MeteringScreenLayoutConfig _config =
ServiceProvider.userPreferencesServiceOf(context).meteringScreenLayout;
@override
Widget build(BuildContext context) {
return InheritedModelBase<MeteringScreenLayoutFeature, bool>(
data: MeteringScreenLayoutConfig.from(_config),
child: widget.child,
);
}
void updateFeatures(MeteringScreenLayoutConfig config) {
setState(() {
config.forEach((key, value) {
_config.update(
key,
(_) => value,
ifAbsent: () => value,
);
});
});
ServiceProvider.userPreferencesServiceOf(context).meteringScreenLayout = _config;
}
}
typedef _MeteringScreenLayoutModel = InheritedModelBase<MeteringScreenLayoutFeature, bool>;
extension MeteringScreenLayout on InheritedModelBase<MeteringScreenLayoutFeature, bool> {
static MeteringScreenLayoutConfig of(BuildContext context, {bool listen = true}) {
if (listen) {
return context.dependOnInheritedWidgetOfExactType<_MeteringScreenLayoutModel>()!.data;
} else {
return context.findAncestorWidgetOfExactType<_MeteringScreenLayoutModel>()!.data;
}
}
static bool featureOf(BuildContext context, MeteringScreenLayoutFeature aspect) {
return InheritedModel.inheritFrom<_MeteringScreenLayoutModel>(context, aspect: aspect)!
.data[aspect]!;
}
}

View file

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:lightmeter/data/models/dynamic_colors_state.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/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';
@ -10,16 +11,6 @@ import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/service_provider.dart'; import 'package:lightmeter/providers/service_provider.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
enum _ListenableAspect {
brightness,
dynamicColorState,
evSourceType,
locale,
primaryColor,
stopType,
themeType,
}
class UserPreferencesProvider extends StatefulWidget { class UserPreferencesProvider extends StatefulWidget {
final Widget child; final Widget child;
@ -45,6 +36,15 @@ class UserPreferencesProvider extends StatefulWidget {
return _inheritFrom(context, _ListenableAspect.locale).locale; return _inheritFrom(context, _ListenableAspect.locale).locale;
} }
static MeteringScreenLayoutConfig meteringScreenConfigOf(BuildContext context) {
return context.findAncestorWidgetOfExactType<_MeteringScreenLayoutModel>()!.data;
}
static bool meteringScreenFeatureOf(BuildContext context, MeteringScreenLayoutFeature feature) {
return InheritedModel.inheritFrom<_MeteringScreenLayoutModel>(context, aspect: feature)!
.data[feature]!;
}
static Color primaryColorOf(BuildContext context) { static Color primaryColorOf(BuildContext context) {
return _inheritFrom(context, _ListenableAspect.primaryColor).primaryColor; return _inheritFrom(context, _ListenableAspect.primaryColor).primaryColor;
} }
@ -57,9 +57,11 @@ class UserPreferencesProvider extends StatefulWidget {
return _inheritFrom(context, _ListenableAspect.themeType).themeType; return _inheritFrom(context, _ListenableAspect.themeType).themeType;
} }
static _UserPreferencesProviderModel _inheritFrom( static _EnumsModel _inheritFrom(
BuildContext context, _ListenableAspect aspect) { BuildContext context,
return InheritedModel.inheritFrom<_UserPreferencesProviderModel>(context, aspect: aspect)!; _ListenableAspect aspect,
) {
return InheritedModel.inheritFrom<_EnumsModel>(context, aspect: aspect)!;
} }
@override @override
@ -73,6 +75,8 @@ class _UserPreferencesProviderState extends State<UserPreferencesProvider>
late bool dynamicColor = userPreferencesService.dynamicColor; late bool dynamicColor = userPreferencesService.dynamicColor;
late EvSourceType evSourceType; late EvSourceType evSourceType;
late final MeteringScreenLayoutConfig meteringScreenLayout =
ServiceProvider.userPreferencesServiceOf(context).meteringScreenLayout;
late Color primaryColor = userPreferencesService.primaryColor; 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;
@ -120,7 +124,7 @@ class _UserPreferencesProviderState extends State<UserPreferencesProvider>
dynamicPrimaryColor = null; dynamicPrimaryColor = null;
state = DynamicColorState.unavailable; state = DynamicColorState.unavailable;
} }
return _UserPreferencesProviderModel( return _EnumsModel(
brightness: _themeBrightness, brightness: _themeBrightness,
dynamicColorState: state, dynamicColorState: state,
evSourceType: evSourceType, evSourceType: evSourceType,
@ -128,7 +132,10 @@ class _UserPreferencesProviderState extends State<UserPreferencesProvider>
primaryColor: dynamicPrimaryColor ?? primaryColor, primaryColor: dynamicPrimaryColor ?? primaryColor,
stopType: stopType, stopType: stopType,
themeType: themeType, themeType: themeType,
child: widget.child, child: _MeteringScreenLayoutModel(
data: meteringScreenLayout,
child: widget.child,
),
); );
}, },
); );
@ -165,6 +172,19 @@ class _UserPreferencesProviderState extends State<UserPreferencesProvider>
}); });
} }
void setMeteringScreenLayout(MeteringScreenLayoutConfig config) {
setState(() {
config.forEach((key, value) {
meteringScreenLayout.update(
key,
(_) => value,
ifAbsent: () => value,
);
});
});
ServiceProvider.userPreferencesServiceOf(context).meteringScreenLayout = meteringScreenLayout;
}
void setPrimaryColor(Color primaryColor) { void setPrimaryColor(Color primaryColor) {
setState(() { setState(() {
this.primaryColor = primaryColor; this.primaryColor = primaryColor;
@ -198,7 +218,17 @@ class _UserPreferencesProviderState extends State<UserPreferencesProvider>
} }
} }
class _UserPreferencesProviderModel extends InheritedModel<_ListenableAspect> { enum _ListenableAspect {
brightness,
dynamicColorState,
evSourceType,
locale,
primaryColor,
stopType,
themeType,
}
class _EnumsModel extends InheritedModel<_ListenableAspect> {
final Brightness brightness; final Brightness brightness;
final DynamicColorState dynamicColorState; final DynamicColorState dynamicColorState;
final EvSourceType evSourceType; final EvSourceType evSourceType;
@ -207,7 +237,7 @@ class _UserPreferencesProviderModel extends InheritedModel<_ListenableAspect> {
final StopType stopType; final StopType stopType;
final ThemeType themeType; final ThemeType themeType;
const _UserPreferencesProviderModel({ const _EnumsModel({
required this.brightness, required this.brightness,
required this.dynamicColorState, required this.dynamicColorState,
required this.evSourceType, required this.evSourceType,
@ -219,7 +249,7 @@ class _UserPreferencesProviderModel extends InheritedModel<_ListenableAspect> {
}); });
@override @override
bool updateShouldNotify(_UserPreferencesProviderModel oldWidget) { bool updateShouldNotify(_EnumsModel oldWidget) {
return brightness != oldWidget.brightness || return brightness != oldWidget.brightness ||
dynamicColorState != oldWidget.dynamicColorState || dynamicColorState != oldWidget.dynamicColorState ||
evSourceType != oldWidget.evSourceType || evSourceType != oldWidget.evSourceType ||
@ -231,7 +261,7 @@ class _UserPreferencesProviderModel extends InheritedModel<_ListenableAspect> {
@override @override
bool updateShouldNotifyDependent( bool updateShouldNotifyDependent(
_UserPreferencesProviderModel oldWidget, _EnumsModel oldWidget,
Set<_ListenableAspect> dependencies, Set<_ListenableAspect> dependencies,
) { ) {
return (brightness != oldWidget.brightness && return (brightness != oldWidget.brightness &&
@ -247,3 +277,28 @@ class _UserPreferencesProviderModel extends InheritedModel<_ListenableAspect> {
(themeType != oldWidget.themeType && dependencies.contains(_ListenableAspect.themeType)); (themeType != oldWidget.themeType && dependencies.contains(_ListenableAspect.themeType));
} }
} }
class _MeteringScreenLayoutModel extends InheritedModel<MeteringScreenLayoutFeature> {
final Map<MeteringScreenLayoutFeature, bool> data;
const _MeteringScreenLayoutModel({
required this.data,
required super.child,
});
@override
bool updateShouldNotify(_MeteringScreenLayoutModel oldWidget) => oldWidget.data != data;
@override
bool updateShouldNotifyDependent(
_MeteringScreenLayoutModel oldWidget,
Set<MeteringScreenLayoutFeature> dependencies,
) {
for (final dependecy in dependencies) {
if (oldWidget.data[dependecy] != data[dependecy]) {
return true;
}
}
return false;
}
}

View file

@ -2,7 +2,7 @@ import 'package:camera/camera.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/metering_screen_layout_config.dart'; import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
import 'package:lightmeter/platform_config.dart'; import 'package:lightmeter/platform_config.dart';
import 'package:lightmeter/providers/metering_screen_layout_provider.dart'; import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_view/widget_camera_view.dart'; import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_view/widget_camera_view.dart';
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_view_placeholder/widget_placeholder_camera_view.dart'; import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_view_placeholder/widget_placeholder_camera_view.dart';
@ -38,7 +38,7 @@ class _CameraPreviewState extends State<CameraPreview> {
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
children: [ children: [
CameraView(controller: widget.controller!), CameraView(controller: widget.controller!),
if (MeteringScreenLayout.featureOf( if (UserPreferencesProvider.meteringScreenFeatureOf(
context, context,
MeteringScreenLayoutFeature.histogram, MeteringScreenLayoutFeature.histogram,
)) ))

View file

@ -7,7 +7,7 @@ import 'package:lightmeter/data/models/film.dart';
import 'package:lightmeter/data/models/metering_screen_layout_config.dart'; import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
import 'package:lightmeter/features.dart'; import 'package:lightmeter/features.dart';
import 'package:lightmeter/platform_config.dart'; import 'package:lightmeter/platform_config.dart';
import 'package:lightmeter/providers/metering_screen_layout_provider.dart'; import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/metering/components/camera_container/bloc_container_camera.dart'; import 'package:lightmeter/screens/metering/components/camera_container/bloc_container_camera.dart';
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_controls/widget_camera_controls.dart'; import 'package:lightmeter/screens/metering/components/camera_container/components/camera_controls/widget_camera_controls.dart';
@ -114,14 +114,14 @@ class CameraContainer extends StatelessWidget {
enabledFeaturesHeight += Dimens.readingContainerSingleValueHeight; enabledFeaturesHeight += Dimens.readingContainerSingleValueHeight;
enabledFeaturesHeight += Dimens.paddingS; enabledFeaturesHeight += Dimens.paddingS;
} }
if (MeteringScreenLayout.featureOf( if (UserPreferencesProvider.meteringScreenFeatureOf(
context, context,
MeteringScreenLayoutFeature.extremeExposurePairs, MeteringScreenLayoutFeature.extremeExposurePairs,
)) { )) {
enabledFeaturesHeight += Dimens.readingContainerDoubleValueHeight; enabledFeaturesHeight += Dimens.readingContainerDoubleValueHeight;
enabledFeaturesHeight += Dimens.paddingS; enabledFeaturesHeight += Dimens.paddingS;
} }
if (MeteringScreenLayout.featureOf( if (UserPreferencesProvider.meteringScreenFeatureOf(
context, context,
MeteringScreenLayoutFeature.filmPicker, MeteringScreenLayoutFeature.filmPicker,
)) { )) {

View file

@ -5,7 +5,7 @@ import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
import 'package:lightmeter/features.dart'; import 'package:lightmeter/features.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.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/user_preferences_provider.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/metering/components/shared/readings_container/components/animated_dialog_picker/widget_picker_dialog_animated.dart'; import 'package:lightmeter/screens/metering/components/shared/readings_container/components/animated_dialog_picker/widget_picker_dialog_animated.dart';
import 'package:lightmeter/screens/metering/components/shared/readings_container/components/reading_value_container/widget_container_reading_value.dart'; import 'package:lightmeter/screens/metering/components/shared/readings_container/components/reading_value_container/widget_container_reading_value.dart';
@ -43,7 +43,7 @@ class ReadingsContainer extends StatelessWidget {
const _EquipmentProfilePicker(), const _EquipmentProfilePicker(),
const _InnerPadding(), const _InnerPadding(),
], ],
if (MeteringScreenLayout.featureOf( if (UserPreferencesProvider.meteringScreenFeatureOf(
context, context,
MeteringScreenLayoutFeature.extremeExposurePairs, MeteringScreenLayoutFeature.extremeExposurePairs,
)) ...[ )) ...[
@ -61,7 +61,7 @@ class ReadingsContainer extends StatelessWidget {
), ),
const _InnerPadding(), const _InnerPadding(),
], ],
if (MeteringScreenLayout.featureOf( if (UserPreferencesProvider.meteringScreenFeatureOf(
context, context,
MeteringScreenLayoutFeature.filmPicker, MeteringScreenLayoutFeature.filmPicker,
)) ...[ )) ...[

View file

@ -6,8 +6,8 @@ import 'package:lightmeter/data/models/ev_source_type.dart';
import 'package:lightmeter/data/models/exposure_pair.dart'; import 'package:lightmeter/data/models/exposure_pair.dart';
import 'package:lightmeter/data/models/film.dart'; import 'package:lightmeter/data/models/film.dart';
import 'package:lightmeter/data/models/metering_screen_layout_config.dart'; import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/providers/service_provider.dart'; import 'package:lightmeter/providers/service_provider.dart';
import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/screens/metering/bloc_metering.dart'; import 'package:lightmeter/screens/metering/bloc_metering.dart';
import 'package:lightmeter/screens/metering/components/bottom_controls/provider_bottom_controls.dart'; import 'package:lightmeter/screens/metering/components/bottom_controls/provider_bottom_controls.dart';
import 'package:lightmeter/screens/metering/components/camera_container/provider_container_camera.dart'; import 'package:lightmeter/screens/metering/components/camera_container/provider_container_camera.dart';

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/metering_screen_layout_config.dart'; import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/metering_screen_layout_provider.dart'; import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
class MeteringScreenLayoutFeaturesDialog extends StatefulWidget { class MeteringScreenLayoutFeaturesDialog extends StatefulWidget {
@ -14,7 +14,7 @@ class MeteringScreenLayoutFeaturesDialog extends StatefulWidget {
class _MeteringScreenLayoutFeaturesDialogState extends State<MeteringScreenLayoutFeaturesDialog> { class _MeteringScreenLayoutFeaturesDialogState extends State<MeteringScreenLayoutFeaturesDialog> {
late final _features = late final _features =
MeteringScreenLayoutConfig.from(MeteringScreenLayout.of(context, listen: false)); MeteringScreenLayoutConfig.from(UserPreferencesProvider.meteringScreenConfigOf(context));
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -56,7 +56,7 @@ class _MeteringScreenLayoutFeaturesDialogState extends State<MeteringScreenLayou
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
MeteringScreenLayoutProvider.of(context).updateFeatures(_features); UserPreferencesProvider.of(context).setMeteringScreenLayout(_features);
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
child: Text(S.of(context).save), child: Text(S.of(context).save),