mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-22 07:20:39 +00:00
added reset button (wip)
This commit is contained in:
parent
b008ef7c83
commit
985ecaa41e
4 changed files with 97 additions and 37 deletions
|
@ -68,7 +68,7 @@ class TimerBloc extends Bloc<TimerEvent, TimerState> {
|
||||||
Future<void> _onResetTimer(ResetTimerEvent _, Emitter emit) async {
|
Future<void> _onResetTimer(ResetTimerEvent _, Emitter emit) async {
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
emit(
|
emit(
|
||||||
TimerStoppedState(
|
TimerResetState(
|
||||||
duration: state.duration,
|
duration: state.duration,
|
||||||
timeLeft: state.duration,
|
timeLeft: state.duration,
|
||||||
),
|
),
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:lightmeter/interactors/metering_interactor.dart';
|
import 'package:lightmeter/interactors/metering_interactor.dart';
|
||||||
import 'package:lightmeter/providers/services_provider.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/bloc_timer.dart';
|
||||||
import 'package:lightmeter/screens/timer/screen_timer.dart';
|
import 'package:lightmeter/screens/timer/screen_timer.dart';
|
||||||
|
|
||||||
|
@ -10,22 +11,35 @@ class TimerFlow extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MeteringInteractorProvider(
|
final scheme = Theme.of(context).colorScheme;
|
||||||
data: MeteringInteractor(
|
return IconButtonTheme(
|
||||||
ServicesProvider.of(context).userPreferencesService,
|
data: IconButtonThemeData(
|
||||||
ServicesProvider.of(context).caffeineService,
|
style: ButtonStyle(
|
||||||
ServicesProvider.of(context).hapticsService,
|
backgroundColor: MaterialStatePropertyAll(scheme.surface),
|
||||||
ServicesProvider.of(context).permissionsService,
|
elevation: const MaterialStatePropertyAll(4),
|
||||||
ServicesProvider.of(context).lightSensorService,
|
iconColor: MaterialStatePropertyAll(scheme.onSurface),
|
||||||
ServicesProvider.of(context).volumeEventsService,
|
shadowColor: const MaterialStatePropertyAll(Colors.transparent),
|
||||||
)..initialize(),
|
surfaceTintColor: MaterialStatePropertyAll(scheme.surfaceTint),
|
||||||
child: BlocProvider(
|
fixedSize: const MaterialStatePropertyAll(Size(Dimens.grid48, Dimens.grid48)),
|
||||||
create: (context) => TimerBloc(
|
|
||||||
MeteringInteractorProvider.of(context),
|
|
||||||
124,
|
|
||||||
),
|
),
|
||||||
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),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -50,10 +50,9 @@ class _TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
// TODO (@vodemn): split build in timer/components folder
|
||||||
return BlocListener<TimerBloc, TimerState>(
|
return BlocListener<TimerBloc, TimerState>(
|
||||||
listenWhen: (previous, current) =>
|
listenWhen: (previous, current) => previous.runtimeType != current.runtimeType,
|
||||||
previous is TimerStoppedState && current is TimerResumedState ||
|
|
||||||
previous is TimerResumedState && current is TimerStoppedState,
|
|
||||||
listener: (context, state) => _updateAnimations(state),
|
listener: (context, state) => _updateAnimations(state),
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
|
@ -95,18 +94,39 @@ class _TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
BlocBuilder<TimerBloc, TimerState>(
|
Row(
|
||||||
builder: (_, state) => FloatingActionButton(
|
children: [
|
||||||
onPressed: () {
|
Expanded(
|
||||||
context.read<TimerBloc>().add(
|
child: Center(
|
||||||
state is TimerStoppedState ? const StartTimerEvent() : const StopTimerEvent(),
|
child: IconButton(
|
||||||
);
|
onPressed: () {
|
||||||
},
|
context.read<TimerBloc>().add(const ResetTimerEvent());
|
||||||
child: AnimatedIcon(
|
},
|
||||||
icon: AnimatedIcons.play_pause,
|
icon: const Icon(Icons.restore),
|
||||||
progress: startStopIconAnimation,
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox.fromSize(
|
||||||
|
size: const Size.square(Dimens.grid72),
|
||||||
|
child: BlocBuilder<TimerBloc, TimerState>(
|
||||||
|
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<TimerBloc>().add(event);
|
||||||
|
},
|
||||||
|
child: AnimatedIcon(
|
||||||
|
icon: AnimatedIcons.play_pause,
|
||||||
|
progress: startStopIconAnimation,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -119,6 +139,10 @@ class _TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin
|
||||||
|
|
||||||
void _updateAnimations(TimerState state) {
|
void _updateAnimations(TimerState state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
case TimerResetState():
|
||||||
|
startStopIconController.reverse();
|
||||||
|
timelineController.stop();
|
||||||
|
timelineController.animateTo(0, duration: Dimens.durationS);
|
||||||
case TimerResumedState():
|
case TimerResumedState():
|
||||||
startStopIconController.forward();
|
startStopIconController.forward();
|
||||||
timelineController.forward();
|
timelineController.forward();
|
||||||
|
@ -210,7 +234,6 @@ class _TimelinePainter extends CustomPainter {
|
||||||
final double progress;
|
final double progress;
|
||||||
|
|
||||||
late final double timelineEdgeRadius = strokeWidth / 2;
|
late final double timelineEdgeRadius = strokeWidth / 2;
|
||||||
late final double radiansProgress = 2 * pi * progress;
|
|
||||||
static const double radiansQuarterTurn = -pi / 2;
|
static const double radiansQuarterTurn = -pi / 2;
|
||||||
static const double strokeWidth = Dimens.grid8;
|
static const double strokeWidth = Dimens.grid8;
|
||||||
|
|
||||||
|
@ -222,11 +245,22 @@ class _TimelinePainter extends CustomPainter {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void paint(Canvas canvas, Size size) {
|
void paint(Canvas canvas, Size size) {
|
||||||
|
print('PROGRESS: $progress');
|
||||||
|
late final double radiansProgress = 2 * pi * progress;
|
||||||
final radius = size.height / 2;
|
final radius = size.height / 2;
|
||||||
final timerCenter = Offset(radius, radius);
|
final timerCenter = Offset(radius, radius);
|
||||||
final timelineSegmentPath = Path.combine(
|
|
||||||
PathOperation.difference,
|
final timelineSegmentPath = Path();
|
||||||
Path()
|
if (progress == 1) {
|
||||||
|
timelineSegmentPath.addOval(
|
||||||
|
Rect.fromCenter(
|
||||||
|
center: timerCenter,
|
||||||
|
height: size.height,
|
||||||
|
width: size.width,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
timelineSegmentPath
|
||||||
..arcTo(
|
..arcTo(
|
||||||
Rect.fromCenter(
|
Rect.fromCenter(
|
||||||
center: timerCenter,
|
center: timerCenter,
|
||||||
|
@ -238,7 +272,12 @@ class _TimelinePainter extends CustomPainter {
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
..lineTo(radius, radius)
|
..lineTo(radius, radius)
|
||||||
..lineTo(radius, 0),
|
..lineTo(radius, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
final timelinePath = Path.combine(
|
||||||
|
PathOperation.difference,
|
||||||
|
timelineSegmentPath,
|
||||||
Path()
|
Path()
|
||||||
..addOval(
|
..addOval(
|
||||||
Rect.fromCircle(
|
Rect.fromCircle(
|
||||||
|
@ -293,7 +332,7 @@ class _TimelinePainter extends CustomPainter {
|
||||||
canvas.drawPath(
|
canvas.drawPath(
|
||||||
Path.combine(
|
Path.combine(
|
||||||
PathOperation.union,
|
PathOperation.union,
|
||||||
timelineSegmentPath,
|
timelinePath,
|
||||||
smoothEdgesPath,
|
smoothEdgesPath,
|
||||||
),
|
),
|
||||||
Paint()..color = progressColor,
|
Paint()..color = progressColor,
|
||||||
|
@ -301,5 +340,5 @@ class _TimelinePainter extends CustomPainter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldRepaint(_TimelinePainter oldDelegate) => oldDelegate.progress != progress;
|
bool shouldRepaint(_TimelinePainter oldDelegate) => true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,3 +24,10 @@ class TimerResumedState extends TimerState {
|
||||||
required super.timeLeft,
|
required super.timeLeft,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TimerResetState extends TimerStoppedState {
|
||||||
|
const TimerResetState({
|
||||||
|
required super.duration,
|
||||||
|
required super.timeLeft,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue