added CameraFeaturesListTile to metering section

This commit is contained in:
Vadim 2023-11-08 12:54:51 +01:00
parent f4f1960fda
commit b0210d1e8c
7 changed files with 112 additions and 30 deletions

View file

@ -1,6 +1,6 @@
enum CameraFeature { enum CameraFeature {
histogram,
spotMetering, spotMetering,
histogram,
} }
typedef CameraFeaturesConfig = Map<CameraFeature, bool>; typedef CameraFeaturesConfig = Map<CameraFeature, bool>;

View file

@ -40,6 +40,9 @@
"meteringScreenFeatureExtremeExposurePairs": "Fastest & shortest exposure pairs", "meteringScreenFeatureExtremeExposurePairs": "Fastest & shortest exposure pairs",
"meteringScreenFeatureFilmPicker": "Film picker", "meteringScreenFeatureFilmPicker": "Film picker",
"meteringScreenFeatureHistogram": "Histogram", "meteringScreenFeatureHistogram": "Histogram",
"cameraFeatures": "Camera features",
"cameraFeatureSpotMetering": "Spot metering",
"cameraFeatureHistogram": "Histogram",
"film": "Film", "film": "Film",
"filmPush": "Film (push)", "filmPush": "Film (push)",
"filmPull": "Film (pull)", "filmPull": "Film (pull)",

View file

@ -1,6 +1,7 @@
import 'package:dynamic_color/dynamic_color.dart'; import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:lightmeter/data/models/camera_feature.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/metering_screen_layout_config.dart';
@ -9,6 +10,7 @@ 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/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/theme.dart'; import 'package:lightmeter/res/theme.dart';
import 'package:lightmeter/utils/map_model.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class UserPreferencesProvider extends StatefulWidget { class UserPreferencesProvider extends StatefulWidget {
@ -51,6 +53,14 @@ class UserPreferencesProvider extends StatefulWidget {
return _inheritFromEnumsModel(context, _Aspect.stopType).stopType; return _inheritFromEnumsModel(context, _Aspect.stopType).stopType;
} }
static CameraFeaturesConfig cameraConfigOf(BuildContext context) {
return context.findAncestorWidgetOfExactType<_CameraFeaturesModel>()!.data;
}
static bool cameraFeatureOf(BuildContext context, CameraFeature feature) {
return InheritedModel.inheritFrom<_CameraFeaturesModel>(context, aspect: feature)!.data[feature]!;
}
static ThemeData themeOf(BuildContext context) { static ThemeData themeOf(BuildContext context) {
return _inheritFromEnumsModel(context, _Aspect.theme).theme; return _inheritFromEnumsModel(context, _Aspect.theme).theme;
} }
@ -74,6 +84,7 @@ class _UserPreferencesProviderState extends State<UserPreferencesProvider> with
late EvSourceType _evSourceType; late EvSourceType _evSourceType;
late StopType _stopType = widget.userPreferencesService.stopType; late StopType _stopType = widget.userPreferencesService.stopType;
late MeteringScreenLayoutConfig _meteringScreenLayout = widget.userPreferencesService.meteringScreenLayout; late MeteringScreenLayoutConfig _meteringScreenLayout = widget.userPreferencesService.meteringScreenLayout;
late CameraFeaturesConfig _cameraFeatures = widget.userPreferencesService.cameraFeatures;
late SupportedLocale _locale = widget.userPreferencesService.locale; late SupportedLocale _locale = widget.userPreferencesService.locale;
late ThemeType _themeType = widget.userPreferencesService.themeType; late ThemeType _themeType = widget.userPreferencesService.themeType;
late Color _primaryColor = widget.userPreferencesService.primaryColor; late Color _primaryColor = widget.userPreferencesService.primaryColor;
@ -83,7 +94,8 @@ class _UserPreferencesProviderState extends State<UserPreferencesProvider> with
void initState() { void initState() {
super.initState(); super.initState();
_evSourceType = widget.userPreferencesService.evSourceType; _evSourceType = widget.userPreferencesService.evSourceType;
_evSourceType = _evSourceType == EvSourceType.sensor && !widget.hasLightSensor ? EvSourceType.camera : _evSourceType; _evSourceType =
_evSourceType == EvSourceType.sensor && !widget.hasLightSensor ? EvSourceType.camera : _evSourceType;
WidgetsBinding.instance.addObserver(this); WidgetsBinding.instance.addObserver(this);
} }
@ -127,8 +139,11 @@ class _UserPreferencesProviderState extends State<UserPreferencesProvider> with
themeType: _themeType, themeType: _themeType,
child: _MeteringScreenLayoutModel( child: _MeteringScreenLayoutModel(
data: _meteringScreenLayout, data: _meteringScreenLayout,
child: _CameraFeaturesModel(
data: _cameraFeatures,
child: widget.child, child: widget.child,
), ),
),
); );
}, },
); );
@ -172,6 +187,13 @@ class _UserPreferencesProviderState extends State<UserPreferencesProvider> with
widget.userPreferencesService.meteringScreenLayout = _meteringScreenLayout; widget.userPreferencesService.meteringScreenLayout = _meteringScreenLayout;
} }
void setCameraFeature(CameraFeaturesConfig config) {
setState(() {
_cameraFeatures = config;
});
widget.userPreferencesService.cameraFeatures = _cameraFeatures;
}
void setPrimaryColor(Color primaryColor) { void setPrimaryColor(Color primaryColor) {
setState(() { setState(() {
_primaryColor = primaryColor; _primaryColor = primaryColor;
@ -264,27 +286,16 @@ class _UserPreferencesModel extends InheritedModel<_Aspect> {
} }
} }
class _MeteringScreenLayoutModel extends InheritedModel<MeteringScreenLayoutFeature> { class _MeteringScreenLayoutModel extends MapModel<MeteringScreenLayoutFeature> {
final Map<MeteringScreenLayoutFeature, bool> data;
const _MeteringScreenLayoutModel({ const _MeteringScreenLayoutModel({
required this.data, required super.data,
required super.child, required super.child,
}); });
}
@override class _CameraFeaturesModel extends MapModel<CameraFeature> {
bool updateShouldNotify(_MeteringScreenLayoutModel oldWidget) => oldWidget.data != data; const _CameraFeaturesModel({
required super.data,
@override required super.child,
bool updateShouldNotifyDependent( });
_MeteringScreenLayoutModel oldWidget,
Set<MeteringScreenLayoutFeature> dependencies,
) {
for (final dependecy in dependencies) {
if (oldWidget.data[dependecy] != data[dependecy]) {
return true;
}
}
return false;
}
} }

View file

@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/camera_feature.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/screens/settings/components/shared/dialog_switch/widget_dialog_switch.dart';
class CameraFeaturesListTile extends StatelessWidget {
const CameraFeaturesListTile({super.key});
@override
Widget build(BuildContext context) {
return ListTile(
leading: const Icon(Icons.camera_alt),
title: Text(S.of(context).cameraFeatures),
onTap: () {
showDialog(
context: context,
builder: (_) => DialogSwitch<CameraFeature>(
icon: Icons.layers_outlined,
title: S.of(context).cameraFeatures,
values: UserPreferencesProvider.cameraConfigOf(context),
titleAdapter: _toStringLocalized,
onSave: UserPreferencesProvider.of(context).setCameraFeature,
),
);
},
);
}
String _toStringLocalized(BuildContext context, CameraFeature feature) {
switch (feature) {
case CameraFeature.spotMetering:
return S.of(context).cameraFeatureSpotMetering;
case CameraFeature.histogram:
return S.of(context).cameraFeatureHistogram;
}
}
}

View file

@ -1,6 +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/screens/settings/components/metering/components/calibration/widget_list_tile_calibration.dart'; import 'package:lightmeter/screens/settings/components/metering/components/calibration/widget_list_tile_calibration.dart';
import 'package:lightmeter/screens/settings/components/metering/components/camera_features/widget_list_tile_camera_features.dart';
import 'package:lightmeter/screens/settings/components/metering/components/equipment_profiles/widget_list_tile_equipment_profiles.dart'; import 'package:lightmeter/screens/settings/components/metering/components/equipment_profiles/widget_list_tile_equipment_profiles.dart';
import 'package:lightmeter/screens/settings/components/metering/components/films/widget_list_tile_films.dart'; import 'package:lightmeter/screens/settings/components/metering/components/films/widget_list_tile_films.dart';
import 'package:lightmeter/screens/settings/components/metering/components/fractional_stops/widget_list_tile_fractional_stops.dart'; import 'package:lightmeter/screens/settings/components/metering/components/fractional_stops/widget_list_tile_fractional_stops.dart';
@ -20,6 +21,7 @@ class MeteringSettingsSection extends StatelessWidget {
MeteringScreenLayoutListTile(), MeteringScreenLayoutListTile(),
EquipmentProfilesListTile(), EquipmentProfilesListTile(),
FilmsListTile(), FilmsListTile(),
CameraFeaturesListTile(),
], ],
); );
} }

