recovered copy feature for profiles

This commit is contained in:
Vadim 2024-11-08 10:37:44 +01:00
parent 4ea34410a4
commit 63b5723684
7 changed files with 70 additions and 10 deletions

View file

@ -67,10 +67,11 @@ void testE2E(String description) {
expect(find.text('x1.91'), findsOneWidget); expect(find.text('x1.91'), findsOneWidget);
expect(find.text('f/1.7 - f/16'), findsOneWidget); expect(find.text('f/1.7 - f/16'), findsOneWidget);
expect(find.text('1/1000 - B'), findsOneWidget); expect(find.text('1/1000 - B'), findsOneWidget);
await tester.tap(find.byIcon(Icons.save_outlined)); await tester.saveEdits();
await tester.pump();
/// Create Praktica + Jupiter profile from Zenitar profile /// 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.tap(find.byIcon(Icons.copy_outlined).first);
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await tester.enterProfileName(mockEquipmentProfiles[1].name); await tester.enterProfileName(mockEquipmentProfiles[1].name);
@ -78,7 +79,12 @@ void testE2E(String description) {
await tester.setZoomValue(mockEquipmentProfiles[1].lensZoom); await tester.setZoomValue(mockEquipmentProfiles[1].lensZoom);
expect(find.text('x5.02'), findsOneWidget); expect(find.text('x5.02'), findsOneWidget);
expect(find.text('f/3.5 - f/22'), 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();
await tester.navigatorPop(); await tester.navigatorPop();
@ -181,6 +187,11 @@ extension on WidgetTester {
await tapSelectButton(); await tapSelectButton();
} }
Future<void> saveEdits() async {
await tap(find.byIcon(Icons.save_outlined));
await pumpAndSettle(Dimens.durationML);
}
Future<void> setDialogFilterValues<T>( Future<void> setDialogFilterValues<T>(
List<T> valuesToSelect, { List<T> valuesToSelect, {
bool deselectAll = true, bool deselectAll = true,

View file

@ -62,6 +62,8 @@ class EquipmentProfileEditBloc extends Bloc<EquipmentProfileEditEvent, Equipment
await _onLensZoomChanged(e, emit); await _onLensZoomChanged(e, emit);
case EquipmentProfileSaveEvent(): case EquipmentProfileSaveEvent():
await _onSave(event, emit); await _onSave(event, emit);
case EquipmentProfileCopyEvent():
await _onCopy(event, emit);
case EquipmentProfileDeleteEvent(): case EquipmentProfileDeleteEvent():
await _onDelete(event, emit); await _onDelete(event, emit);
} }
@ -139,6 +141,11 @@ class EquipmentProfileEditBloc extends Bloc<EquipmentProfileEditEvent, Equipment
emit(state.copyWith(isLoading: false)); emit(state.copyWith(isLoading: false));
} }
Future<void> _onCopy(EquipmentProfileCopyEvent _, Emitter emit) async {
emit(state.copyWith(isLoading: true));
emit(state.copyWith(isLoading: false, profileToCopy: _originalEquipmentProfile));
}
Future<void> _onDelete(EquipmentProfileDeleteEvent _, Emitter emit) async { Future<void> _onDelete(EquipmentProfileDeleteEvent _, Emitter emit) async {
emit(state.copyWith(isLoading: true)); emit(state.copyWith(isLoading: true));
await profilesProvider.deleteProfile(_newEquipmentProfile); await profilesProvider.deleteProfile(_newEquipmentProfile);

View file

@ -44,6 +44,10 @@ class EquipmentProfileSaveEvent extends EquipmentProfileEditEvent {
const EquipmentProfileSaveEvent(); const EquipmentProfileSaveEvent();
} }
class EquipmentProfileCopyEvent extends EquipmentProfileEditEvent {
const EquipmentProfileCopyEvent();
}
class EquipmentProfileDeleteEvent extends EquipmentProfileEditEvent { class EquipmentProfileDeleteEvent extends EquipmentProfileEditEvent {
const EquipmentProfileDeleteEvent(); const EquipmentProfileDeleteEvent();
} }

View file

@ -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:lightmeter/screens/equipment_profile_edit/screen_equipment_profile_edit.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
enum EquipmentProfileEditType { add, edit }
class EquipmentProfileEditArgs { class EquipmentProfileEditArgs {
final EquipmentProfileEditType editType;
final EquipmentProfile? profile; final EquipmentProfile? profile;
const EquipmentProfileEditArgs({this.profile}); const EquipmentProfileEditArgs({required this.editType, this.profile});
} }
class EquipmentProfileEditFlow extends StatelessWidget { class EquipmentProfileEditFlow extends StatelessWidget {
final EquipmentProfileEditArgs args; 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -22,9 +29,9 @@ class EquipmentProfileEditFlow extends StatelessWidget {
create: (_) => EquipmentProfileEditBloc( create: (_) => EquipmentProfileEditBloc(
EquipmentProfilesProvider.of(context), EquipmentProfilesProvider.of(context),
profile: args.profile, profile: args.profile,
isEdit: args.profile != null, isEdit: _isEdit,
), ),
child: EquipmentProfileEditScreen(isEdit: args.profile != null), child: EquipmentProfileEditScreen(isEdit: _isEdit),
); );
} }
} }

