added milliseconds to timer

This commit is contained in:
Vadim 2024-05-03 10:50:35 +02:00
parent 1c66a82270
commit f77ef321d0
4 changed files with 71 additions and 66 deletions

View file

@ -5,16 +5,18 @@ import 'package:lightmeter/interactors/metering_interactor.dart';
import 'package:lightmeter/screens/timer/event_timer.dart'; import 'package:lightmeter/screens/timer/event_timer.dart';
import 'package:lightmeter/screens/timer/state_timer.dart'; import 'package:lightmeter/screens/timer/state_timer.dart';
const _kTimerStep = Duration(milliseconds: 1);
class TimerBloc extends Bloc<TimerEvent, TimerState> { class TimerBloc extends Bloc<TimerEvent, TimerState> {
final MeteringInteractor _meteringInteractor; final MeteringInteractor _meteringInteractor;
late Timer? _timer; late Timer? _timer;
final int timerLength; final Duration duration;
TimerBloc(this._meteringInteractor, this.timerLength) TimerBloc(this._meteringInteractor, this.duration)
: super( : super(
TimerStoppedState( TimerStoppedState(
duration: Duration(seconds: timerLength), duration: duration,
timeLeft: Duration(seconds: timerLength), timeLeft: duration,
), ),
) { ) {
on<StartTimerEvent>(_onStartTimer); on<StartTimerEvent>(_onStartTimer);
@ -37,11 +39,11 @@ class TimerBloc extends Bloc<TimerEvent, TimerState> {
), ),
); );
_timer = Timer.periodic(const Duration(seconds: 1), (_) { _timer = Timer.periodic(_kTimerStep, (_) {
if (state.timeLeft.inMilliseconds == 0) { if (state.timeLeft.inMilliseconds == 0) {
add(const StopTimerEvent()); add(const StopTimerEvent());
} else { } else {
add(SetTimeLeftEvent(state.timeLeft - const Duration(seconds: 1))); add(SetTimeLeftEvent(state.timeLeft - _kTimerStep));
} }
}); });
} }

View file

@ -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';
}
}

View file

@ -9,8 +9,10 @@ import 'package:lightmeter/screens/timer/screen_timer.dart';
class TimerFlow extends StatelessWidget { class TimerFlow extends StatelessWidget {
final ExposurePair exposurePair; 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -38,7 +40,7 @@ class TimerFlow extends StatelessWidget {
child: BlocProvider( child: BlocProvider(
create: (context) => TimerBloc( create: (context) => TimerBloc(
MeteringInteractorProvider.of(context), MeteringInteractorProvider.of(context),
exposurePair.shutterSpeed.value.toInt(), _duration,
), ),
child: TimerScreen(exposurePair: exposurePair), child: TimerScreen(exposurePair: exposurePair),
), ),

View file

@ -6,6 +6,7 @@ import 'package:lightmeter/data/models/exposure_pair.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/timer/bloc_timer.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/components/timeline/widget_timeline_timer.dart';
import 'package:lightmeter/screens/timer/event_timer.dart'; import 'package:lightmeter/screens/timer/event_timer.dart';
import 'package:lightmeter/screens/timer/state_timer.dart'; import 'package:lightmeter/screens/timer/state_timer.dart';
@ -91,7 +92,7 @@ class _TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin
), ),
child: BlocBuilder<TimerBloc, TimerState>( child: BlocBuilder<TimerBloc, TimerState>(
buildWhen: (previous, current) => previous.timeLeft != current.timeLeft, buildWhen: (previous, current) => previous.timeLeft != current.timeLeft,
builder: (_, state) => _Timer( builder: (_, state) => TimerText(
timeLeft: state.timeLeft, timeLeft: state.timeLeft,
duration: state.duration, duration: state.duration,
), ),
@ -157,60 +158,3 @@ class _TimerScreenState extends State<TimerScreen> 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();
}
}