m3_lightmeter/lib/screens/metering/bloc_metering.dart

200 lines
6.4 KiB
Dart
Raw Permalink Normal View History

import 'dart:async';
2022-10-29 18:02:45 +00:00
import 'package:bloc_concurrency/bloc_concurrency.dart';
import 'package:flutter/foundation.dart';
2022-10-29 18:02:45 +00:00
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';
2024-05-03 10:28:10 +00:00
import 'package:lightmeter/screens/metering/communication/event_communication_metering.dart' as communication_events;
import 'package:lightmeter/screens/metering/communication/state_communication_metering.dart' as communication_states;
import 'package:lightmeter/screens/metering/event_metering.dart';
import 'package:lightmeter/screens/metering/state_metering.dart';
ML-62 Utils tests (#133) * removed redundant `UserPreferencesService` from `MeteringBloc` * wip * post-merge fixes * `MeasureEvent` tests * `MeasureEvent` tests revision * `MeasureEvent` tests added timeout * added stubs for other `MeteringBloc` events * rewritten `MeteringBloc` logic * wip * `IsoChangedEvent` tests * refined `IsoChangedEvent` tests * `NdChangedEvent` tests * `FilmChangedEvent` tests * `MeteringCommunicationBloc` tests * added test run to ci * overriden `==` for `MeasuredState` * `LuxMeteringEvent` tests * refined `LuxMeteringEvent` tests * rename * wip * wip * `InitializeEvent`/`DeinitializeEvent` tests * clamp minZoomLevel * fixed `MeteringCommunicationBloc` tests * wip * `ZoomChangedEvent` tests * `ExposureOffsetChangedEvent`/`ExposureOffsetResetEvent` tests * renamed test groups * added test coverage script * improved `CameraContainerBloc` test coverage * `EquipmentProfileChangedEvent` tests * verify response vibration * fixed running all tests * `MeteringCommunicationBloc` equality tests * `CameraContainerBloc` equality tests * removed generated code from coverage * `MeteringScreenLayoutFeature` tests * `SupportedLocale` tests * `Film` tests * `CaffeineService` tests * `UserPreferencesService` tests (wip) * `LightSensorService` tests (wip) * `migrateOldKeys()` tests * ignore currently unused getters & setters * gradle upgrade * `reset(sharedPreferences);` calls count * typo * `MeteringInteractor` tests * `SettingsInteractor` tests (wip) * `MeteringInteractor` tests (wip) * `SettingsInteractor` tests * AnimatedDialog picker standalone tests * Moved Animated dialog picker to widget tests * `ExtremeExposurePairsContainer` widget test * dialog picker test * Match extreme exposure pairs & pairs list edge values * `FilmPicker` widget tests * fixed animated dialog picker tests * add not hit files to coverage percentage * Moved `EquipmentProfileProvider` & `FilmsProvider` to the main repo * Synced _iap_ stub with repo * `FilmsProvider` tests * `EquipmentProfileProvider` tests * Pass `availableFilms` to `FilmsProvider` * `FilmPicker` tests * removed unnecessary imports * Metering layout features tests * split integration tests by screens * Films in use test * mock light meter lux stream * removed mockito mocks for integration tests From no on these are the only mocks in use: - Mock shared prefs initial values - Mock platform responses (camera/light sensor) * set sharedprefs mock without redundant group * unified granting camera permission on Android * fixed metering screen tests * extracted common values * `FilmPicker` integration tests * fixed light sensor platform mocks * wip * removed integration tests for now * moved screenshots generator to screenshots folder * typo * removed `MockIAPProductsProvider` * implemented platform mocks for unit tests * data/models/ 100% coverage * `IsoValuePicker` tests * `EquipmentProfileProvider` tests * extended PR check timeout * typo * added storage action verification for `FilmsProvider` tests * `UserPreferencesProvider` tests * Update README.md * added //coverage:ignore to `ServicesProvider` * typo * typo * `toStringSignedAsFixed` tests * `SelectableInheritedModel` tests * removed unused `TextLineHeight` util * `VolumeKeysNotifier` tests * import * `EquipmentProfileListener` tests * typo * split `EquipmentProfileListener` tests * `showBuyProDialog` tests * added `maybeOf` getter for iap stub
2023-11-02 16:40:47 +00:00
import 'package:lightmeter/screens/metering/utils/notifier_volume_keys.dart';
ML-42 Implement equipment profiles creating (#45) * added Equipment section placeholder * get iso & nd values from equipment profile * use photography values from remote repo * removed equipment section * wip * moved `EquipmentProfileProvider` from iap repo * wip * moved equipment profiles screen from iap * improved equipment profiles screen * mock add/delete * collapse on expand * add profile with name * show selected values count (wip) * fixed profile update * cleanup * Update pubspec.yaml * made `AnimatedDialogPicker` more generic * switched to local `Dimens` * fixed `MeteringTopBarShape` * rename * animated `EquipmentProfileContainer` * added default equipment profile * change equipment profile name via dialog * fixed profile selection * filter equipment profile update/delete * removed `enabled` param from settings section * non-null `EquipmentProfile` * fixed duplicate GlobalKeys * animated equipment list * Update ci.yml * fixed shutter speed anchor issue * autofocus * added firebase to project * save/restore equipment profiles * unified `SliverList` * added SSH key to iap repo * Update ci.yml * ci recursive submodules * try full url * Revert "try full url" This reverts commit a9b692b60ea5b2e88188a5d497467708becb4a02. * restore firebase_options.dart * changed runner to macos * restore options earlier * removed problematic file from analysis :) * removed launch_app * textoverflow * implemented `DialogRangePicker` * add iap repo to cd * typo * added workflow_dispatch to crowdin push * removed `equipmentProfileValuesCount` from intl * fr & ru translations * style * removed iap
2023-03-30 19:24:18 +00:00
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
2022-10-29 18:02:45 +00:00
class MeteringBloc extends Bloc<MeteringEvent, MeteringState> {
final MeteringInteractor _meteringInteractor;
final VolumeKeysNotifier _volumeKeysNotifier;
final MeteringCommunicationBloc _communicationBloc;
late final StreamSubscription<communication_states.ScreenState> _communicationSubscription;
2022-12-16 08:08:12 +00:00
MeteringBloc(
this._meteringInteractor,
this._volumeKeysNotifier,
this._communicationBloc,
2022-12-16 08:08:12 +00:00
) : super(
MeteringDataState(
ev100: null,
iso: _meteringInteractor.iso,
nd: _meteringInteractor.ndFilter,
isMetering: false,
2022-10-29 18:02:45 +00:00
),
) {
_volumeKeysNotifier.addListener(onVolumeKey);
_communicationSubscription = _communicationBloc.stream
.where((state) => state is communication_states.ScreenState)
.map((state) => state as communication_states.ScreenState)
.listen(onCommunicationState);
ML-42 Implement equipment profiles creating (#45) * added Equipment section placeholder * get iso & nd values from equipment profile * use photography values from remote repo * removed equipment section * wip * moved `EquipmentProfileProvider` from iap repo * wip * moved equipment profiles screen from iap * improved equipment profiles screen * mock add/delete * collapse on expand * add profile with name * show selected values count (wip) * fixed profile update * cleanup * Update pubspec.yaml * made `AnimatedDialogPicker` more generic * switched to local `Dimens` * fixed `MeteringTopBarShape` * rename * animated `EquipmentProfileContainer` * added default equipment profile * change equipment profile name via dialog * fixed profile selection * filter equipment profile update/delete * removed `enabled` param from settings section * non-null `EquipmentProfile` * fixed duplicate GlobalKeys * animated equipment list * Update ci.yml * fixed shutter speed anchor issue * autofocus * added firebase to project * save/restore equipment profiles * unified `SliverList` * added SSH key to iap repo * Update ci.yml * ci recursive submodules * try full url * Revert "try full url" This reverts commit a9b692b60ea5b2e88188a5d497467708becb4a02. * restore firebase_options.dart * changed runner to macos * restore options earlier * removed problematic file from analysis :) * removed launch_app * textoverflow * implemented `DialogRangePicker` * add iap repo to cd * typo * added workflow_dispatch to crowdin push * removed `equipmentProfileValuesCount` from intl * fr & ru translations * style * removed iap
2023-03-30 19:24:18 +00:00
on<EquipmentProfileChangedEvent>(_onEquipmentProfileChanged);
2022-12-04 19:00:43 +00:00
on<IsoChangedEvent>(_onIsoChanged);
on<NdChangedEvent>(_onNdChanged);
on<MeasureEvent>(_onMeasure, transformer: droppable());
on<MeasuredEvent>(_onMeasured);
on<MeasureErrorEvent>(_onMeasureError);
2024-05-03 10:28:10 +00:00
on<ScreenOnTopOpenedEvent>(_onSettingsOpened);
on<ScreenOnTopClosedEvent>(_onSettingsClosed);
2022-10-29 18:02:45 +00:00
}
@override
void onTransition(Transition<MeteringEvent, MeteringState> transition) {
super.onTransition(transition);
if (transition.nextState is MeteringDataState) {
final nextState = transition.nextState as MeteringDataState;
if (transition.currentState is LoadingState ||
transition.currentState is MeteringDataState &&
(transition.currentState as MeteringDataState).ev != nextState.ev) {
if (nextState.hasError) {
_meteringInteractor.errorVibration();
} else {
_meteringInteractor.responseVibration();
}
}
}
}
@override
Future<void> close() async {
_volumeKeysNotifier.removeListener(onVolumeKey);
await _communicationSubscription.cancel();
return super.close();
}
@visibleForTesting
void onCommunicationState(communication_states.ScreenState communicationState) {
if (communicationState is communication_states.MeasuredState) {
_handleEv100(
communicationState.ev100,
isMetering: communicationState is communication_states.MeteringInProgressState,
);
}
}
ML-42 Implement equipment profiles creating (#45) * added Equipment section placeholder * get iso & nd values from equipment profile * use photography values from remote repo * removed equipment section * wip * moved `EquipmentProfileProvider` from iap repo * wip * moved equipment profiles screen from iap * improved equipment profiles screen * mock add/delete * collapse on expand * add profile with name * show selected values count (wip) * fixed profile update * cleanup * Update pubspec.yaml * made `AnimatedDialogPicker` more generic * switched to local `Dimens` * fixed `MeteringTopBarShape` * rename * animated `EquipmentProfileContainer` * added default equipment profile * change equipment profile name via dialog * fixed profile selection * filter equipment profile update/delete * removed `enabled` param from settings section * non-null `EquipmentProfile` * fixed duplicate GlobalKeys * animated equipment list * Update ci.yml * fixed shutter speed anchor issue * autofocus * added firebase to project * save/restore equipment profiles * unified `SliverList` * added SSH key to iap repo * Update ci.yml * ci recursive submodules * try full url * Revert "try full url" This reverts commit a9b692b60ea5b2e88188a5d497467708becb4a02. * restore firebase_options.dart * changed runner to macos * restore options earlier * removed problematic file from analysis :) * removed launch_app * textoverflow * implemented `DialogRangePicker` * add iap repo to cd * typo * added workflow_dispatch to crowdin push * removed `equipmentProfileValuesCount` from intl * fr & ru translations * style * removed iap
2023-03-30 19:24:18 +00:00
void _onEquipmentProfileChanged(EquipmentProfileChangedEvent event, Emitter emit) {
bool willUpdateMeasurements = false;
ML-42 Implement equipment profiles creating (#45) * added Equipment section placeholder * get iso & nd values from equipment profile * use photography values from remote repo * removed equipment section * wip * moved `EquipmentProfileProvider` from iap repo * wip * moved equipment profiles screen from iap * improved equipment profiles screen * mock add/delete * collapse on expand * add profile with name * show selected values count (wip) * fixed profile update * cleanup * Update pubspec.yaml * made `AnimatedDialogPicker` more generic * switched to local `Dimens` * fixed `MeteringTopBarShape` * rename * animated `EquipmentProfileContainer` * added default equipment profile * change equipment profile name via dialog * fixed profile selection * filter equipment profile update/delete * removed `enabled` param from settings section * non-null `EquipmentProfile` * fixed duplicate GlobalKeys * animated equipment list * Update ci.yml * fixed shutter speed anchor issue * autofocus * added firebase to project * save/restore equipment profiles * unified `SliverList` * added SSH key to iap repo * Update ci.yml * ci recursive submodules * try full url * Revert "try full url" This reverts commit a9b692b60ea5b2e88188a5d497467708becb4a02. * restore firebase_options.dart * changed runner to macos * restore options earlier * removed problematic file from analysis :) * removed launch_app * textoverflow * implemented `DialogRangePicker` * add iap repo to cd * typo * added workflow_dispatch to crowdin push * removed `equipmentProfileValuesCount` from intl * fr & ru translations * style * removed iap
2023-03-30 19:24:18 +00:00
/// Update selected ISO value and discard selected film, if selected equipment profile
ML-42 Implement equipment profiles creating (#45) * added Equipment section placeholder * get iso & nd values from equipment profile * use photography values from remote repo * removed equipment section * wip * moved `EquipmentProfileProvider` from iap repo * wip * moved equipment profiles screen from iap * improved equipment profiles screen * mock add/delete * collapse on expand * add profile with name * show selected values count (wip) * fixed profile update * cleanup * Update pubspec.yaml * made `AnimatedDialogPicker` more generic * switched to local `Dimens` * fixed `MeteringTopBarShape` * rename * animated `EquipmentProfileContainer` * added default equipment profile * change equipment profile name via dialog * fixed profile selection * filter equipment profile update/delete * removed `enabled` param from settings section * non-null `EquipmentProfile` * fixed duplicate GlobalKeys * animated equipment list * Update ci.yml * fixed shutter speed anchor issue * autofocus * added firebase to project * save/restore equipment profiles * unified `SliverList` * added SSH key to iap repo * Update ci.yml * ci recursive submodules * try full url * Revert "try full url" This reverts commit a9b692b60ea5b2e88188a5d497467708becb4a02. * restore firebase_options.dart * changed runner to macos * restore options earlier * removed problematic file from analysis :) * removed launch_app * textoverflow * implemented `DialogRangePicker` * add iap repo to cd * typo * added workflow_dispatch to crowdin push * removed `equipmentProfileValuesCount` from intl * fr & ru translations * style * removed iap
2023-03-30 19:24:18 +00:00
/// doesn't contain currently selected value
IsoValue iso = state.iso;
if (!event.equipmentProfileData.isoValues.any((v) => state.iso.value == v.value)) {
_meteringInteractor.iso = event.equipmentProfileData.isoValues.first;
iso = event.equipmentProfileData.isoValues.first;
willUpdateMeasurements = true;
ML-42 Implement equipment profiles creating (#45) * added Equipment section placeholder * get iso & nd values from equipment profile * use photography values from remote repo * removed equipment section * wip * moved `EquipmentProfileProvider` from iap repo * wip * moved equipment profiles screen from iap * improved equipment profiles screen * mock add/delete * collapse on expand * add profile with name * show selected values count (wip) * fixed profile update * cleanup * Update pubspec.yaml * made `AnimatedDialogPicker` more generic * switched to local `Dimens` * fixed `MeteringTopBarShape` * rename * animated `EquipmentProfileContainer` * added default equipment profile * change equipment profile name via dialog * fixed profile selection * filter equipment profile update/delete * removed `enabled` param from settings section * non-null `EquipmentProfile` * fixed duplicate GlobalKeys * animated equipment list * Update ci.yml * fixed shutter speed anchor issue * autofocus * added firebase to project * save/restore equipment profiles * unified `SliverList` * added SSH key to iap repo * Update ci.yml * ci recursive submodules * try full url * Revert "try full url" This reverts commit a9b692b60ea5b2e88188a5d497467708becb4a02. * restore firebase_options.dart * changed runner to macos * restore options earlier * removed problematic file from analysis :) * removed launch_app * textoverflow * implemented `DialogRangePicker` * add iap repo to cd * typo * added workflow_dispatch to crowdin push * removed `equipmentProfileValuesCount` from intl * fr & ru translations * style * removed iap
2023-03-30 19:24:18 +00:00
}
/// The same for ND filter
NdValue nd = state.nd;
if (!event.equipmentProfileData.ndValues.any((v) => state.nd.value == v.value)) {
_meteringInteractor.ndFilter = event.equipmentProfileData.ndValues.first;
nd = event.equipmentProfileData.ndValues.first;
willUpdateMeasurements = true;
ML-42 Implement equipment profiles creating (#45) * added Equipment section placeholder * get iso & nd values from equipment profile * use photography values from remote repo * removed equipment section * wip * moved `EquipmentProfileProvider` from iap repo * wip * moved equipment profiles screen from iap * improved equipment profiles screen * mock add/delete * collapse on expand * add profile with name * show selected values count (wip) * fixed profile update * cleanup * Update pubspec.yaml * made `AnimatedDialogPicker` more generic * switched to local `Dimens` * fixed `MeteringTopBarShape` * rename * animated `EquipmentProfileContainer` * added default equipment profile * change equipment profile name via dialog * fixed profile selection * filter equipment profile update/delete * removed `enabled` param from settings section * non-null `EquipmentProfile` * fixed duplicate GlobalKeys * animated equipment list * Update ci.yml * fixed shutter speed anchor issue * autofocus * added firebase to project * save/restore equipment profiles * unified `SliverList` * added SSH key to iap repo * Update ci.yml * ci recursive submodules * try full url * Revert "try full url" This reverts commit a9b692b60ea5b2e88188a5d497467708becb4a02. * restore firebase_options.dart * changed runner to macos * restore options earlier * removed problematic file from analysis :) * removed launch_app * textoverflow * implemented `DialogRangePicker` * add iap repo to cd * typo * added workflow_dispatch to crowdin push * removed `equipmentProfileValuesCount` from intl * fr & ru translations * style * removed iap
2023-03-30 19:24:18 +00:00
}
if (willUpdateMeasurements) {
emit(
MeteringDataState(
ev100: state.ev100,
iso: iso,
nd: nd,
isMetering: state.isMetering,
),
);
}
ML-42 Implement equipment profiles creating (#45) * added Equipment section placeholder * get iso & nd values from equipment profile * use photography values from remote repo * removed equipment section * wip * moved `EquipmentProfileProvider` from iap repo * wip * moved equipment profiles screen from iap * improved equipment profiles screen * mock add/delete * collapse on expand * add profile with name * show selected values count (wip) * fixed profile update * cleanup * Update pubspec.yaml * made `AnimatedDialogPicker` more generic * switched to local `Dimens` * fixed `MeteringTopBarShape` * rename * animated `EquipmentProfileContainer` * added default equipment profile * change equipment profile name via dialog * fixed profile selection * filter equipment profile update/delete * removed `enabled` param from settings section * non-null `EquipmentProfile` * fixed duplicate GlobalKeys * animated equipment list * Update ci.yml * fixed shutter speed anchor issue * autofocus * added firebase to project * save/restore equipment profiles * unified `SliverList` * added SSH key to iap repo * Update ci.yml * ci recursive submodules * try full url * Revert "try full url" This reverts commit a9b692b60ea5b2e88188a5d497467708becb4a02. * restore firebase_options.dart * changed runner to macos * restore options earlier * removed problematic file from analysis :) * removed launch_app * textoverflow * implemented `DialogRangePicker` * add iap repo to cd * typo * added workflow_dispatch to crowdin push * removed `equipmentProfileValuesCount` from intl * fr & ru translations * style * removed iap
2023-03-30 19:24:18 +00:00
}
2022-12-04 19:00:43 +00:00
void _onIsoChanged(IsoChangedEvent event, Emitter emit) {
if (state.iso != event.isoValue) {
_meteringInteractor.iso = event.isoValue;
emit(
MeteringDataState(
ev100: state.ev100,
iso: event.isoValue,
nd: state.nd,
isMetering: state.isMetering,
),
);
}
2022-12-04 19:00:43 +00:00
}
void _onNdChanged(NdChangedEvent event, Emitter emit) {
if (state.nd != event.ndValue) {
_meteringInteractor.ndFilter = event.ndValue;
emit(
MeteringDataState(
ev100: state.ev100,
iso: state.iso,
nd: event.ndValue,
isMetering: state.isMetering,
),
);
}
}
void _onMeasure(MeasureEvent _, Emitter emit) {
_meteringInteractor.quickVibration();
_communicationBloc.add(const communication_events.MeasureEvent());
emit(
LoadingState(
iso: state.iso,
nd: state.nd,
),
);
}
void _handleEv100(double? ev100, {required bool isMetering}) {
if (ev100 == null || ev100.isNaN || ev100.isInfinite) {
add(MeasureErrorEvent(isMetering: isMetering));
} else {
add(MeasuredEvent(ev100, isMetering: isMetering));
}
}
void _onMeasured(MeasuredEvent event, Emitter emit) {
emit(
MeteringDataState(
ev100: event.ev100,
iso: state.iso,
nd: state.nd,
isMetering: event.isMetering,
),
);
}
void _onMeasureError(MeasureErrorEvent event, Emitter emit) {
emit(
MeteringDataState(
ev100: null,
iso: state.iso,
nd: state.nd,
isMetering: event.isMetering,
2022-10-29 18:02:45 +00:00
),
);
}
@visibleForTesting
void onVolumeKey() {
if (_meteringInteractor.volumeAction == VolumeAction.shutter) {
add(const MeasureEvent());
}
}
2024-05-03 10:28:10 +00:00
void _onSettingsOpened(ScreenOnTopOpenedEvent _, Emitter __) {
_communicationBloc.add(const communication_events.ScreenOnTopOpenedEvent());
}
2024-05-03 10:28:10 +00:00
void _onSettingsClosed(ScreenOnTopClosedEvent _, Emitter __) {
_communicationBloc.add(const communication_events.ScreenOnTopClosedEvent());
}
2022-10-29 18:02:45 +00:00
}