View file

@ -5,7 +5,7 @@ import 'package:lightmeter/res/dimens.dart';
class DialogSwitch<T> extends StatefulWidget { class DialogSwitch<T> extends StatefulWidget {
final IconData icon; final IconData icon;
final String title; final String title;
final String description; final String? description;
final Map<T, bool> values; final Map<T, bool> values;
final String Function(BuildContext context, T value) titleAdapter; final String Function(BuildContext context, T value) titleAdapter;
final ValueChanged<Map<T, bool>> onSave; final ValueChanged<Map<T, bool>> onSave;
@ -13,7 +13,7 @@ class DialogSwitch<T> extends StatefulWidget {
const DialogSwitch({ const DialogSwitch({
required this.icon, required this.icon,
required this.title, required this.title,
required this.description, this.description,
required this.values, required this.values,
required this.titleAdapter, required this.titleAdapter,
required this.onSave, required this.onSave,
@ -39,11 +39,13 @@ class _DialogSwitchState<T> extends State<DialogSwitch<T>> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (widget.description != null) ...[
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingL), padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingL),
child: Text(widget.description), child: Text(widget.description!),
), ),
const SizedBox(height: Dimens.grid16), const SizedBox(height: Dimens.grid16)
],
ListView( ListView(
shrinkWrap: true, shrinkWrap: true,
children: _features.entries children: _features.entries

26
lib/utils/map_model.dart Normal file
View file

@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
class MapModel<T> extends InheritedModel<T> {
final Map<T, bool> data;
const MapModel({
required this.data,
required super.child,
});
@override
bool updateShouldNotify(MapModel oldWidget) => oldWidget.data != data;
@override
bool updateShouldNotifyDependent(
MapModel<T> oldWidget,
Set<T> dependencies,
) {
for (final dependecy in dependencies) {
if (oldWidget.data[dependecy] != data[dependecy]) {
return true;
}
}
return false;
}
}