removed VolumeAction.zoom

This commit is contained in:
Vadim 2023-07-09 13:10:58 +02:00
parent ee54aed1f3
commit bf37d1a1d2
10 changed files with 15 additions and 204 deletions

View file

@ -1,3 +1,3 @@
enum VolumeAction { shutter, zoom, none } enum VolumeAction { shutter, none }
enum VolumeKey { up, down } enum VolumeKey { up, down }

View file

@ -56,9 +56,7 @@
"general": "General", "general": "General",
"keepScreenOn": "Keep screen on", "keepScreenOn": "Keep screen on",
"haptics": "Haptics", "haptics": "Haptics",
"volumeKeysAction": "Volume keys action", "volumeKeysAction": "Shutter by volume keys",
"shutter": "Shutter",
"zoom": "Zoom",
"language": "Language", "language": "Language",
"chooseLanguage": "Choose language", "chooseLanguage": "Choose language",
"theme": "Theme", "theme": "Theme",

View file

@ -56,9 +56,7 @@
"general": "Général", "general": "Général",
"keepScreenOn": "Garder l'écran allumé", "keepScreenOn": "Garder l'écran allumé",
"haptics": "Haptiques", "haptics": "Haptiques",
"volumeKeysAction": "Action des touches de volume", "volumeKeysAction": "Obturateur par boutons de volume",
"shutter": "Obturateur",
"zoom": "Zoom",
"language": "Langue", "language": "Langue",
"chooseLanguage": "Choisissez la langue", "chooseLanguage": "Choisissez la langue",
"theme": "Thème", "theme": "Thème",

View file

@ -56,9 +56,7 @@
"general": "Общие", "general": "Общие",
"keepScreenOn": "Запрет блокировки", "keepScreenOn": "Запрет блокировки",
"haptics": "Вибрация", "haptics": "Вибрация",
"volumeKeysAction": "Кнопки регулировки громкости", "volumeKeysAction": "Затвор по кнопкам громкости",
"shutter": "Затвор",
"zoom": "Зум",
"language": "Язык", "language": "Язык",
"chooseLanguage": "Выберите язык", "chooseLanguage": "Выберите язык",
"theme": "Тема", "theme": "Тема",

View file

@ -8,7 +8,6 @@ import 'package:camera/camera.dart';
import 'package:exif/exif.dart'; import 'package:exif/exif.dart';
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/data/models/volume_action.dart';
import 'package:lightmeter/interactors/metering_interactor.dart'; import 'package:lightmeter/interactors/metering_interactor.dart';
import 'package:lightmeter/screens/metering/communication/bloc_communication_metering.dart'; import 'package:lightmeter/screens/metering/communication/bloc_communication_metering.dart';
import 'package:lightmeter/screens/metering/communication/event_communication_metering.dart' import 'package:lightmeter/screens/metering/communication/event_communication_metering.dart'
@ -19,12 +18,10 @@ import 'package:lightmeter/screens/metering/components/camera_container/event_co
import 'package:lightmeter/screens/metering/components/camera_container/models/camera_error_type.dart'; import 'package:lightmeter/screens/metering/components/camera_container/models/camera_error_type.dart';
import 'package:lightmeter/screens/metering/components/camera_container/state_container_camera.dart'; import 'package:lightmeter/screens/metering/components/camera_container/state_container_camera.dart';
import 'package:lightmeter/screens/metering/components/shared/ev_source_base/bloc_base_ev_source.dart'; import 'package:lightmeter/screens/metering/components/shared/ev_source_base/bloc_base_ev_source.dart';
import 'package:lightmeter/screens/metering/components/shared/volume_keys_notifier/notifier_volume_keys.dart';
import 'package:lightmeter/utils/log_2.dart'; import 'package:lightmeter/utils/log_2.dart';
class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraContainerState> { class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraContainerState> {
final MeteringInteractor _meteringInteractor; final MeteringInteractor _meteringInteractor;
final VolumeKeysNotifier _volumeKeysNotifier;
late final _WidgetsBindingObserver _observer; late final _WidgetsBindingObserver _observer;
CameraController? _cameraController; CameraController? _cameraController;
@ -44,13 +41,11 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
CameraContainerBloc( CameraContainerBloc(
this._meteringInteractor, this._meteringInteractor,
this._volumeKeysNotifier,
MeteringCommunicationBloc communicationBloc, MeteringCommunicationBloc communicationBloc,
) : super( ) : super(
communicationBloc, communicationBloc,
const CameraInitState(), const CameraInitState(),
) { ) {
_volumeKeysNotifier.addListener(onVolumeKey);
_observer = _WidgetsBindingObserver(_appLifecycleStateObserver); _observer = _WidgetsBindingObserver(_appLifecycleStateObserver);
WidgetsBinding.instance.addObserver(_observer); WidgetsBinding.instance.addObserver(_observer);
@ -66,7 +61,6 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
@override @override
Future<void> close() async { Future<void> close() async {
WidgetsBinding.instance.removeObserver(_observer); WidgetsBinding.instance.removeObserver(_observer);
_volumeKeysNotifier.removeListener(onVolumeKey);
unawaited(_cameraController?.dispose().then((_) => _cameraController = null)); unawaited(_cameraController?.dispose().then((_) => _cameraController = null));
communicationBloc.add(communication_event.MeteringEndedEvent(_ev100)); communicationBloc.add(communication_event.MeteringEndedEvent(_ev100));
return super.close(); return super.close();
@ -245,18 +239,6 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
} }
} }
} }
@visibleForTesting
void onVolumeKey() {
if (_meteringInteractor.volumeAction == VolumeAction.zoom) {
switch (_volumeKeysNotifier.value) {
case VolumeKey.up:
add(ZoomChangedEvent(_currentZoom + 0.5));
case VolumeKey.down:
add(ZoomChangedEvent(_currentZoom - 0.5));
}
}
}
} }
/// This is needed only because we cannot use `with` with mixins /// This is needed only because we cannot use `with` with mixins

