improved equipment profiles screen

This commit is contained in:
Vadim 2023-03-20 22:34:59 +03:00
parent 82c63803bb
commit 5e814184f0
7 changed files with 176 additions and 129 deletions

View file

@ -8,7 +8,6 @@ import 'package:lightmeter/data/caffeine_service.dart';
import 'package:lightmeter/data/haptics_service.dart'; import 'package:lightmeter/data/haptics_service.dart';
import 'package:lightmeter/data/models/supported_locale.dart'; import 'package:lightmeter/data/models/supported_locale.dart';
import 'package:lightmeter/providers/supported_locale_provider.dart'; import 'package:lightmeter/providers/supported_locale_provider.dart';
import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -48,33 +47,31 @@ class Application extends StatelessWidget {
Provider(create: (_) => PermissionsService()), Provider(create: (_) => PermissionsService()),
Provider(create: (_) => const LightSensorService()), Provider(create: (_) => const LightSensorService()),
], ],
child: IAPProductsProvider( child: StopTypeProvider(
child: StopTypeProvider( child: EquipmentProfileProvider(
child: EquipmentProfileProvider( child: EvSourceTypeProvider(
child: EvSourceTypeProvider( child: SupportedLocaleProvider(
child: SupportedLocaleProvider( child: ThemeProvider(
child: ThemeProvider( builder: (context, _) => _AnnotatedRegionWrapper(
builder: (context, _) => _AnnotatedRegionWrapper( child: MaterialApp(
child: MaterialApp( theme: context.watch<ThemeData>(),
theme: context.watch<ThemeData>(), locale: Locale(context.watch<SupportedLocale>().intlName),
locale: Locale(context.watch<SupportedLocale>().intlName), localizationsDelegates: const [
localizationsDelegates: const [ S.delegate,
S.delegate, GlobalMaterialLocalizations.delegate,
GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate,
GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, ],
], supportedLocales: S.delegate.supportedLocales,
supportedLocales: S.delegate.supportedLocales, builder: (context, child) => MediaQuery(
builder: (context, child) => MediaQuery( data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), child: child!,
child: child!,
),
initialRoute: "metering",
routes: {
"metering": (context) => const MeteringFlow(),
"settings": (context) => const SettingsFlow(),
},
), ),
initialRoute: "metering",
routes: {
"metering": (context) => const MeteringFlow(),
"settings": (context) => const SettingsFlow(),
},
), ),
), ),
), ),

View file

@ -38,8 +38,7 @@ class ReadingsContainer extends StatelessWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
if (IAPProducts.of(context, IAPProductType.equipment)?.status == if (true) ...[
IAPProductStatus.purchased) ...[
ReadingValueContainer.singleValue( ReadingValueContainer.singleValue(
value: ReadingValue( value: ReadingValue(
label: S.of(context).equipment, label: S.of(context).equipment,

View file

@ -1,46 +0,0 @@
import 'package:flutter/material.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import '../dialog_filter/widget_dialog_filter.dart';
class EquipmentListTile<T extends PhotographyValue> extends StatelessWidget {
final IconData icon;
final String title;
final String description;
final List<T> selectedValues;
final List<T> values;
final ValueChanged<List<T>> onChanged;
final bool rangeSelect;
const EquipmentListTile({
required this.icon,
required this.title,
required this.description,
required this.selectedValues,
required this.values,
required this.onChanged,
required this.rangeSelect,
super.key,
});
@override
Widget build(BuildContext context) {
return ListTile(
leading: Icon(icon),
title: Text(title),
onTap: () {
showDialog(
context: context,
builder: (_) => DialogFilter<T>(
icon: Icon(icon),
title: title,
description: description,
values: values,
titleAdapter: (_, value) => value.toString(),
rangeSelect: rangeSelect,
),
);
},
);
}
}

View file

@ -0,0 +1,114 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import 'package:lightmeter/screens/settings/components/shared/dialog_filter/widget_dialog_filter.dart';
class EquipmentListTiles extends StatelessWidget {
final List<ApertureValue> selectedApertureValues;
final List<IsoValue> selectedIsoValues;
final List<NdValue> selectedNdValues;
final List<ShutterSpeedValue> selectedShutterSpeedValues;
final ValueChanged<List<ApertureValue>> onApertureValuesSelected;
final ValueChanged<List<IsoValue>> onIsoValuesSelecred;
final ValueChanged<List<NdValue>> onNdValuesSelected;
final ValueChanged<List<ShutterSpeedValue>> onShutterSpeedValuesSelected;
const EquipmentListTiles({
required this.selectedApertureValues,
required this.selectedIsoValues,
required this.selectedNdValues,
required this.selectedShutterSpeedValues,
required this.onApertureValuesSelected,
required this.onIsoValuesSelecred,
required this.onNdValuesSelected,
required this.onShutterSpeedValuesSelected,
super.key,
});
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
_EquipmentListTile<IsoValue>(
icon: Icons.iso,
title: S.of(context).isoValues,
description: S.of(context).isoValuesFilterDescription,
values: isoValues,
selectedValues: selectedIsoValues,
rangeSelect: false,
onChanged: onIsoValuesSelecred,
),
_EquipmentListTile<NdValue>(
icon: Icons.filter_b_and_w,
title: S.of(context).ndFilters,
description: S.of(context).ndFiltersFilterDescription,
values: ndValues,
selectedValues: selectedNdValues,
rangeSelect: false,
onChanged: onNdValuesSelected,
),
_EquipmentListTile<ApertureValue>(
icon: Icons.camera,
title: S.of(context).apertureValues,
description: S.of(context).apertureValuesFilterDescription,
values: apertureValues,
selectedValues: selectedApertureValues,
rangeSelect: true,
onChanged: onApertureValuesSelected,
),
_EquipmentListTile<ShutterSpeedValue>(
icon: Icons.shutter_speed,
title: S.of(context).shutterSpeedValues,
description: S.of(context).shutterSpeedValuesFilterDescription,
values: shutterSpeedValues,
selectedValues: selectedShutterSpeedValues,
rangeSelect: true,
onChanged: onShutterSpeedValuesSelected,
),
],
);
}
}
class _EquipmentListTile<T extends PhotographyValue> extends StatelessWidget {
final IconData icon;
final String title;
final String description;
final List<T> selectedValues;
final List<T> values;
final ValueChanged<List<T>> onChanged;
final bool rangeSelect;
const _EquipmentListTile({
required this.icon,
required this.title,
required this.description,
required this.selectedValues,
required this.values,
required this.onChanged,
required this.rangeSelect,
super.key,
});
@override
Widget build(BuildContext context) {
return ListTile(
leading: Icon(icon),
title: Text(title),
onTap: () {
showDialog(
context: context,
builder: (_) => DialogFilter<T>(
icon: Icon(icon),
title: title,
description: description,
values: values,
titleAdapter: (_, value) => value.toString(),
rangeSelect: rangeSelect,
),
);
},
);
}
}

View file

@ -1,8 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import 'components/equipment_list_tile/widget_list_tile_equipment.dart'; import 'components/equipment_list_tiles/widget_list_tiles_equipments.dart';
class EquipmentListTilesSection extends StatefulWidget { class EquipmentListTilesSection extends StatefulWidget {
final EquipmentProfileData data; final EquipmentProfileData data;
@ -69,7 +70,17 @@ class _EquipmentListTilesSectionState extends State<EquipmentListTilesSection> {
), ),
], ],
), ),
if (_expanded) const _DialogsListTiles() if (_expanded)
EquipmentListTiles(
selectedApertureValues: widget.data.apertureValues,
selectedIsoValues: widget.data.isoValues,
selectedNdValues: widget.data.ndValues,
selectedShutterSpeedValues: widget.data.shutterSpeedValues,
onApertureValuesSelected: (value) {},
onIsoValuesSelecred: (value) {},
onNdValuesSelected: (value) {},
onShutterSpeedValuesSelected: (value) {},
),
], ],
), ),
), ),
@ -82,7 +93,14 @@ class _EquipmentListTilesSectionState extends State<EquipmentListTilesSection> {
setState(() { setState(() {
_expanded = !_expanded; _expanded = !_expanded;
}); });
if (!_expanded) { if (_expanded) {
SchedulerBinding.instance.addPostFrameCallback((_) {
Scrollable.ensureVisible(
context,
alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd,
);
});
} else {
_fieldFocusNode.unfocus(); _fieldFocusNode.unfocus();
} }
}, },
@ -90,52 +108,3 @@ class _EquipmentListTilesSectionState extends State<EquipmentListTilesSection> {
); );
} }
} }
class _DialogsListTiles extends StatelessWidget {
const _DialogsListTiles();
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
EquipmentListTile<IsoValue>(
icon: Icons.iso,
title: S.of(context).isoValues,
description: S.of(context).isoValuesFilterDescription,
values: isoValues,
selectedValues: const [],
rangeSelect: false,
onChanged: (value) {},
),
EquipmentListTile<NdValue>(
icon: Icons.filter_b_and_w,
title: S.of(context).ndFilters,
description: S.of(context).ndFiltersFilterDescription,
values: ndValues,
selectedValues: const [],
rangeSelect: false,
onChanged: (value) {},
),
EquipmentListTile<ApertureValue>(
icon: Icons.camera,
title: S.of(context).apertureValues,
description: S.of(context).apertureValuesFilterDescription,
values: apertureValues,
selectedValues: const [],
rangeSelect: true,
onChanged: (value) {},
),
EquipmentListTile<ShutterSpeedValue>(
icon: Icons.shutter_speed,
title: S.of(context).shutterSpeedValues,
description: S.of(context).shutterSpeedValuesFilterDescription,
values: shutterSpeedValues,
selectedValues: const [],
rangeSelect: true,
onChanged: (value) {},
),
],
);
}
}

View file

@ -23,14 +23,28 @@ class _EquipmentProfileScreenState extends State<EquipmentProfileScreen> {
), ),
body: SafeArea( body: SafeArea(
bottom: false, bottom: false,
child: ListView.builder( child: ListView.separated(
padding: const EdgeInsets.all(Dimens.paddingM), padding: EdgeInsets.fromLTRB(
Dimens.paddingM,
Dimens.paddingM,
Dimens.paddingM,
Dimens.paddingM +
MediaQuery.of(context).padding.bottom +
Dimens.grid56 +
kFloatingActionButtonMargin,
),
separatorBuilder: (context, index) => const SizedBox(height: Dimens.grid16),
itemCount: EquipmentProfiles.of(context)?.length ?? 0, itemCount: EquipmentProfiles.of(context)?.length ?? 0,
itemBuilder: (_, index) => EquipmentListTilesSection( itemBuilder: (_, index) => EquipmentListTilesSection(
data: EquipmentProfiles.of(context)![index], data: EquipmentProfiles.of(context)![index],
), ),
), ),
), ),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
onPressed: EquipmentProfileProvider.of(context).addProfile,
child: const Icon(Icons.add),
),
); );
} }
} }