Compare commits

..

5 commits

Author SHA1 Message Date
Vadim
c50baa4802 await dispose 2023-07-06 20:30:35 +02:00
Vadim
205255b916 cleanup 2023-07-06 18:15:20 +02:00
Vadim
e165b53ef2 lints 2023-07-06 17:55:49 +02:00
Vadim
6ee662d79d allow volume action override only on metering screen 2023-07-06 17:49:21 +02:00
Vadim
cdaf0905da init/deinit camera on settings open 2023-07-06 17:43:57 +02:00
15 changed files with 113 additions and 104 deletions

View file

@ -12,9 +12,7 @@ import 'package:lightmeter/utils/inherited_generics.dart';
class Application extends StatelessWidget { class Application extends StatelessWidget {
final Environment env; final Environment env;
Application(this.env, {super.key}); const Application(this.env, {super.key});
final RouteObserver<ModalRoute> routeObserver = RouteObserver<ModalRoute>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -32,19 +30,15 @@ class Application extends StatelessWidget {
GlobalCupertinoLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
], ],
supportedLocales: S.delegate.supportedLocales, supportedLocales: S.delegate.supportedLocales,
builder: (context, child) => InheritedWidgetBase<RouteObserver<ModalRoute>>( builder: (context, child) => MediaQuery(
data: routeObserver, data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
child: MediaQuery( child: child!,
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
child: child!,
),
), ),
initialRoute: "metering", initialRoute: "metering",
routes: { routes: {
"metering": (context) => const MeteringFlow(), "metering": (context) => const MeteringFlow(),
"settings": (context) => const SettingsFlow(), "settings": (context) => const SettingsFlow(),
}, },
navigatorObservers: [routeObserver],
), ),
) )
: const SizedBox(), : const SizedBox(),

View file

@ -4,5 +4,5 @@ import 'package:lightmeter/environment.dart';
Future<void> main() async { Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
runApp(Application(const Environment.dev())); runApp(const Application(Environment.dev()));
} }

View file

@ -6,5 +6,5 @@ import 'package:lightmeter/firebase.dart';
Future<void> main() async { Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await initializeFirebase(); await initializeFirebase();
runApp(Application(const Environment.prod())); runApp(const Application(Environment.prod()));
} }

View file

@ -48,6 +48,8 @@ class MeteringBloc extends Bloc<MeteringEvent, MeteringState> {
on<MeasureEvent>(_onMeasure, transformer: droppable()); on<MeasureEvent>(_onMeasure, transformer: droppable());
on<MeasuredEvent>(_onMeasured); on<MeasuredEvent>(_onMeasured);
on<MeasureErrorEvent>(_onMeasureError); on<MeasureErrorEvent>(_onMeasureError);
on<SettingsOpenedEvent>(_onSettingsOpened);
on<SettingsClosedEvent>(_onSettingsClosed);
} }
@override @override
@ -233,4 +235,12 @@ class MeteringBloc extends Bloc<MeteringEvent, MeteringState> {
add(const MeasureEvent()); add(const MeasureEvent());
} }
} }
void _onSettingsOpened(SettingsOpenedEvent _, Emitter __) {
_communicationBloc.add(const communication_events.SettingsOpenedEvent());
}
void _onSettingsClosed(SettingsClosedEvent _, Emitter __) {
_communicationBloc.add(const communication_events.SettingsClosedEvent());
}
} }

View file

@ -11,5 +11,7 @@ class MeteringCommunicationBloc
on<MeasureEvent>((_, emit) => emit(MeasureState())); on<MeasureEvent>((_, emit) => emit(MeasureState()));
on<MeteringInProgressEvent>((event, emit) => emit(MeteringInProgressState(event.ev100))); on<MeteringInProgressEvent>((event, emit) => emit(MeteringInProgressState(event.ev100)));
on<MeteringEndedEvent>((event, emit) => emit(MeteringEndedState(event.ev100))); on<MeteringEndedEvent>((event, emit) => emit(MeteringEndedState(event.ev100)));
on<SettingsOpenedEvent>((_, emit) => emit(const SettingsOpenedState()));
on<SettingsClosedEvent>((_, emit) => emit(const SettingsClosedState()));
} }
} }

View file