View file

@ -7,7 +7,6 @@ import 'package:lightmeter/screens/metering/communication/bloc_communication_met
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/event_container_camera.dart'; import 'package:lightmeter/screens/metering/components/camera_container/event_container_camera.dart';
import 'package:lightmeter/screens/metering/components/camera_container/widget_container_camera.dart'; import 'package:lightmeter/screens/metering/components/camera_container/widget_container_camera.dart';
import 'package:lightmeter/screens/metering/components/shared/volume_keys_notifier/notifier_volume_keys.dart';
import 'package:lightmeter/utils/inherited_generics.dart'; import 'package:lightmeter/utils/inherited_generics.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
@ -41,7 +40,6 @@ class CameraContainerProvider extends StatelessWidget {
lazy: false, lazy: false,
create: (context) => CameraContainerBloc( create: (context) => CameraContainerBloc(
context.get<MeteringInteractor>(), context.get<MeteringInteractor>(),
context.get<VolumeKeysNotifier>(),
context.read<MeteringCommunicationBloc>(), context.read<MeteringCommunicationBloc>(),
)..add(const RequestPermissionEvent()), )..add(const RequestPermissionEvent()),
child: CameraContainer( child: CameraContainer(

View file

@ -2,15 +2,15 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/data/models/volume_action.dart'; import 'package:lightmeter/data/models/volume_action.dart';
import 'package:lightmeter/interactors/settings_interactor.dart'; import 'package:lightmeter/interactors/settings_interactor.dart';
class VolumeActionsListTileBloc extends Cubit<VolumeAction> { class VolumeActionsListTileBloc extends Cubit<bool> {
final SettingsInteractor _settingsInteractor; final SettingsInteractor _settingsInteractor;
VolumeActionsListTileBloc( VolumeActionsListTileBloc(
this._settingsInteractor, this._settingsInteractor,
) : super(_settingsInteractor.volumeAction); ) : super(_settingsInteractor.volumeAction == VolumeAction.shutter);
void onVolumeActionChanged(VolumeAction value) { void onVolumeActionChanged(bool value) {
_settingsInteractor.setVolumeAction(value); _settingsInteractor.setVolumeAction(value ? VolumeAction.shutter : VolumeAction.none);
// while in settings we allow system to handle volume // while in settings we allow system to handle volume
// so that volume keys action works only when necessary - on the metering screen // so that volume keys action works only when necessary - on the metering screen

View file

@ -1,48 +1,22 @@
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/data/models/volume_action.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/settings/components/general/components/volume_actions/bloc_list_tile_volume_actions.dart'; import 'package:lightmeter/screens/settings/components/general/components/volume_actions/bloc_list_tile_volume_actions.dart';
import 'package:lightmeter/screens/settings/components/shared/dialog_picker.dart/widget_dialog_picker.dart';
class VolumeActionsListTile extends StatelessWidget { class VolumeActionsListTile extends StatelessWidget {
const VolumeActionsListTile({super.key}); const VolumeActionsListTile({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<VolumeActionsListTileBloc, VolumeAction>( return BlocBuilder<VolumeActionsListTileBloc, bool>(
builder: (context, state) => ListTile( builder: (context, state) => SwitchListTile(
leading: const Icon(Icons.volume_up), secondary: const Icon(Icons.volume_up),
title: Text(S.of(context).volumeKeysAction), title: Text(S.of(context).volumeKeysAction),
trailing: Text(actionToString(context, state)), value: state,
onTap: () { onChanged: context.read<VolumeActionsListTileBloc>().onVolumeActionChanged,
showDialog<VolumeAction>( contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
context: context,
builder: (_) => DialogPicker<VolumeAction>(
icon: Icons.volume_up,
title: S.of(context).volumeKeysAction,
selectedValue: state,
values: VolumeAction.values,
titleAdapter: (context, value) => actionToString(context, value),
),
).then((value) {
if (value != null) {
context.read<VolumeActionsListTileBloc>().onVolumeActionChanged(value);
}
});
},
), ),
); );
} }
String actionToString(BuildContext context, VolumeAction themeType) {
switch (themeType) {
case VolumeAction.shutter:
return S.of(context).shutter;
case VolumeAction.zoom:
return S.of(context).zoom;
case VolumeAction.none:
return S.of(context).none;
}
}
} }

View file

@ -641,19 +641,6 @@ void main() {
expect: () => [isA<LoadingState>()], expect: () => [isA<LoadingState>()],
); );
blocTest<MeteringBloc, MeteringState>(
'onVolumeKey & VolumeAction.zoom',
build: () => bloc,
act: (bloc) async {
bloc.onVolumeKey();
},
setUp: () {
when(() => meteringInteractor.volumeAction).thenReturn(VolumeAction.zoom);
},
verify: (_) {},
expect: () => [],
);
blocTest<MeteringBloc, MeteringState>( blocTest<MeteringBloc, MeteringState>(
'onVolumeKey & VolumeAction.none', 'onVolumeKey & VolumeAction.none',
build: () => bloc, build: () => bloc,

View file

@ -2,7 +2,6 @@ import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:lightmeter/data/models/volume_action.dart';
import 'package:lightmeter/interactors/metering_interactor.dart'; import 'package:lightmeter/interactors/metering_interactor.dart';
import 'package:lightmeter/screens/metering/communication/bloc_communication_metering.dart'; import 'package:lightmeter/screens/metering/communication/bloc_communication_metering.dart';
import 'package:lightmeter/screens/metering/communication/event_communication_metering.dart' import 'package:lightmeter/screens/metering/communication/event_communication_metering.dart'
@ -13,13 +12,10 @@ import 'package:lightmeter/screens/metering/components/camera_container/bloc_con
import 'package:lightmeter/screens/metering/components/camera_container/event_container_camera.dart'; import 'package:lightmeter/screens/metering/components/camera_container/event_container_camera.dart';
import 'package:lightmeter/screens/metering/components/camera_container/models/camera_error_type.dart'; import 'package:lightmeter/screens/metering/components/camera_container/models/camera_error_type.dart';
import 'package:lightmeter/screens/metering/components/camera_container/state_container_camera.dart'; import 'package:lightmeter/screens/metering/components/camera_container/state_container_camera.dart';
import 'package:lightmeter/screens/metering/components/shared/volume_keys_notifier/notifier_volume_keys.dart';
import 'package:mocktail/mocktail.dart'; import 'package:mocktail/mocktail.dart';
class _MockMeteringInteractor extends Mock implements MeteringInteractor {} class _MockMeteringInteractor extends Mock implements MeteringInteractor {}
class _MockVolumeKeysNotifier extends Mock implements VolumeKeysNotifier {}
class _MockMeteringCommunicationBloc extends MockBloc< class _MockMeteringCommunicationBloc extends MockBloc<
communication_events.MeteringCommunicationEvent, communication_events.MeteringCommunicationEvent,
communication_states.MeteringCommunicationState> implements MeteringCommunicationBloc {} communication_states.MeteringCommunicationState> implements MeteringCommunicationBloc {}
@ -28,7 +24,6 @@ void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
late _MockMeteringInteractor meteringInteractor; late _MockMeteringInteractor meteringInteractor;
late _MockVolumeKeysNotifier volumeKeysNotifier;
late _MockMeteringCommunicationBloc communicationBloc; late _MockMeteringCommunicationBloc communicationBloc;
late CameraContainerBloc bloc; late CameraContainerBloc bloc;
@ -117,7 +112,6 @@ void main() {
setUpAll(() { setUpAll(() {
meteringInteractor = _MockMeteringInteractor(); meteringInteractor = _MockMeteringInteractor();
volumeKeysNotifier = _MockVolumeKeysNotifier();
communicationBloc = _MockMeteringCommunicationBloc(); communicationBloc = _MockMeteringCommunicationBloc();
when(() => meteringInteractor.cameraEvCalibration).thenReturn(0.0); when(() => meteringInteractor.cameraEvCalibration).thenReturn(0.0);
@ -127,7 +121,6 @@ void main() {
setUp(() { setUp(() {
bloc = CameraContainerBloc( bloc = CameraContainerBloc(
meteringInteractor, meteringInteractor,
volumeKeysNotifier,
communicationBloc, communicationBloc,
); );
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
@ -483,123 +476,6 @@ void main() {
); );
}, },
); );
group(
'`Volume keys shutter action`',
() {
blocTest<CameraContainerBloc, CameraContainerState>(
'Add/remove listener',
build: () => bloc,
verify: (_) {
verify(() => volumeKeysNotifier.addListener(bloc.onVolumeKey)).called(1);
verify(() => volumeKeysNotifier.removeListener(bloc.onVolumeKey)).called(1);
},
expect: () => [],
);
blocTest<CameraContainerBloc, CameraContainerState>(
'onVolumeKey & VolumeAction.shutter',
build: () => bloc,
act: (bloc) async {
bloc.onVolumeKey();
},
setUp: () {
when(() => meteringInteractor.volumeAction).thenReturn(VolumeAction.shutter);
},
verify: (_) {},
expect: () => [],
);
blocTest<CameraContainerBloc, CameraContainerState>(
'onVolumeKey.up & VolumeAction.zoom',
build: () => bloc,
act: (bloc) async {
bloc.add(const InitializeEvent());
await Future.delayed(Duration.zero);
bloc.onVolumeKey();
await Future.delayed(Duration.zero);
bloc.onVolumeKey();
await Future.delayed(Duration.zero);
bloc.onVolumeKey();
},
setUp: () {
when(() => meteringInteractor.checkCameraPermission()).thenAnswer((_) async => true);
when(() => meteringInteractor.volumeAction).thenReturn(VolumeAction.zoom);
when(() => volumeKeysNotifier.value).thenReturn(VolumeKey.up);
},
verify: (_) {},
expect: () => [
...initializedStateSequence,
isA<CameraActiveState>()
.having((state) => state.zoomRange, 'zoomRange', const RangeValues(1.0, 7.0))
.having((state) => state.currentZoom, 'currentZoom', 1.5)
.having(
(state) => state.exposureOffsetRange,
'exposureOffsetRange',
const RangeValues(-4.0, 4.0),
)
.having((state) => state.exposureOffsetStep, 'exposureOffsetStep', 0.1666666)
.having((state) => state.currentExposureOffset, 'currentExposureOffset', 0.0),
isA<CameraActiveState>()
.having((state) => state.zoomRange, 'zoomRange', const RangeValues(1.0, 7.0))
.having((state) => state.currentZoom, 'currentZoom', 2.0)
.having(
(state) => state.exposureOffsetRange,
'exposureOffsetRange',
const RangeValues(-4.0, 4.0),
)
.having((state) => state.exposureOffsetStep, 'exposureOffsetStep', 0.1666666)
.having((state) => state.currentExposureOffset, 'currentExposureOffset', 0.0),
isA<CameraActiveState>()
.having((state) => state.zoomRange, 'zoomRange', const RangeValues(1.0, 7.0))
.having((state) => state.currentZoom, 'currentZoom', 2.5)
.having(
(state) => state.exposureOffsetRange,
'exposureOffsetRange',
const RangeValues(-4.0, 4.0),
)
.having((state) => state.exposureOffsetStep, 'exposureOffsetStep', 0.1666666)
.having((state) => state.currentExposureOffset, 'currentExposureOffset', 0.0),
],
);
blocTest<CameraContainerBloc, CameraContainerState>(
'onVolumeKey.down & VolumeAction.zoom',
build: () => bloc,
act: (bloc) async {
bloc.add(const InitializeEvent());
await Future.delayed(Duration.zero);
bloc.onVolumeKey();
await Future.delayed(Duration.zero);
bloc.onVolumeKey();
await Future.delayed(Duration.zero);
bloc.onVolumeKey();
},
setUp: () {
when(() => meteringInteractor.checkCameraPermission()).thenAnswer((_) async => true);
when(() => meteringInteractor.volumeAction).thenReturn(VolumeAction.zoom);
when(() => volumeKeysNotifier.value).thenReturn(VolumeKey.down);
},
verify: (_) {},
expect: () => [
...initializedStateSequence,
],
);
blocTest<CameraContainerBloc, CameraContainerState>(
'onVolumeKey & VolumeAction.none',
build: () => bloc,
act: (bloc) async {
bloc.onVolumeKey();
},
setUp: () {
when(() => meteringInteractor.volumeAction).thenReturn(VolumeAction.none);
},
verify: (_) {},
expect: () => [],
);
},
);
} }
extension _MethodChannelMock on MethodChannel { extension _MethodChannelMock on MethodChannel {