View file

@ -1,12 +1,14 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/navigation/routes.dart';
import 'package:lightmeter/res/dimens.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/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/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/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/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/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/equipment_profile_edit/state_equipment_profile_edit.dart';
import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart'; import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart';
import 'package:lightmeter/screens/shared/text_field/widget_text_field.dart'; import 'package:lightmeter/screens/shared/text_field/widget_text_field.dart';
@ -33,9 +35,19 @@ class _EquipmentProfileEditScreenState extends State<EquipmentProfileEditScreen>
listener: (context, state) { listener: (context, state) {
if (state.isLoading) { if (state.isLoading) {
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
} else {
if (state.profileToCopy != null) {
Navigator.of(context).pushReplacementNamed(
NavigationRoutes.equipmentProfileEditScreen.name,
arguments: EquipmentProfileEditArgs(
editType: EquipmentProfileEditType.add,
profile: state.profileToCopy,
),
);
} else { } else {
Navigator.of(context).pop(); Navigator.of(context).pop();
} }
}
}, },
buildWhen: (previous, current) => previous.isLoading != current.isLoading, buildWhen: (previous, current) => previous.isLoading != current.isLoading,
builder: (context, state) => IgnorePointer( builder: (context, state) => IgnorePointer(
@ -54,6 +66,18 @@ class _EquipmentProfileEditScreenState extends State<EquipmentProfileEditScreen>
icon: const Icon(Icons.save_outlined), icon: const Icon(Icons.save_outlined),
), ),
), ),
if (widget.isEdit)
BlocBuilder<EquipmentProfileEditBloc, EquipmentProfileEditState>(
buildWhen: (previous, current) => previous.canSave != current.canSave,
builder: (context, state) => IconButton(
onPressed: state.canSave
? null
: () {
context.read<EquipmentProfileEditBloc>().add(const EquipmentProfileCopyEvent());
},
icon: const Icon(Icons.copy_outlined),
),
),
if (widget.isEdit) if (widget.isEdit)
IconButton( IconButton(
onPressed: () { onPressed: () {

View file

@ -9,6 +9,7 @@ class EquipmentProfileEditState {
final double lensZoom; final double lensZoom;
final bool canSave; final bool canSave;
final bool isLoading; final bool isLoading;
final EquipmentProfile? profileToCopy;
const EquipmentProfileEditState({ const EquipmentProfileEditState({
required this.name, required this.name,
@ -19,6 +20,7 @@ class EquipmentProfileEditState {
required this.lensZoom, required this.lensZoom,
required this.canSave, required this.canSave,
this.isLoading = false, this.isLoading = false,
this.profileToCopy,
}); });
EquipmentProfileEditState copyWith({ EquipmentProfileEditState copyWith({
@ -30,6 +32,7 @@ class EquipmentProfileEditState {
double? lensZoom, double? lensZoom,
bool? canSave, bool? canSave,
bool? isLoading, bool? isLoading,
EquipmentProfile? profileToCopy,
}) => }) =>
EquipmentProfileEditState( EquipmentProfileEditState(
name: name ?? this.name, name: name ?? this.name,
@ -40,5 +43,6 @@ class EquipmentProfileEditState {
lensZoom: lensZoom ?? this.lensZoom, lensZoom: lensZoom ?? this.lensZoom,
canSave: canSave ?? this.canSave, canSave: canSave ?? this.canSave,
isLoading: isLoading ?? this.isLoading, isLoading: isLoading ?? this.isLoading,
profileToCopy: profileToCopy ?? this.profileToCopy,
); );
} }

View file

@ -42,14 +42,17 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> with
void _addProfile() { void _addProfile() {
Navigator.of(context).pushNamed( Navigator.of(context).pushNamed(
NavigationRoutes.equipmentProfileEditScreen.name, NavigationRoutes.equipmentProfileEditScreen.name,
arguments: const EquipmentProfileEditArgs(), arguments: const EquipmentProfileEditArgs(editType: EquipmentProfileEditType.add),
); );
} }
void _editProfile(EquipmentProfile profile) { void _editProfile(EquipmentProfile profile) {
Navigator.of(context).pushNamed( Navigator.of(context).pushNamed(
NavigationRoutes.equipmentProfileEditScreen.name, NavigationRoutes.equipmentProfileEditScreen.name,
arguments: EquipmentProfileEditArgs(profile: profile), arguments: EquipmentProfileEditArgs(
editType: EquipmentProfileEditType.edit,
profile: profile,
),
); );
} }
} }