Last active
July 20, 2020 11:42
-
-
Save SebastianKlaiber/be46bb4287e341d6160326c283aea84b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:app/src/i_app_config.dart'; | |
import 'package:bloc/bloc.dart'; | |
import 'package:freezed_annotation/freezed_annotation.dart'; | |
import 'package:meta/meta.dart'; | |
part 'session_timer_bloc.freezed.dart'; | |
part 'session_timer_event.dart'; | |
part 'session_timer_state.dart'; | |
class SessionTimerBloc extends Bloc<SessionTimerEvent, SessionTimerState> { | |
StreamSubscription<int> _tickerSubscription; | |
final Ticker _ticker; | |
final IAppConfig appConfig; | |
SessionTimerBloc({@required Ticker ticker, @required this.appConfig}) | |
: assert(ticker != null), | |
_ticker = ticker, | |
super(Ready(appConfig.accessTokenLifetime)); | |
@override | |
Stream<SessionTimerState> mapEventToState( | |
SessionTimerEvent event, | |
) async* { | |
yield* event.map( | |
start: _mapStartToState, | |
pause: _mapPauseToState, | |
resume: _mapResumeToState, | |
reset: _mapResetToState, | |
tick: _mapTickToState, | |
); | |
} | |
@override | |
Future<void> close() { | |
_tickerSubscription?.cancel(); | |
return super.close(); | |
} | |
Stream<SessionTimerState> _mapStartToState(Start start) async* { | |
yield Running(start.duration ?? appConfig.accessTokenLifetime); | |
_tickerSubscription?.cancel(); | |
_tickerSubscription = _ticker.tick(ticks: start.duration).listen((duration) => add(Tick(duration: duration))); | |
} | |
Stream<SessionTimerState> _mapPauseToState(Pause pause) async* { | |
if (state is Running) { | |
final currentState = state as Running; | |
_tickerSubscription?.pause(); | |
yield Paused(currentState.duration); | |
} | |
} | |
Stream<SessionTimerState> _mapResumeToState(Resume resume) async* { | |
if (state is Paused) { | |
final currentState = state as Paused; | |
_tickerSubscription?.resume(); | |
yield Running(currentState.duration); | |
} | |
} | |
Stream<SessionTimerState> _mapResetToState(Reset reset) async* { | |
_tickerSubscription?.cancel(); | |
yield Ready(appConfig.accessTokenLifetime); | |
} | |
Stream<SessionTimerState> _mapTickToState(Tick tick) async* { | |
yield tick.duration > 0 ? Running(tick.duration) : Finished(appConfig.accessTokenLifetime); | |
} | |
} | |
class Ticker { | |
Stream<int> tick({int ticks}) => Stream.periodic(const Duration(seconds: 1), (x) => ticks - x - 1).take(ticks); | |
} | |
class SessionTimerText extends StatelessWidget { | |
const SessionTimerText({Key key}) : super(key: key); | |
static final TextStyle style = GoogleFonts.sourceSansPro( | |
color: textDarkGrey, | |
fontWeight: FontWeight.w600, | |
fontSize: 2 * SizeConfig.textMultiplier, | |
); | |
@override | |
Widget build(BuildContext context) { | |
return BlocConsumer<SessionTimerBloc, SessionTimerState>( | |
listenWhen: (previous, current) => current is Finished, | |
listener: (BuildContext context, SessionTimerState state) { | |
if (state is Finished) { | |
final isBiometricsEnabled = getIt<IPreference>().isBiometricsEnabled; | |
if (isBiometricsEnabled) { | |
context.bloc<AuthenticationBloc>().add(const AppStarted()); | |
} else { | |
context.bloc<AuthenticationBloc>().add(const RefreshAccessTokenEvent()); | |
} | |
} | |
}, | |
builder: (context, state) { | |
final String minutesStr = ((state.duration / 60) % 60).floor().toString().padLeft(2, '0'); | |
final String secondsStr = (state.duration % 60).floor().toString().padLeft(2, '0'); | |
return Text('$minutesStr:$secondsStr', style: SessionTimerText.style); | |
}, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment