diff --git a/integration_test/e2e_test.dart b/integration_test/e2e_test.dart index febfbd2..39034a0 100644 --- a/integration_test/e2e_test.dart +++ b/integration_test/e2e_test.dart @@ -67,10 +67,11 @@ void testE2E(String description) { expect(find.text('x1.91'), findsOneWidget); expect(find.text('f/1.7 - f/16'), findsOneWidget); expect(find.text('1/1000 - B'), findsOneWidget); - await tester.tap(find.byIcon(Icons.save_outlined)); - await tester.pump(); + await tester.saveEdits(); /// Create Praktica + Jupiter profile from Zenitar profile + await tester.tap(find.byIcon(Icons.edit)); + await tester.pumpAndSettle(); await tester.tap(find.byIcon(Icons.copy_outlined).first); await tester.pumpAndSettle(); await tester.enterProfileName(mockEquipmentProfiles[1].name); @@ -78,7 +79,12 @@ void testE2E(String description) { await tester.setZoomValue(mockEquipmentProfiles[1].lensZoom); expect(find.text('x5.02'), findsOneWidget); expect(find.text('f/3.5 - f/22'), findsOneWidget); - expect(find.text('1/1000 - B'), findsNWidgets(2)); + expect(find.text('1/1000 - B'), findsNWidgets(1)); + await tester.saveEdits(); + + /// Verify that both profiles were added and leave to the main screen + expect(find.text(mockEquipmentProfiles[0].name), findsOneWidget); + expect(find.text(mockEquipmentProfiles[1].name), findsOneWidget); await tester.navigatorPop(); await tester.navigatorPop(); @@ -181,6 +187,11 @@ extension on WidgetTester { await tapSelectButton(); } + Future saveEdits() async { + await tap(find.byIcon(Icons.save_outlined)); + await pumpAndSettle(Dimens.durationML); + } + Future setDialogFilterValues( List valuesToSelect, { bool deselectAll = true, diff --git a/lib/screens/equipment_profile_edit/bloc_equipment_profile_edit.dart b/lib/screens/equipment_profile_edit/bloc_equipment_profile_edit.dart index 68a349a..83ed0dd 100644 --- a/lib/screens/equipment_profile_edit/bloc_equipment_profile_edit.dart +++ b/lib/screens/equipment_profile_edit/bloc_equipment_profile_edit.dart @@ -62,6 +62,8 @@ class EquipmentProfileEditBloc extends Bloc _onCopy(EquipmentProfileCopyEvent _, Emitter emit) async { + emit(state.copyWith(isLoading: true)); + emit(state.copyWith(isLoading: false, profileToCopy: _originalEquipmentProfile)); + } + Future _onDelete(EquipmentProfileDeleteEvent _, Emitter emit) async { emit(state.copyWith(isLoading: true)); await profilesProvider.deleteProfile(_newEquipmentProfile); diff --git a/lib/screens/equipment_profile_edit/event_equipment_profile_edit.dart b/lib/screens/equipment_profile_edit/event_equipment_profile_edit.dart index 092290c..a441ef7 100644 --- a/lib/screens/equipment_profile_edit/event_equipment_profile_edit.dart +++ b/lib/screens/equipment_profile_edit/event_equipment_profile_edit.dart @@ -44,6 +44,10 @@ class EquipmentProfileSaveEvent extends EquipmentProfileEditEvent { const EquipmentProfileSaveEvent(); } +class EquipmentProfileCopyEvent extends EquipmentProfileEditEvent { + const EquipmentProfileCopyEvent(); +} + class EquipmentProfileDeleteEvent extends EquipmentProfileEditEvent { const EquipmentProfileDeleteEvent(); } diff --git a/lib/screens/equipment_profile_edit/flow_equipment_profile_edit.dart b/lib/screens/equipment_profile_edit/flow_equipment_profile_edit.dart index 0923bd4..94db81a 100644 --- a/lib/screens/equipment_profile_edit/flow_equipment_profile_edit.dart +++ b/lib/screens/equipment_profile_edit/flow_equipment_profile_edit.dart @@ -5,16 +5,23 @@ import 'package:lightmeter/screens/equipment_profile_edit/bloc_equipment_profile import 'package:lightmeter/screens/equipment_profile_edit/screen_equipment_profile_edit.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; +enum EquipmentProfileEditType { add, edit } + class EquipmentProfileEditArgs { + final EquipmentProfileEditType editType; final EquipmentProfile? profile; - const EquipmentProfileEditArgs({this.profile}); + const EquipmentProfileEditArgs({required this.editType, this.profile}); } class EquipmentProfileEditFlow extends StatelessWidget { final EquipmentProfileEditArgs args; + final bool _isEdit; - const EquipmentProfileEditFlow({required this.args, super.key}); + EquipmentProfileEditFlow({ + required this.args, + super.key, + }) : _isEdit = args.editType == EquipmentProfileEditType.edit; @override Widget build(BuildContext context) { @@ -22,9 +29,9 @@ class EquipmentProfileEditFlow extends StatelessWidget { create: (_) => EquipmentProfileEditBloc( EquipmentProfilesProvider.of(context), profile: args.profile, - isEdit: args.profile != null, + isEdit: _isEdit, ), - child: EquipmentProfileEditScreen(isEdit: args.profile != null), + child: EquipmentProfileEditScreen(isEdit: _isEdit), ); } } diff --git a/lib/screens/equipment_profile_edit/screen_equipment_profile_edit.dart b/lib/screens/equipment_profile_edit/screen_equipment_profile_edit.dart index af136af..d33a889 100644 --- a/lib/screens/equipment_profile_edit/screen_equipment_profile_edit.dart +++ b/lib/screens/equipment_profile_edit/screen_equipment_profile_edit.dart @@ -1,12 +1,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:lightmeter/generated/l10n.dart'; +import 'package:lightmeter/navigation/routes.dart'; import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/screens/equipment_profile_edit/bloc_equipment_profile_edit.dart'; import 'package:lightmeter/screens/equipment_profile_edit/components/filter_list_tile/widget_list_tile_filter.dart'; import 'package:lightmeter/screens/equipment_profile_edit/components/range_picker_list_tile/widget_list_tile_range_picker.dart'; import 'package:lightmeter/screens/equipment_profile_edit/components/slider_picker_list_tile/widget_list_tile_slider_picker.dart'; import 'package:lightmeter/screens/equipment_profile_edit/event_equipment_profile_edit.dart'; +import 'package:lightmeter/screens/equipment_profile_edit/flow_equipment_profile_edit.dart'; import 'package:lightmeter/screens/equipment_profile_edit/state_equipment_profile_edit.dart'; import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart'; import 'package:lightmeter/screens/shared/text_field/widget_text_field.dart'; @@ -34,7 +36,17 @@ class _EquipmentProfileEditScreenState extends State if (state.isLoading) { FocusScope.of(context).unfocus(); } else { - Navigator.of(context).pop(); + if (state.profileToCopy != null) { + Navigator.of(context).pushReplacementNamed( + NavigationRoutes.equipmentProfileEditScreen.name, + arguments: EquipmentProfileEditArgs( + editType: EquipmentProfileEditType.add, + profile: state.profileToCopy, + ), + ); + } else { + Navigator.of(context).pop(); + } } }, buildWhen: (previous, current) => previous.isLoading != current.isLoading, @@ -54,6 +66,18 @@ class _EquipmentProfileEditScreenState extends State icon: const Icon(Icons.save_outlined), ), ), + if (widget.isEdit) + BlocBuilder( + buildWhen: (previous, current) => previous.canSave != current.canSave, + builder: (context, state) => IconButton( + onPressed: state.canSave + ? null + : () { + context.read().add(const EquipmentProfileCopyEvent()); + }, + icon: const Icon(Icons.copy_outlined), + ), + ), if (widget.isEdit) IconButton( onPressed: () { diff --git a/lib/screens/equipment_profile_edit/state_equipment_profile_edit.dart b/lib/screens/equipment_profile_edit/state_equipment_profile_edit.dart index e0f5ef0..5002a84 100644 --- a/lib/screens/equipment_profile_edit/state_equipment_profile_edit.dart +++ b/lib/screens/equipment_profile_edit/state_equipment_profile_edit.dart @@ -9,6 +9,7 @@ class EquipmentProfileEditState { final double lensZoom; final bool canSave; final bool isLoading; + final EquipmentProfile? profileToCopy; const EquipmentProfileEditState({ required this.name, @@ -19,6 +20,7 @@ class EquipmentProfileEditState { required this.lensZoom, required this.canSave, this.isLoading = false, + this.profileToCopy, }); EquipmentProfileEditState copyWith({ @@ -30,6 +32,7 @@ class EquipmentProfileEditState { double? lensZoom, bool? canSave, bool? isLoading, + EquipmentProfile? profileToCopy, }) => EquipmentProfileEditState( name: name ?? this.name, @@ -40,5 +43,6 @@ class EquipmentProfileEditState { lensZoom: lensZoom ?? this.lensZoom, canSave: canSave ?? this.canSave, isLoading: isLoading ?? this.isLoading, + profileToCopy: profileToCopy ?? this.profileToCopy, ); } diff --git a/lib/screens/equipment_profiles/screen_equipment_profiles.dart b/lib/screens/equipment_profiles/screen_equipment_profiles.dart index 8203216..e5269fb 100644 --- a/lib/screens/equipment_profiles/screen_equipment_profiles.dart +++ b/lib/screens/equipment_profiles/screen_equipment_profiles.dart @@ -42,14 +42,17 @@ class _EquipmentProfilesScreenState extends State with void _addProfile() { Navigator.of(context).pushNamed( NavigationRoutes.equipmentProfileEditScreen.name, - arguments: const EquipmentProfileEditArgs(), + arguments: const EquipmentProfileEditArgs(editType: EquipmentProfileEditType.add), ); } void _editProfile(EquipmentProfile profile) { Navigator.of(context).pushNamed( NavigationRoutes.equipmentProfileEditScreen.name, - arguments: EquipmentProfileEditArgs(profile: profile), + arguments: EquipmentProfileEditArgs( + editType: EquipmentProfileEditType.edit, + profile: profile, + ), ); } }