@ -47,3 +47,11 @@ class MeteringEndedEvent extends MeasuredEvent {
@override @override
int get hashCode => Object.hash(ev100, runtimeType); int get hashCode => Object.hash(ev100, runtimeType);
} }
class SettingsOpenedEvent extends ScreenEvent {
const SettingsOpenedEvent();
}
class SettingsClosedEvent extends ScreenEvent {
const SettingsClosedEvent();
}

View file

@ -51,3 +51,11 @@ class MeteringEndedState extends MeasuredState {
@override @override
int get hashCode => Object.hash(ev100, runtimeType); int get hashCode => Object.hash(ev100, runtimeType);
} }
class SettingsOpenedState extends SourceState {
const SettingsOpenedState();
}
class SettingsClosedState extends SourceState {
const SettingsClosedState();
}

View file

@ -40,6 +40,8 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
double? _ev100 = 0.0; double? _ev100 = 0.0;
bool _settingsOpened = false;
CameraContainerBloc( CameraContainerBloc(
this._meteringInteractor, this._meteringInteractor,
this._volumeKeysNotifier, this._volumeKeysNotifier,
@ -72,18 +74,26 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
@override @override
void onCommunicationState(communication_states.SourceState communicationState) { void onCommunicationState(communication_states.SourceState communicationState) {
if (communicationState is communication_states.MeasureState) { switch (communicationState) {
if (_canTakePhoto) { case communication_states.MeasureState():
_takePhoto().then((ev100Raw) { if (_canTakePhoto) {
if (ev100Raw != null) { _takePhoto().then((ev100Raw) {
_ev100 = ev100Raw + _meteringInteractor.cameraEvCalibration; if (ev100Raw != null) {
communicationBloc.add(communication_event.MeteringEndedEvent(_ev100)); _ev100 = ev100Raw + _meteringInteractor.cameraEvCalibration;
} else { communicationBloc.add(communication_event.MeteringEndedEvent(_ev100));
_ev100 = null; } else {
communicationBloc.add(const communication_event.MeteringEndedEvent(null)); _ev100 = null;
} communicationBloc.add(const communication_event.MeteringEndedEvent(null));
}); }
} });
}
case communication_states.SettingsOpenedState():
_settingsOpened = true;
add(const DeinitializeEvent());
case communication_states.SettingsClosedState():
_settingsOpened = false;
add(const InitializeEvent());
default:
} }
} }
@ -156,7 +166,7 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
Future<void> _onDeinitialize(DeinitializeEvent _, Emitter emit) async { Future<void> _onDeinitialize(DeinitializeEvent _, Emitter emit) async {
emit(const CameraLoadingState()); emit(const CameraLoadingState());
unawaited(_cameraController?.dispose().then((_) => _cameraController = null)); await _cameraController?.dispose().then((_) => _cameraController = null);
} }
Future<void> _onZoomChanged(ZoomChangedEvent event, Emitter emit) async { Future<void> _onZoomChanged(ZoomChangedEvent event, Emitter emit) async {
@ -224,13 +234,15 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
} }
Future<void> _appLifecycleStateObserver(AppLifecycleState state) async { Future<void> _appLifecycleStateObserver(AppLifecycleState state) async {
switch (state) { if (!_settingsOpened) {
case AppLifecycleState.resumed: switch (state) {
add(const InitializeEvent()); case AppLifecycleState.resumed:
case AppLifecycleState.paused: add(const InitializeEvent());
case AppLifecycleState.detached: case AppLifecycleState.paused:
add(const DeinitializeEvent()); case AppLifecycleState.detached:
default: add(const DeinitializeEvent());
default:
}
} }
} }

View file

@ -18,10 +18,9 @@ import 'package:lightmeter/screens/metering/components/camera_container/state_co
import 'package:lightmeter/screens/metering/components/shared/exposure_pairs_list/widget_list_exposure_pairs.dart'; import 'package:lightmeter/screens/metering/components/shared/exposure_pairs_list/widget_list_exposure_pairs.dart';
import 'package:lightmeter/screens/metering/components/shared/metering_top_bar/widget_top_bar_metering.dart'; import 'package:lightmeter/screens/metering/components/shared/metering_top_bar/widget_top_bar_metering.dart';
import 'package:lightmeter/screens/metering/components/shared/readings_container/widget_container_readings.dart'; import 'package:lightmeter/screens/metering/components/shared/readings_container/widget_container_readings.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';
class CameraContainer extends StatefulWidget { class CameraContainer extends StatelessWidget {
final ExposurePair? fastest; final ExposurePair? fastest;
final ExposurePair? slowest; final ExposurePair? slowest;
final Film film; final Film film;
@ -45,29 +44,6 @@ class CameraContainer extends StatefulWidget {
super.key, super.key,
}); });
@override
State<CameraContainer> createState() => _CameraContainerState();
}
class _CameraContainerState extends State<CameraContainer> with RouteAware {
@override
void didChangeDependencies() {
super.didChangeDependencies();
context.get<RouteObserver<ModalRoute>>().subscribe(this, ModalRoute.of(context)!);
}
@override
void didPushNext() {
super.didPushNext();
context.read<CameraContainerBloc>().add(const DeinitializeEvent());
}
@override
void didPopNext() {
super.didPopNext();
context.read<CameraContainerBloc>().add(const InitializeEvent());
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final double cameraViewHeight = final double cameraViewHeight =
@ -99,14 +75,14 @@ class _CameraContainerState extends State<CameraContainer> with RouteAware {
children: [ children: [
MeteringTopBar( MeteringTopBar(
readingsContainer: ReadingsContainer( readingsContainer: ReadingsContainer(
fastest: widget.fastest, fastest: fastest,
slowest: widget.slowest, slowest: slowest,
film: widget.film, film: film,
iso: widget.iso, iso: iso,
nd: widget.nd, nd: nd,
onFilmChanged: widget.onFilmChanged, onFilmChanged: onFilmChanged,
onIsoChanged: widget.onIsoChanged, onIsoChanged: onIsoChanged,
onNdChanged: widget.onNdChanged, onNdChanged: onNdChanged,
), ),
appendixHeight: topBarOverflow, appendixHeight: topBarOverflow,
preview: const _CameraViewBuilder(), preview: const _CameraViewBuilder(),
@ -116,7 +92,7 @@ class _CameraContainerState extends State<CameraContainer> with RouteAware {
padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM), padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
child: _MiddleContentWrapper( child: _MiddleContentWrapper(
topBarOverflow: topBarOverflow, topBarOverflow: topBarOverflow,
leftContent: ExposurePairsList(widget.exposurePairs), leftContent: ExposurePairsList(exposurePairs),
rightContent: const _CameraControlsBuilder(), rightContent: const _CameraControlsBuilder(),
), ),
), ),

View file

@ -31,12 +31,16 @@ class LightSensorContainerBloc
@override @override
void onCommunicationState(communication_states.SourceState communicationState) { void onCommunicationState(communication_states.SourceState communicationState) {
if (communicationState is communication_states.MeasureState) { switch (communicationState) {
if (_luxSubscriptions == null) { case communication_states.MeasureState():
_startMetering(); if (_luxSubscriptions == null) {
} else { _startMetering();
} else {
_cancelMetering();
}
case communication_states.SettingsOpenedState():
_cancelMetering(); _cancelMetering();
} default:
} }
} }

View file

@ -1,17 +1,13 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/data/models/exposure_pair.dart'; import 'package:lightmeter/data/models/exposure_pair.dart';
import 'package:lightmeter/data/models/film.dart'; import 'package:lightmeter/data/models/film.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/metering/components/light_sensor_container/bloc_container_light_sensor.dart';
import 'package:lightmeter/screens/metering/components/light_sensor_container/event_container_light_sensor.dart';
import 'package:lightmeter/screens/metering/components/shared/exposure_pairs_list/widget_list_exposure_pairs.dart'; import 'package:lightmeter/screens/metering/components/shared/exposure_pairs_list/widget_list_exposure_pairs.dart';
import 'package:lightmeter/screens/metering/components/shared/metering_top_bar/widget_top_bar_metering.dart'; import 'package:lightmeter/screens/metering/components/shared/metering_top_bar/widget_top_bar_metering.dart';
import 'package:lightmeter/screens/metering/components/shared/readings_container/widget_container_readings.dart'; import 'package:lightmeter/screens/metering/components/shared/readings_container/widget_container_readings.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';
class LightSensorContainer extends StatefulWidget { class LightSensorContainer extends StatelessWidget {
final ExposurePair? fastest; final ExposurePair? fastest;
final ExposurePair? slowest; final ExposurePair? slowest;
final Film film; final Film film;
@ -35,43 +31,26 @@ class LightSensorContainer extends StatefulWidget {
super.key, super.key,
}); });
@override
State<LightSensorContainer> createState() => _LightSensorContainerState();
}
class _LightSensorContainerState extends State<LightSensorContainer> with RouteAware {
@override
void didChangeDependencies() {
super.didChangeDependencies();
context.get<RouteObserver<ModalRoute>>().subscribe(this, ModalRoute.of(context)!);
}
@override
void didPushNext() {
super.didPushNext();
context.read<LightSensorContainerBloc>().add(const CancelLuxMeteringEvent());
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Column(
children: [ children: [
MeteringTopBar( MeteringTopBar(
readingsContainer: ReadingsContainer( readingsContainer: ReadingsContainer(
fastest: widget.fastest, fastest: fastest,
slowest: widget.slowest, slowest: slowest,
film: widget.film, film: film,
iso: widget.iso, iso: iso,
nd: widget.nd, nd: nd,
onFilmChanged: widget.onFilmChanged, onFilmChanged: onFilmChanged,
onIsoChanged: widget.onIsoChanged, onIsoChanged: onIsoChanged,
onNdChanged: widget.onNdChanged, onNdChanged: onNdChanged,
), ),
), ),
Expanded( Expanded(
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM), padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
child: Center(child: ExposurePairsList(widget.exposurePairs)), child: Center(child: ExposurePairsList(exposurePairs)),
), ),
), ),
], ],

View file

@ -10,7 +10,6 @@ class VolumeKeysNotifier extends ChangeNotifier with RouteAware {
VolumeKey _value = VolumeKey.up; VolumeKey _value = VolumeKey.up;
VolumeKeysNotifier(this.volumeEventsService) { VolumeKeysNotifier(this.volumeEventsService) {
// TODO: add RouteObserver and disable overriden action if SettingScreen is opened
_volumeKeysSubscription = volumeEventsService _volumeKeysSubscription = volumeEventsService
.volumeButtonsEventStream() .volumeButtonsEventStream()
.map((event) => event == 24 ? VolumeKey.up : VolumeKey.down) .map((event) => event == 24 ? VolumeKey.up : VolumeKey.down)

View file

@ -45,3 +45,11 @@ class MeasureErrorEvent extends MeteringEvent {
const MeasureErrorEvent({required this.isMetering}); const MeasureErrorEvent({required this.isMetering});
} }
class SettingsOpenedEvent extends MeteringEvent {
const SettingsOpenedEvent();
}
class SettingsClosedEvent extends MeteringEvent {
const SettingsClosedEvent();
}

View file

@ -50,7 +50,12 @@ class MeteringScreen extends StatelessWidget {
? EvSourceTypeProvider.of(context).toggleType ? EvSourceTypeProvider.of(context).toggleType
: null, : null,
onMeasure: () => context.read<MeteringBloc>().add(const MeasureEvent()), onMeasure: () => context.read<MeteringBloc>().add(const MeasureEvent()),
onSettings: () => Navigator.pushNamed(context, 'settings'), onSettings: () {
context.read<MeteringBloc>().add(const SettingsOpenedEvent());
Navigator.pushNamed(context, 'settings').then((value) {
context.read<MeteringBloc>().add(const SettingsClosedEvent());
});
},
), ),
), ),
], ],

View file

@ -11,6 +11,10 @@ class VolumeActionsListTileBloc extends Cubit<VolumeAction> {
void onVolumeActionChanged(VolumeAction value) { void onVolumeActionChanged(VolumeAction value) {
_settingsInteractor.setVolumeAction(value); _settingsInteractor.setVolumeAction(value);
// while in settings we allow system to handle volume
// so that volume keys action works only when necessary - on the metering screen
_settingsInteractor.disableVolumeHandling();
emit(value); emit(value);
} }
} }