mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-24 08:20:40 +00:00
removed VolumeAction.zoom
This commit is contained in:
parent
ee54aed1f3
commit
bf37d1a1d2
10 changed files with 15 additions and 204 deletions
|
@ -1,3 +1,3 @@
|
|||
enum VolumeAction { shutter, zoom, none }
|
||||
enum VolumeAction { shutter, none }
|
||||
|
||||
enum VolumeKey { up, down }
|
||||
|
|
|
@ -56,9 +56,7 @@
|
|||
"general": "General",
|
||||
"keepScreenOn": "Keep screen on",
|
||||
"haptics": "Haptics",
|
||||
"volumeKeysAction": "Volume keys action",
|
||||
"shutter": "Shutter",
|
||||
"zoom": "Zoom",
|
||||
"volumeKeysAction": "Shutter by volume keys",
|
||||
"language": "Language",
|
||||
"chooseLanguage": "Choose language",
|
||||
"theme": "Theme",
|
||||
|
|
|
@ -56,9 +56,7 @@
|
|||
"general": "Général",
|
||||
"keepScreenOn": "Garder l'écran allumé",
|
||||
"haptics": "Haptiques",
|
||||
"volumeKeysAction": "Action des touches de volume",
|
||||
"shutter": "Obturateur",
|
||||
"zoom": "Zoom",
|
||||
"volumeKeysAction": "Obturateur par boutons de volume",
|
||||
"language": "Langue",
|
||||
"chooseLanguage": "Choisissez la langue",
|
||||
"theme": "Thème",
|
||||
|
|
|
@ -56,9 +56,7 @@
|
|||
"general": "Общие",
|
||||
"keepScreenOn": "Запрет блокировки",
|
||||
"haptics": "Вибрация",
|
||||
"volumeKeysAction": "Кнопки регулировки громкости",
|
||||
"shutter": "Затвор",
|
||||
"zoom": "Зум",
|
||||
"volumeKeysAction": "Затвор по кнопкам громкости",
|
||||
"language": "Язык",
|
||||
"chooseLanguage": "Выберите язык",
|
||||
"theme": "Тема",
|
||||
|
|
|
@ -8,7 +8,6 @@ import 'package:camera/camera.dart';
|
|||
import 'package:exif/exif.dart';
|
||||
import 'package:flutter/material.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/screens/metering/communication/bloc_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/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/volume_keys_notifier/notifier_volume_keys.dart';
|
||||
import 'package:lightmeter/utils/log_2.dart';
|
||||
|
||||
class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraContainerState> {
|
||||
final MeteringInteractor _meteringInteractor;
|
||||
final VolumeKeysNotifier _volumeKeysNotifier;
|
||||
late final _WidgetsBindingObserver _observer;
|
||||
|
||||
CameraController? _cameraController;
|
||||
|
@ -44,13 +41,11 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
|
|||
|
||||
CameraContainerBloc(
|
||||
this._meteringInteractor,
|
||||
this._volumeKeysNotifier,
|
||||
MeteringCommunicationBloc communicationBloc,
|
||||
) : super(
|
||||
communicationBloc,
|
||||
const CameraInitState(),
|
||||
) {
|
||||
_volumeKeysNotifier.addListener(onVolumeKey);
|
||||
_observer = _WidgetsBindingObserver(_appLifecycleStateObserver);
|
||||
WidgetsBinding.instance.addObserver(_observer);
|
||||
|
||||
|
@ -66,7 +61,6 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
|
|||
@override
|
||||
Future<void> close() async {
|
||||
WidgetsBinding.instance.removeObserver(_observer);
|
||||
_volumeKeysNotifier.removeListener(onVolumeKey);
|
||||
unawaited(_cameraController?.dispose().then((_) => _cameraController = null));
|
||||
communicationBloc.add(communication_event.MeteringEndedEvent(_ev100));
|
||||
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
|
||||
|
|
|
@ -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/event_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:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||
|
||||
|
@ -41,7 +40,6 @@ class CameraContainerProvider extends StatelessWidget {
|
|||
lazy: false,
|
||||
create: (context) => CameraContainerBloc(
|
||||
context.get<MeteringInteractor>(),
|
||||
context.get<VolumeKeysNotifier>(),
|
||||
context.read<MeteringCommunicationBloc>(),
|
||||
)..add(const RequestPermissionEvent()),
|
||||
child: CameraContainer(
|
||||
|
|
|
@ -2,15 +2,15 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||
import 'package:lightmeter/data/models/volume_action.dart';
|
||||
import 'package:lightmeter/interactors/settings_interactor.dart';
|
||||
|
||||
class VolumeActionsListTileBloc extends Cubit<VolumeAction> {
|
||||
class VolumeActionsListTileBloc extends Cubit<bool> {
|
||||
final SettingsInteractor _settingsInteractor;
|
||||
|
||||
VolumeActionsListTileBloc(
|
||||
this._settingsInteractor,
|
||||
) : super(_settingsInteractor.volumeAction);
|
||||
) : super(_settingsInteractor.volumeAction == VolumeAction.shutter);
|
||||
|
||||
void onVolumeActionChanged(VolumeAction value) {
|
||||
_settingsInteractor.setVolumeAction(value);
|
||||
void onVolumeActionChanged(bool value) {
|
||||
_settingsInteractor.setVolumeAction(value ? VolumeAction.shutter : VolumeAction.none);
|
||||
|
||||
// while in settings we allow system to handle volume
|
||||
// so that volume keys action works only when necessary - on the metering screen
|
||||
|
|
|
@ -1,48 +1,22 @@
|
|||
import 'package:flutter/material.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/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/shared/dialog_picker.dart/widget_dialog_picker.dart';
|
||||
|
||||
class VolumeActionsListTile extends StatelessWidget {
|
||||
const VolumeActionsListTile({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<VolumeActionsListTileBloc, VolumeAction>(
|
||||
builder: (context, state) => ListTile(
|
||||
leading: const Icon(Icons.volume_up),
|
||||
return BlocBuilder<VolumeActionsListTileBloc, bool>(
|
||||
builder: (context, state) => SwitchListTile(
|
||||
secondary: const Icon(Icons.volume_up),
|
||||
title: Text(S.of(context).volumeKeysAction),
|
||||
trailing: Text(actionToString(context, state)),
|
||||
onTap: () {
|
||||
showDialog<VolumeAction>(
|
||||
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);
|
||||
}
|
||||
});
|
||||
},
|
||||
value: state,
|
||||
onChanged: context.read<VolumeActionsListTileBloc>().onVolumeActionChanged,
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -641,19 +641,6 @@ void main() {
|
|||
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>(
|
||||
'onVolumeKey & VolumeAction.none',
|
||||
build: () => bloc,
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:bloc_test/bloc_test.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.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/screens/metering/communication/bloc_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/models/camera_error_type.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';
|
||||
|
||||
class _MockMeteringInteractor extends Mock implements MeteringInteractor {}
|
||||
|
||||
class _MockVolumeKeysNotifier extends Mock implements VolumeKeysNotifier {}
|
||||
|
||||
class _MockMeteringCommunicationBloc extends MockBloc<
|
||||
communication_events.MeteringCommunicationEvent,
|
||||
communication_states.MeteringCommunicationState> implements MeteringCommunicationBloc {}
|
||||
|
@ -28,7 +24,6 @@ void main() {
|
|||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
late _MockMeteringInteractor meteringInteractor;
|
||||
late _MockVolumeKeysNotifier volumeKeysNotifier;
|
||||
late _MockMeteringCommunicationBloc communicationBloc;
|
||||
late CameraContainerBloc bloc;
|
||||
|
||||
|
@ -117,7 +112,6 @@ void main() {
|
|||
|
||||
setUpAll(() {
|
||||
meteringInteractor = _MockMeteringInteractor();
|
||||
volumeKeysNotifier = _MockVolumeKeysNotifier();
|
||||
communicationBloc = _MockMeteringCommunicationBloc();
|
||||
|
||||
when(() => meteringInteractor.cameraEvCalibration).thenReturn(0.0);
|
||||
|
@ -127,7 +121,6 @@ void main() {
|
|||
setUp(() {
|
||||
bloc = CameraContainerBloc(
|
||||
meteringInteractor,
|
||||
volumeKeysNotifier,
|
||||
communicationBloc,
|
||||
);
|
||||
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 {
|
||||
|
|
Loading…
Reference in a new issue