diff --git a/lib/screens/timer/bloc_timer.dart b/lib/screens/timer/bloc_timer.dart index 91d974a..0bd8cd7 100644 --- a/lib/screens/timer/bloc_timer.dart +++ b/lib/screens/timer/bloc_timer.dart @@ -68,7 +68,7 @@ class TimerBloc extends Bloc { Future _onResetTimer(ResetTimerEvent _, Emitter emit) async { _timer?.cancel(); emit( - TimerStoppedState( + TimerResetState( duration: state.duration, timeLeft: state.duration, ), diff --git a/lib/screens/timer/flow_timer.dart b/lib/screens/timer/flow_timer.dart index 622618a..5d26057 100644 --- a/lib/screens/timer/flow_timer.dart +++ b/lib/screens/timer/flow_timer.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:lightmeter/interactors/metering_interactor.dart'; import 'package:lightmeter/providers/services_provider.dart'; +import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/screens/timer/bloc_timer.dart'; import 'package:lightmeter/screens/timer/screen_timer.dart'; @@ -10,22 +11,35 @@ class TimerFlow extends StatelessWidget { @override Widget build(BuildContext context) { - return MeteringInteractorProvider( - data: MeteringInteractor( - ServicesProvider.of(context).userPreferencesService, - ServicesProvider.of(context).caffeineService, - ServicesProvider.of(context).hapticsService, - ServicesProvider.of(context).permissionsService, - ServicesProvider.of(context).lightSensorService, - ServicesProvider.of(context).volumeEventsService, - )..initialize(), - child: BlocProvider( - create: (context) => TimerBloc( - MeteringInteractorProvider.of(context), - 124, + final scheme = Theme.of(context).colorScheme; + return IconButtonTheme( + data: IconButtonThemeData( + style: ButtonStyle( + backgroundColor: MaterialStatePropertyAll(scheme.surface), + elevation: const MaterialStatePropertyAll(4), + iconColor: MaterialStatePropertyAll(scheme.onSurface), + shadowColor: const MaterialStatePropertyAll(Colors.transparent), + surfaceTintColor: MaterialStatePropertyAll(scheme.surfaceTint), + fixedSize: const MaterialStatePropertyAll(Size(Dimens.grid48, Dimens.grid48)), ), - child: const TimerScreen( - duration: const Duration(seconds: 124), + ), + child: MeteringInteractorProvider( + data: MeteringInteractor( + ServicesProvider.of(context).userPreferencesService, + ServicesProvider.of(context).caffeineService, + ServicesProvider.of(context).hapticsService, + ServicesProvider.of(context).permissionsService, + ServicesProvider.of(context).lightSensorService, + ServicesProvider.of(context).volumeEventsService, + )..initialize(), + child: BlocProvider( + create: (context) => TimerBloc( + MeteringInteractorProvider.of(context), + 60, + ), + child: const TimerScreen( + duration: const Duration(seconds: 60), + ), ), ), ); diff --git a/lib/screens/timer/screen_timer.dart b/lib/screens/timer/screen_timer.dart index 650f4c8..c25bc87 100644 --- a/lib/screens/timer/screen_timer.dart +++ b/lib/screens/timer/screen_timer.dart @@ -50,10 +50,9 @@ class _TimerScreenState extends State with TickerProviderStateMixin @override Widget build(BuildContext context) { + // TODO (@vodemn): split build in timer/components folder return BlocListener( - listenWhen: (previous, current) => - previous is TimerStoppedState && current is TimerResumedState || - previous is TimerResumedState && current is TimerStoppedState, + listenWhen: (previous, current) => previous.runtimeType != current.runtimeType, listener: (context, state) => _updateAnimations(state), child: Scaffold( appBar: AppBar( @@ -95,18 +94,39 @@ class _TimerScreenState extends State with TickerProviderStateMixin ), ), const Spacer(), - BlocBuilder( - builder: (_, state) => FloatingActionButton( - onPressed: () { - context.read().add( - state is TimerStoppedState ? const StartTimerEvent() : const StopTimerEvent(), - ); - }, - child: AnimatedIcon( - icon: AnimatedIcons.play_pause, - progress: startStopIconAnimation, + Row( + children: [ + Expanded( + child: Center( + child: IconButton( + onPressed: () { + context.read().add(const ResetTimerEvent()); + }, + icon: const Icon(Icons.restore), + ), + ), ), - ), + SizedBox.fromSize( + size: const Size.square(Dimens.grid72), + child: BlocBuilder( + builder: (_, state) => FloatingActionButton( + shape: state is TimerResumedState ? null : const CircleBorder(), + onPressed: state.timeLeft.inSeconds == 0 + ? null + : () { + final event = + state is TimerStoppedState ? const StartTimerEvent() : const StopTimerEvent(); + context.read().add(event); + }, + child: AnimatedIcon( + icon: AnimatedIcons.play_pause, + progress: startStopIconAnimation, + ), + ), + ), + ), + const Spacer(), + ], ), ], ), @@ -119,6 +139,10 @@ class _TimerScreenState extends State with TickerProviderStateMixin void _updateAnimations(TimerState state) { switch (state) { + case TimerResetState(): + startStopIconController.reverse(); + timelineController.stop(); + timelineController.animateTo(0, duration: Dimens.durationS); case TimerResumedState(): startStopIconController.forward(); timelineController.forward(); @@ -210,7 +234,6 @@ class _TimelinePainter extends CustomPainter { final double progress; late final double timelineEdgeRadius = strokeWidth / 2; - late final double radiansProgress = 2 * pi * progress; static const double radiansQuarterTurn = -pi / 2; static const double strokeWidth = Dimens.grid8; @@ -222,11 +245,22 @@ class _TimelinePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { + print('PROGRESS: $progress'); + late final double radiansProgress = 2 * pi * progress; final radius = size.height / 2; final timerCenter = Offset(radius, radius); - final timelineSegmentPath = Path.combine( - PathOperation.difference, - Path() + + final timelineSegmentPath = Path(); + if (progress == 1) { + timelineSegmentPath.addOval( + Rect.fromCenter( + center: timerCenter, + height: size.height, + width: size.width, + ), + ); + } else { + timelineSegmentPath ..arcTo( Rect.fromCenter( center: timerCenter, @@ -238,7 +272,12 @@ class _TimelinePainter extends CustomPainter { false, ) ..lineTo(radius, radius) - ..lineTo(radius, 0), + ..lineTo(radius, 0); + } + + final timelinePath = Path.combine( + PathOperation.difference, + timelineSegmentPath, Path() ..addOval( Rect.fromCircle( @@ -293,7 +332,7 @@ class _TimelinePainter extends CustomPainter { canvas.drawPath( Path.combine( PathOperation.union, - timelineSegmentPath, + timelinePath, smoothEdgesPath, ), Paint()..color = progressColor, @@ -301,5 +340,5 @@ class _TimelinePainter extends CustomPainter { } @override - bool shouldRepaint(_TimelinePainter oldDelegate) => oldDelegate.progress != progress; + bool shouldRepaint(_TimelinePainter oldDelegate) => true; } diff --git a/lib/screens/timer/state_timer.dart b/lib/screens/timer/state_timer.dart index b5916a9..ec570b3 100644 --- a/lib/screens/timer/state_timer.dart +++ b/lib/screens/timer/state_timer.dart @@ -24,3 +24,10 @@ class TimerResumedState extends TimerState { required super.timeLeft, }); } + +class TimerResetState extends TimerStoppedState { + const TimerResetState({ + required super.duration, + required super.timeLeft, + }); +}