diff --git a/lib/screens/timer/bloc_timer.dart b/lib/screens/timer/bloc_timer.dart index 0bd8cd7..687e09a 100644 --- a/lib/screens/timer/bloc_timer.dart +++ b/lib/screens/timer/bloc_timer.dart @@ -5,16 +5,18 @@ import 'package:lightmeter/interactors/metering_interactor.dart'; import 'package:lightmeter/screens/timer/event_timer.dart'; import 'package:lightmeter/screens/timer/state_timer.dart'; +const _kTimerStep = Duration(milliseconds: 1); + class TimerBloc extends Bloc { final MeteringInteractor _meteringInteractor; late Timer? _timer; - final int timerLength; + final Duration duration; - TimerBloc(this._meteringInteractor, this.timerLength) + TimerBloc(this._meteringInteractor, this.duration) : super( TimerStoppedState( - duration: Duration(seconds: timerLength), - timeLeft: Duration(seconds: timerLength), + duration: duration, + timeLeft: duration, ), ) { on(_onStartTimer); @@ -37,11 +39,11 @@ class TimerBloc extends Bloc { ), ); - _timer = Timer.periodic(const Duration(seconds: 1), (_) { + _timer = Timer.periodic(_kTimerStep, (_) { if (state.timeLeft.inMilliseconds == 0) { add(const StopTimerEvent()); } else { - add(SetTimeLeftEvent(state.timeLeft - const Duration(seconds: 1))); + add(SetTimeLeftEvent(state.timeLeft - _kTimerStep)); } }); } diff --git a/lib/screens/timer/components/text/widget_text_timer.dart b/lib/screens/timer/components/text/widget_text_timer.dart new file mode 100644 index 0000000..f8fc67a --- /dev/null +++ b/lib/screens/timer/components/text/widget_text_timer.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; + +class TimerText extends StatelessWidget { + final Duration timeLeft; + final Duration duration; + + const TimerText({ + required this.timeLeft, + required this.duration, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + parseSeconds(), + style: Theme.of(context).textTheme.displayMedium, + ), + if (duration.inMinutes < 1) + Text( + addZeroIfNeeded(timeLeft.inMilliseconds % 1000, 3), + style: Theme.of(context).textTheme.displaySmall, + ), + ], + ); + } + + String parseSeconds() { + final buffer = StringBuffer(); + int remainingMs = timeLeft.inMilliseconds; + // longer than 1 hours + if (duration.inSeconds >= Duration.millisecondsPerHour) { + final hours = remainingMs ~/ Duration.millisecondsPerHour; + buffer.writeAll([addZeroIfNeeded(hours), ':']); + remainingMs -= hours * Duration.millisecondsPerHour; + } + // longer than 1 minute + final minutes = remainingMs ~/ Duration.millisecondsPerMinute; + buffer.writeAll([addZeroIfNeeded(minutes), ':']); + remainingMs -= minutes * Duration.millisecondsPerMinute; + + // longer than 1 second + final seconds = remainingMs ~/ Duration.millisecondsPerSecond; + buffer.writeAll([addZeroIfNeeded(seconds)]); + remainingMs -= seconds * Duration.millisecondsPerSecond; + + return buffer.toString(); + } + + String addZeroIfNeeded(int value, [int charactersCount = 2]) { + final zerosCount = charactersCount - value.toString().length; + return '${"0" * zerosCount}$value'; + } +} diff --git a/lib/screens/timer/flow_timer.dart b/lib/screens/timer/flow_timer.dart index 2aa4688..881bd61 100644 --- a/lib/screens/timer/flow_timer.dart +++ b/lib/screens/timer/flow_timer.dart @@ -9,8 +9,10 @@ import 'package:lightmeter/screens/timer/screen_timer.dart'; class TimerFlow extends StatelessWidget { final ExposurePair exposurePair; + late final _duration = + Duration(milliseconds: (exposurePair.shutterSpeed.value * Duration.millisecondsPerSecond).toInt()); - const TimerFlow({required this.exposurePair, super.key}); + TimerFlow({required this.exposurePair, super.key}); @override Widget build(BuildContext context) { @@ -38,7 +40,7 @@ class TimerFlow extends StatelessWidget { child: BlocProvider( create: (context) => TimerBloc( MeteringInteractorProvider.of(context), - exposurePair.shutterSpeed.value.toInt(), + _duration, ), child: TimerScreen(exposurePair: exposurePair), ), diff --git a/lib/screens/timer/screen_timer.dart b/lib/screens/timer/screen_timer.dart index 71f9059..f28b63c 100644 --- a/lib/screens/timer/screen_timer.dart +++ b/lib/screens/timer/screen_timer.dart @@ -6,6 +6,7 @@ import 'package:lightmeter/data/models/exposure_pair.dart'; import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/screens/timer/bloc_timer.dart'; +import 'package:lightmeter/screens/timer/components/text/widget_text_timer.dart'; import 'package:lightmeter/screens/timer/components/timeline/widget_timeline_timer.dart'; import 'package:lightmeter/screens/timer/event_timer.dart'; import 'package:lightmeter/screens/timer/state_timer.dart'; @@ -91,7 +92,7 @@ class _TimerScreenState extends State with TickerProviderStateMixin ), child: BlocBuilder( buildWhen: (previous, current) => previous.timeLeft != current.timeLeft, - builder: (_, state) => _Timer( + builder: (_, state) => TimerText( timeLeft: state.timeLeft, duration: state.duration, ), @@ -157,60 +158,3 @@ class _TimerScreenState extends State with TickerProviderStateMixin } } } - -class _Timer extends StatelessWidget { - final Duration timeLeft; - final Duration duration; - - const _Timer({ - required this.timeLeft, - required this.duration, - }); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - parseSeconds(), - style: Theme.of(context).textTheme.headlineLarge, - ), - // Text( - // '${timeLeft.inMilliseconds % 1000}'.substring(0,2), - // style: Theme.of(context).textTheme.headlineSmall, - // ), - ], - ); - } - - String parseSeconds() { - String addZeroIfNeeded(int value) { - if (value == 0) { - return '00'; - } else if (value < 10) { - return '0$value'; - } else { - return '$value'; - } - } - - final buffer = StringBuffer(); - int remainingSeconds = timeLeft.inSeconds; - // longer than 1 hours - if (duration.inSeconds >= 3600) { - final hours = remainingSeconds ~/ 3600; - buffer.writeAll([addZeroIfNeeded(hours), ':']); - remainingSeconds -= hours * 3600; - } - // longer than 1 minute - if (duration.inSeconds >= 60 || duration.inSeconds == 0) { - final minutes = remainingSeconds ~/ 60; - buffer.writeAll([addZeroIfNeeded(minutes), ':']); - remainingSeconds -= minutes * 60; - } - // longer than 1 second - buffer.write(addZeroIfNeeded(remainingSeconds)); - return buffer.toString(); - } -}