Implement sleep timer functionality (#84)
This commit is contained in:
parent
17a200b8f4
commit
3d79cd41ff
3 changed files with 164 additions and 1 deletions
|
|
@ -1,4 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:frosty/api/twitch_api.dart';
|
||||
|
|
@ -19,6 +21,17 @@ abstract class _VideoStoreBase with Store {
|
|||
|
||||
late Timer _overlayTimer;
|
||||
|
||||
Timer? sleepTimer;
|
||||
|
||||
@observable
|
||||
var sleepHours = 0;
|
||||
|
||||
@observable
|
||||
var sleepMinutes = 0;
|
||||
|
||||
@observable
|
||||
var timeRemaining = const Duration();
|
||||
|
||||
@readonly
|
||||
var _paused = true;
|
||||
|
||||
|
|
@ -149,4 +162,42 @@ abstract class _VideoStoreBase with Store {
|
|||
debugPrint(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the sleep timer with [sleepHours] and [sleepMinutes].
|
||||
void updateSleepTimer() {
|
||||
// If hours and minutes are 0, do nothing.
|
||||
if (sleepHours == 0 && sleepMinutes == 0) return;
|
||||
|
||||
// If there is an ongoing timer, cancel it since it'll be replaced.
|
||||
if (sleepTimer != null) cancelSleepTimer();
|
||||
|
||||
// Update the new time remaining
|
||||
timeRemaining = Duration(hours: sleepHours, minutes: sleepMinutes);
|
||||
|
||||
// Reset the hours and minutes in the dropdown buttons.
|
||||
sleepHours = 0;
|
||||
sleepMinutes = 0;
|
||||
|
||||
// Set a periodic timer that will update the time remaining every second.
|
||||
sleepTimer = Timer.periodic(
|
||||
const Duration(seconds: 1),
|
||||
(timer) {
|
||||
// If the timer is up, cancel the timer and exit the app.
|
||||
if (timeRemaining.inSeconds == 0) {
|
||||
timer.cancel();
|
||||
Platform.isIOS ? exit(0) : SystemNavigator.pop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Decrement the time remaining.
|
||||
timeRemaining = Duration(seconds: timeRemaining.inSeconds - 1);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Cancels the sleep timer and resets the time remaining.
|
||||
void cancelSleepTimer() {
|
||||
sleepTimer?.cancel();
|
||||
timeRemaining = const Duration();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,51 @@ mixin _$VideoStore on _VideoStoreBase, Store {
|
|||
name: '_VideoStoreBase.videoUrl'))
|
||||
.value;
|
||||
|
||||
final _$sleepHoursAtom = Atom(name: '_VideoStoreBase.sleepHours');
|
||||
|
||||
@override
|
||||
int get sleepHours {
|
||||
_$sleepHoursAtom.reportRead();
|
||||
return super.sleepHours;
|
||||
}
|
||||
|
||||
@override
|
||||
set sleepHours(int value) {
|
||||
_$sleepHoursAtom.reportWrite(value, super.sleepHours, () {
|
||||
super.sleepHours = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$sleepMinutesAtom = Atom(name: '_VideoStoreBase.sleepMinutes');
|
||||
|
||||
@override
|
||||
int get sleepMinutes {
|
||||
_$sleepMinutesAtom.reportRead();
|
||||
return super.sleepMinutes;
|
||||
}
|
||||
|
||||
@override
|
||||
set sleepMinutes(int value) {
|
||||
_$sleepMinutesAtom.reportWrite(value, super.sleepMinutes, () {
|
||||
super.sleepMinutes = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$timeRemainingAtom = Atom(name: '_VideoStoreBase.timeRemaining');
|
||||
|
||||
@override
|
||||
Duration get timeRemaining {
|
||||
_$timeRemainingAtom.reportRead();
|
||||
return super.timeRemaining;
|
||||
}
|
||||
|
||||
@override
|
||||
set timeRemaining(Duration value) {
|
||||
_$timeRemainingAtom.reportWrite(value, super.timeRemaining, () {
|
||||
super.timeRemaining = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$_pausedAtom = Atom(name: '_VideoStoreBase._paused');
|
||||
|
||||
bool get paused {
|
||||
|
|
@ -124,6 +169,9 @@ mixin _$VideoStore on _VideoStoreBase, Store {
|
|||
@override
|
||||
String toString() {
|
||||
return '''
|
||||
sleepHours: ${sleepHours},
|
||||
sleepMinutes: ${sleepMinutes},
|
||||
timeRemaining: ${timeRemaining},
|
||||
videoUrl: ${videoUrl}
|
||||
''';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -12,6 +13,69 @@ class VideoOverlay extends StatelessWidget {
|
|||
|
||||
const VideoOverlay({Key? key, required this.videoStore}) : super(key: key);
|
||||
|
||||
Future<void> _showSleepTimerDialog(BuildContext context) {
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Sleep Timer'),
|
||||
content: Observer(
|
||||
builder: (context) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
DropdownButton(
|
||||
value: videoStore.sleepHours,
|
||||
items: List.generate(24, (index) => index).map((e) => DropdownMenuItem(value: e, child: Text(e.toString()))).toList(),
|
||||
onChanged: (int? hours) => videoStore.sleepHours = hours!,
|
||||
menuMaxHeight: 200,
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
const Text('Hours'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
DropdownButton(
|
||||
value: videoStore.sleepMinutes,
|
||||
items: List.generate(60, (index) => index).map((e) => DropdownMenuItem(value: e, child: Text(e.toString()))).toList(),
|
||||
onChanged: (int? minutes) => videoStore.sleepMinutes = minutes!,
|
||||
menuMaxHeight: 200,
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
const Text('Minutes'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text('Timer: ${videoStore.timeRemaining.toString().split('.')[0]}'),
|
||||
const Spacer(),
|
||||
IconButton(
|
||||
onPressed: videoStore.cancelSleepTimer,
|
||||
icon: const Icon(Icons.cancel),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: Navigator.of(context).pop,
|
||||
child: const Text('Close'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: videoStore.updateSleepTimer,
|
||||
child: const Text('Set Timer'),
|
||||
style: TextButton.styleFrom(primary: Colors.green),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final orientation = MediaQuery.of(context).orientation;
|
||||
|
|
@ -70,7 +134,7 @@ class VideoOverlay extends StatelessWidget {
|
|||
final sleepTimerButton = IconButton(
|
||||
tooltip: 'Sleep Timer',
|
||||
icon: const Icon(Icons.timer),
|
||||
onPressed: () {},
|
||||
onPressed: () => _showSleepTimerDialog(context),
|
||||
);
|
||||
|
||||
final streamInfo = videoStore.streamInfo;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue