ui: better sleep timer ui in player and fix auto turn on settings (#43)

* refactor: enhance sleep timer functionality and improve duration formatting

* refactor: update sleep timer settings handling

* refactor: update cancel icon for sleep timer button

* refactor: implement isBetween method for TimeOfDay and simplify sleep timer logic

* refactor: update alwaysAutoTurnOnTimer default value and improve icon usage in settings

* refactor: remove unused IconButton and update sleep timer preset durations
This commit is contained in:
Dr.Blank 2024-10-02 09:18:06 -04:00 committed by GitHub
parent 933bfc5750
commit 12100ffbcd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 755 additions and 383 deletions

View file

@ -1,17 +1,11 @@
import 'package:duration_picker/duration_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:miniplayer/miniplayer.dart'; import 'package:miniplayer/miniplayer.dart';
import 'package:vaani/constants/sizes.dart'; import 'package:vaani/constants/sizes.dart';
import 'package:vaani/features/player/providers/currently_playing_provider.dart'; import 'package:vaani/features/player/providers/currently_playing_provider.dart';
import 'package:vaani/features/player/providers/player_form.dart'; import 'package:vaani/features/player/providers/player_form.dart';
import 'package:vaani/features/player/view/audiobook_player.dart'; import 'package:vaani/features/player/view/audiobook_player.dart';
import 'package:vaani/features/sleep_timer/core/sleep_timer.dart'; import 'package:vaani/features/sleep_timer/view/sleep_timer_button.dart';
import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart'
show sleepTimerProvider;
import 'package:vaani/settings/app_settings_provider.dart';
import 'package:vaani/shared/extensions/duration_format.dart';
import 'package:vaani/shared/extensions/inverse_lerp.dart'; import 'package:vaani/shared/extensions/inverse_lerp.dart';
import 'package:vaani/shared/widgets/not_implemented.dart'; import 'package:vaani/shared/widgets/not_implemented.dart';
@ -246,143 +240,18 @@ class PlayerWhenExpanded extends HookConsumerWidget {
// chapter list // chapter list
const ChapterSelectionButton(), const ChapterSelectionButton(),
// settings // settings
IconButton( // IconButton(
icon: const Icon(Icons.more_horiz), // icon: const Icon(Icons.more_horiz),
onPressed: () { // onPressed: () {
// show toast // // show toast
showNotImplementedToast(context); // showNotImplementedToast(context);
}, // },
),
],
),
),
),
],
);
}
}
class SleepTimerButton extends HookConsumerWidget {
const SleepTimerButton({
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final sleepTimer = ref.watch(sleepTimerProvider);
// if sleep timer is not active, show the button with the sleep timer icon
// if the sleep timer is active, show the remaining time in a pill shaped container
return Tooltip(
message: 'Sleep Timer',
child: InkWell(
onTap: () async {
pendingPlayerModals++;
// show the sleep timer dialog
final resultingDuration = await showDurationPicker(
context: context,
initialTime: ref
.watch(appSettingsProvider)
.playerSettings
.sleepTimerSettings
.defaultDuration,
);
pendingPlayerModals--;
if (resultingDuration != null) {
// if 0 is selected, cancel the timer
if (resultingDuration.inSeconds == 0) {
ref.read(sleepTimerProvider.notifier).cancelTimer();
} else {
ref.read(sleepTimerProvider.notifier).setTimer(resultingDuration);
}
}
},
child: sleepTimer == null
? Icon(
Icons.timer_rounded,
color: Theme.of(context).colorScheme.onSurface,
)
: RemainingSleepTimeDisplay(
timer: sleepTimer,
),
),
);
}
}
class SleepTimerDialog extends HookConsumerWidget {
const SleepTimerDialog({
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final sleepTimer = ref.watch(sleepTimerProvider);
final sleepTimerSettings =
ref.watch(appSettingsProvider).playerSettings.sleepTimerSettings;
final timerDurationController = useTextEditingController(
text: sleepTimerSettings.defaultDuration.inMinutes.toString(),
);
return AlertDialog(
title: const Text('Sleep Timer'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Set the duration for the sleep timer'),
TextField(
controller: timerDurationController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
labelText: 'Duration in minutes',
),
),
],
),
actions: [
TextButton(
onPressed: () {
// sleepTimer.setTimer(
// Duration(
// minutes: int.tryParse(timerDurationController.text) ?? 0,
// ), // ),
// ); ],
Navigator.of(context).pop(); ),
}, ),
child: const Text('Set Timer'),
), ),
], ],
); );
} }
} }
class RemainingSleepTimeDisplay extends HookConsumerWidget {
const RemainingSleepTimeDisplay({
super.key,
required this.timer,
});
final SleepTimer timer;
@override
Widget build(BuildContext context, WidgetRef ref) {
final remainingTime = useStream(timer.remainingTimeStream).data;
return Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primary,
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 4,
),
child: Text(
timer.timer == null
? timer.duration.smartBinaryFormat
: remainingTime?.smartBinaryFormat ?? '',
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
),
);
}
}

View file

@ -6,6 +6,9 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:list_wheel_scroll_view_nls/list_wheel_scroll_view_nls.dart'; import 'package:list_wheel_scroll_view_nls/list_wheel_scroll_view_nls.dart';
import 'package:vaani/features/player/providers/audiobook_player.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart';
import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/app_settings_provider.dart';
import 'package:vaani/shared/hooks.dart';
const double itemExtent = 25;
class SpeedSelector extends HookConsumerWidget { class SpeedSelector extends HookConsumerWidget {
const SpeedSelector({ const SpeedSelector({
@ -34,11 +37,11 @@ class SpeedSelector extends HookConsumerWidget {
// the speed options // the speed options
final minSpeed = min( final minSpeed = min(
speeds.reduce((minSpeedSoFar, element) => min(minSpeedSoFar, element)), speeds.reduce(min),
playerSettings.minSpeed, playerSettings.minSpeed,
); );
final maxSpeed = max( final maxSpeed = max(
speeds.reduce((maxSpeedSoFar, element) => max(maxSpeedSoFar, element)), speeds.reduce(max),
playerSettings.maxSpeed, playerSettings.maxSpeed,
); );
final speedIncrement = playerSettings.speedIncrement; final speedIncrement = playerSettings.speedIncrement;
@ -53,10 +56,9 @@ class SpeedSelector extends HookConsumerWidget {
}, },
); );
final scrollController = FixedExtentScrollController( final scrollController = useFixedExtentScrollController(
initialItem: availableSpeedsList.indexOf(currentSpeed), initialItem: availableSpeedsList.indexOf(currentSpeed),
); );
const double itemExtent = 25;
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -89,7 +91,6 @@ class SpeedSelector extends HookConsumerWidget {
availableSpeedsList: availableSpeedsList, availableSpeedsList: availableSpeedsList,
speedState: speedState, speedState: speedState,
scrollController: scrollController, scrollController: scrollController,
itemExtent: itemExtent,
), ),
), ),
), ),
@ -159,14 +160,12 @@ class SpeedWheel extends StatelessWidget {
required this.availableSpeedsList, required this.availableSpeedsList,
required this.speedState, required this.speedState,
required this.scrollController, required this.scrollController,
required this.itemExtent,
this.showIncrementButtons = true, this.showIncrementButtons = true,
}); });
final List<double> availableSpeedsList; final List<double> availableSpeedsList;
final ValueNotifier<double> speedState; final ValueNotifier<double> speedState;
final FixedExtentScrollController scrollController; final FixedExtentScrollController scrollController;
final double itemExtent;
final bool showIncrementButtons; final bool showIncrementButtons;
@override @override
@ -203,7 +202,7 @@ class SpeedWheel extends StatelessWidget {
physics: const FixedExtentScrollPhysics(), physics: const FixedExtentScrollPhysics(),
children: availableSpeedsList children: availableSpeedsList
.map( .map(
(speed) => SpeedLine(itemExtent: itemExtent, speed: speed), (speed) => SpeedLine(speed: speed),
) )
.toList(), .toList(),
onSelectedItemChanged: (index) { onSelectedItemChanged: (index) {
@ -236,11 +235,9 @@ class SpeedWheel extends StatelessWidget {
class SpeedLine extends StatelessWidget { class SpeedLine extends StatelessWidget {
const SpeedLine({ const SpeedLine({
super.key, super.key,
required this.itemExtent,
required this.speed, required this.speed,
}); });
final double itemExtent;
final double speed; final double speed;
@override @override
@ -250,7 +247,6 @@ class SpeedLine extends StatelessWidget {
// a vertical line // a vertical line
Expanded( Expanded(
child: Container( child: Container(
// height: itemExtent,
// thick if multiple of 1, thin if multiple of 0.5 and transparent if multiple of 0.05 // thick if multiple of 1, thin if multiple of 0.5 and transparent if multiple of 0.05
width: speed % 0.5 == 0 width: speed % 0.5 == 0
? 3 ? 3

View file

@ -19,8 +19,18 @@ class SleepTimer {
set duration(Duration value) { set duration(Duration value) {
_duration = value; _duration = value;
_logger.fine('duration set to $value');
/// if the timer is active, restart it with the new duration
/// if the timer is not active, do nothing
if (isActive && player.playing) {
_logger.fine('timer is active counting down with new duration');
startCountDown(value);
} else {
_logger.fine('timer is not active');
clearCountDownTimer(); clearCountDownTimer();
} }
}
/// The player to be paused /// The player to be paused
final AudiobookPlayer player; final AudiobookPlayer player;

View file

@ -11,20 +11,16 @@ part 'sleep_timer_provider.g.dart';
class SleepTimer extends _$SleepTimer { class SleepTimer extends _$SleepTimer {
@override @override
core.SleepTimer? build() { core.SleepTimer? build() {
final appSettings = ref.watch(appSettingsProvider); final sleepTimerSettings = ref.watch(sleepTimerSettingsProvider);
final sleepTimerSettings = appSettings.playerSettings.sleepTimerSettings; if (!sleepTimerSettings.autoTurnOnTimer) {
bool isEnabled = sleepTimerSettings.autoTurnOnTimer;
if (!isEnabled) {
return null; return null;
} }
if ((!sleepTimerSettings.alwaysAutoTurnOnTimer) && if ((!sleepTimerSettings.alwaysAutoTurnOnTimer) &&
(sleepTimerSettings.autoTurnOnTime !shouldBuildRightNow(
.toTimeOfDay() sleepTimerSettings.autoTurnOnTime,
.isAfter(TimeOfDay.now()) && sleepTimerSettings.autoTurnOffTime,
sleepTimerSettings.autoTurnOffTime )) {
.toTimeOfDay()
.isBefore(TimeOfDay.now()))) {
return null; return null;
} }
@ -36,10 +32,16 @@ class SleepTimer extends _$SleepTimer {
return sleepTimer; return sleepTimer;
} }
void setTimer(Duration resultingDuration) { void setTimer(Duration? resultingDuration, {bool notifyListeners = true}) {
if (resultingDuration == null || resultingDuration.inSeconds == 0) {
cancelTimer();
return;
}
if (state != null) { if (state != null) {
state!.duration = resultingDuration; state!.duration = resultingDuration;
if (notifyListeners) {
ref.notifyListeners(); ref.notifyListeners();
}
} else { } else {
final timer = core.SleepTimer( final timer = core.SleepTimer(
duration: resultingDuration, duration: resultingDuration,
@ -62,3 +64,11 @@ class SleepTimer extends _$SleepTimer {
state = null; state = null;
} }
} }
bool shouldBuildRightNow(Duration autoTurnOnTime, Duration autoTurnOffTime) {
final now = TimeOfDay.now();
return now.isBetween(
autoTurnOnTime.toTimeOfDay(),
autoTurnOffTime.toTimeOfDay(),
);
}

View file

@ -6,7 +6,7 @@ part of 'sleep_timer_provider.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$sleepTimerHash() => r'4f80bcc342e918c70c547b8b24790ccd88aba8c3'; String _$sleepTimerHash() => r'2679454a217d0630a833d730557ab4e4feac2e56';
/// See also [SleepTimer]. /// See also [SleepTimer].
@ProviderFor(SleepTimer) @ProviderFor(SleepTimer)

View file

@ -0,0 +1,366 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:list_wheel_scroll_view_nls/list_wheel_scroll_view_nls.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:vaani/features/player/view/player_when_expanded.dart';
import 'package:vaani/features/player/view/widgets/speed_selector.dart';
import 'package:vaani/features/sleep_timer/core/sleep_timer.dart';
import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart'
show sleepTimerProvider;
import 'package:vaani/main.dart';
import 'package:vaani/settings/app_settings_provider.dart';
import 'package:vaani/shared/extensions/duration_format.dart';
import 'package:vaani/shared/hooks.dart';
class SleepTimerButton extends HookConsumerWidget {
const SleepTimerButton({
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final sleepTimer = ref.watch(sleepTimerProvider);
final durationState = useState(sleepTimer?.duration);
// if sleep timer is not active, show the button with the sleep timer icon
// if the sleep timer is active, show the remaining time in a pill shaped container
return Tooltip(
message: 'Sleep Timer',
child: InkWell(
onTap: () async {
appLogger.fine('Sleep Timer button pressed');
pendingPlayerModals++;
// show the sleep timer dialog
await showModalBottomSheet<Duration?>(
context: context,
barrierLabel: 'Sleep Timer',
builder: (context) {
return SleepTimerBottomSheet(
onDurationSelected: (duration) {
durationState.value = duration;
// ref
// .read(sleepTimerProvider.notifier)
// .setTimer(duration, notifyListeners: false);
},
);
},
);
pendingPlayerModals--;
ref.read(sleepTimerProvider.notifier).setTimer(durationState.value);
appLogger
.fine('Sleep Timer dialog closed with ${durationState.value}');
},
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: sleepTimer == null
? Icon(
Symbols.bedtime,
color: Theme.of(context).colorScheme.onSurface,
)
: RemainingSleepTimeDisplay(
timer: sleepTimer,
),
),
),
);
}
}
class SleepTimerBottomSheet extends HookConsumerWidget {
const SleepTimerBottomSheet({
super.key,
this.onDurationSelected,
});
final void Function(Duration?)? onDurationSelected;
@override
Widget build(BuildContext context, WidgetRef ref) {
final sleepTimer = ref.watch(sleepTimerProvider);
final sleepTimerSettings = ref.watch(sleepTimerSettingsProvider);
final durationOptions = sleepTimerSettings.presetDurations;
final minDuration = Duration.zero;
final maxDuration = <Duration>[
...durationOptions,
sleepTimerSettings.maxDuration,
].reduce((a, b) => a > b ? a : b);
final incrementStep = Duration(minutes: 1);
final allPossibleDurations = [
for (var i = minDuration; i <= maxDuration; i += incrementStep) i,
];
final scrollController = useFixedExtentScrollController(
initialItem:
allPossibleDurations.indexOf(sleepTimer?.duration ?? minDuration),
);
final durationState = useState<Duration>(
sleepTimer?.duration ?? minDuration,
);
// useEffect to rebuild the sleep timer when the duration changes
useEffect(
() {
onDurationSelected?.call(durationState.value);
return null;
},
[durationState.value],
);
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// the title
Padding(
padding: const EdgeInsets.only(top: 16.0, bottom: 8.0),
child: Center(
child: Text(
'Sleep Timer',
style: Theme.of(context).textTheme.titleLarge,
),
),
),
// a inverted triangle to indicate the speed selector
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Icon(
Icons.arrow_drop_down,
color: Theme.of(context).colorScheme.onSurface,
),
),
// the speed selector
Padding(
padding: const EdgeInsets.only(bottom: 8.0, right: 8.0, left: 8.0),
child: SizedBox(
height: 80,
child: SleepTimerWheel(
durationState: durationState,
availableDurations: allPossibleDurations,
scrollController: scrollController,
),
),
),
// a cancel button to cancel the sleep timer
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: TextButton.icon(
onPressed: () {
ref.read(sleepTimerProvider.notifier).cancelTimer();
onDurationSelected?.call(null);
Navigator.of(context).pop();
},
icon: const Icon(Symbols.bedtime_off),
label: const Text('Cancel Sleep Timer'),
),
),
// the speed buttons
Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
spacing: 8.0,
alignment: WrapAlignment.center,
runAlignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
children: durationOptions
.map(
(timerDuration) => TextButton(
style: timerDuration == durationState.value
? TextButton.styleFrom(
backgroundColor:
Theme.of(context).colorScheme.primaryContainer,
foregroundColor: Theme.of(context)
.colorScheme
.onPrimaryContainer,
)
// border if not selected
: TextButton.styleFrom(
side: BorderSide(
color: Theme.of(context)
.colorScheme
.primaryContainer,
),
),
onPressed: () async {
// animate the wheel to the selected speed
var index = allPossibleDurations.indexOf(timerDuration);
// if the speed is not in the list
if (index == -1) {
// find the nearest speed
final nearestDuration = allPossibleDurations.firstWhere(
(element) => element > timerDuration,
orElse: () => allPossibleDurations.last,
);
index = allPossibleDurations.indexOf(nearestDuration);
}
await scrollController.animateToItem(
index,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
},
child: Text(timerDuration.smartBinaryFormat),
),
)
.toList(),
),
),
],
);
}
}
class RemainingSleepTimeDisplay extends HookConsumerWidget {
const RemainingSleepTimeDisplay({
super.key,
required this.timer,
});
final SleepTimer timer;
@override
Widget build(BuildContext context, WidgetRef ref) {
final remainingTime = useStream(timer.remainingTimeStream).data;
return Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primary,
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 4,
),
child: Text(
timer.timer == null
? timer.duration.smartBinaryFormat
: remainingTime?.smartBinaryFormat ?? '',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
),
);
}
}
class SleepTimerWheel extends StatelessWidget {
const SleepTimerWheel({
super.key,
required this.availableDurations,
required this.scrollController,
required this.durationState,
this.showIncrementButtons = true,
});
final List<Duration> availableDurations;
final ValueNotifier<Duration?> durationState;
final FixedExtentScrollController scrollController;
final bool showIncrementButtons;
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// a minus button to decrease the speed
if (showIncrementButtons)
IconButton.filledTonal(
icon: const Icon(Icons.remove),
onPressed: () {
// animate to index - 1
final index = availableDurations
.indexOf(durationState.value ?? Duration.zero);
if (index > 0) {
scrollController.animateToItem(
index - 1,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
},
),
// the speed selector wheel
Flexible(
child: ListWheelScrollViewX(
controller: scrollController,
scrollDirection: Axis.horizontal,
itemExtent: itemExtent,
diameterRatio: 1.5, squeeze: 1.2,
// useMagnifier: true,
// magnification: 1.5,
physics: const FixedExtentScrollPhysics(),
children: availableDurations
.map(
(duration) => DurationLine(duration: duration),
)
.toList(),
onSelectedItemChanged: (index) {
durationState.value = availableDurations[index];
},
),
),
if (showIncrementButtons)
// a plus button to increase the speed
IconButton.filledTonal(
icon: const Icon(Icons.add),
onPressed: () {
// animate to index + 1
final index = availableDurations
.indexOf(durationState.value ?? Duration.zero);
if (index < availableDurations.length - 1) {
scrollController.animateToItem(
index + 1,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
},
),
],
);
}
}
class DurationLine extends StatelessWidget {
const DurationLine({
super.key,
required this.duration,
});
final Duration duration;
@override
Widget build(BuildContext context) {
return Column(
children: [
// a vertical line
Expanded(
child: Container(
// thick if multiple of 1, thin if multiple of 0.5 and transparent if multiple of 0.05
width: duration.inMinutes % 5 == 0
? 3
: duration.inMinutes % 2.5 == 0
? 2
: 0.5,
color: Theme.of(context).colorScheme.onSurface,
),
),
Opacity(
opacity: duration.inMinutes % 2.5 == 0 ? 1 : 0,
child: Text(
'${duration.inMinutes}m',
style: TextStyle(
fontSize: Theme.of(context).textTheme.labelSmall?.fontSize,
),
),
),
],
);
}
}

View file

@ -60,3 +60,19 @@ class AppSettings extends _$AppSettings {
state = const model.AppSettings(); state = const model.AppSettings();
} }
} }
// SleepTimerSettings provider but only rebuilds when the sleep timer settings change
@Riverpod(keepAlive: true)
class SleepTimerSettings extends _$SleepTimerSettings {
@override
model.SleepTimerSettings build() {
final settings = ref.read(appSettingsProvider).sleepTimerSettings;
state = settings;
ref.listen(appSettingsProvider, (a, b) {
if (a?.sleepTimerSettings != b.sleepTimerSettings) {
state = b.sleepTimerSettings;
}
});
return state;
}
}

View file

@ -21,5 +21,22 @@ final appSettingsProvider =
); );
typedef _$AppSettings = Notifier<model.AppSettings>; typedef _$AppSettings = Notifier<model.AppSettings>;
String _$sleepTimerSettingsHash() =>
r'85bb3d3fb292b9a3a5b771d86e5fc57718519c69';
/// See also [SleepTimerSettings].
@ProviderFor(SleepTimerSettings)
final sleepTimerSettingsProvider =
NotifierProvider<SleepTimerSettings, model.SleepTimerSettings>.internal(
SleepTimerSettings.new,
name: r'sleepTimerSettingsProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
? null
: _$sleepTimerSettingsHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$SleepTimerSettings = Notifier<model.SleepTimerSettings>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View file

@ -14,6 +14,7 @@ class AppSettings with _$AppSettings {
const factory AppSettings({ const factory AppSettings({
@Default(ThemeSettings()) ThemeSettings themeSettings, @Default(ThemeSettings()) ThemeSettings themeSettings,
@Default(PlayerSettings()) PlayerSettings playerSettings, @Default(PlayerSettings()) PlayerSettings playerSettings,
@Default(SleepTimerSettings()) SleepTimerSettings sleepTimerSettings,
@Default(DownloadSettings()) DownloadSettings downloadSettings, @Default(DownloadSettings()) DownloadSettings downloadSettings,
@Default(NotificationSettings()) NotificationSettings notificationSettings, @Default(NotificationSettings()) NotificationSettings notificationSettings,
@Default(ShakeDetectionSettings()) @Default(ShakeDetectionSettings())
@ -49,7 +50,6 @@ class PlayerSettings with _$PlayerSettings {
@Default(0.05) double speedIncrement, @Default(0.05) double speedIncrement,
@Default(0.1) double minSpeed, @Default(0.1) double minSpeed,
@Default(4) double maxSpeed, @Default(4) double maxSpeed,
@Default(SleepTimerSettings()) SleepTimerSettings sleepTimerSettings,
@Default(Duration(seconds: 10)) Duration minimumPositionForReporting, @Default(Duration(seconds: 10)) Duration minimumPositionForReporting,
@Default(Duration(seconds: 10)) Duration playbackReportInterval, @Default(Duration(seconds: 10)) Duration playbackReportInterval,
@Default(Duration(seconds: 15)) Duration markCompleteWhenTimeLeft, @Default(Duration(seconds: 15)) Duration markCompleteWhenTimeLeft,
@ -81,22 +81,23 @@ class MinimizedPlayerSettings with _$MinimizedPlayerSettings {
_$MinimizedPlayerSettingsFromJson(json); _$MinimizedPlayerSettingsFromJson(json);
} }
enum SleepTimerShakeSenseMode { never, always, nearEnds }
@freezed @freezed
class SleepTimerSettings with _$SleepTimerSettings { class SleepTimerSettings with _$SleepTimerSettings {
const factory SleepTimerSettings({ const factory SleepTimerSettings({
@Default(Duration(minutes: 15)) Duration defaultDuration, @Default(Duration(minutes: 15)) Duration defaultDuration,
@Default(SleepTimerShakeSenseMode.always) @Default(
SleepTimerShakeSenseMode shakeSenseMode, [
Duration(minutes: 5),
/// the duration in which the shake is detected before the end of the timer and after the timer ends Duration(minutes: 10),
/// only used if [shakeSenseMode] is [SleepTimerShakeSenseMode.nearEnds] Duration(minutes: 15),
@Default(Duration(seconds: 30)) Duration shakeSenseDuration, Duration(minutes: 20),
@Default(true) bool vibrateWhenReset, Duration(minutes: 30),
@Default(false) bool beepWhenReset, ],
)
List<Duration> presetDurations,
@Default(Duration(minutes: 100)) Duration maxDuration,
@Default(false) bool fadeOutAudio, @Default(false) bool fadeOutAudio,
@Default(0.5) double shakeDetectThreshold, @Default(Duration(seconds: 20)) Duration fadeOutDuration,
/// if true, the player will automatically rewind the audio when the sleep timer is stopped /// if true, the player will automatically rewind the audio when the sleep timer is stopped
@Default(false) bool autoRewindWhenStopped, @Default(false) bool autoRewindWhenStopped,
@ -115,7 +116,7 @@ class SleepTimerSettings with _$SleepTimerSettings {
@Default(false) bool autoTurnOnTimer, @Default(false) bool autoTurnOnTimer,
/// always auto turn on timer settings or during specific times /// always auto turn on timer settings or during specific times
@Default(true) bool alwaysAutoTurnOnTimer, @Default(false) bool alwaysAutoTurnOnTimer,
/// auto timer settings, only used if [alwaysAutoTurnOnTimer] is false /// auto timer settings, only used if [alwaysAutoTurnOnTimer] is false
/// ///

View file

@ -22,6 +22,8 @@ AppSettings _$AppSettingsFromJson(Map<String, dynamic> json) {
mixin _$AppSettings { mixin _$AppSettings {
ThemeSettings get themeSettings => throw _privateConstructorUsedError; ThemeSettings get themeSettings => throw _privateConstructorUsedError;
PlayerSettings get playerSettings => throw _privateConstructorUsedError; PlayerSettings get playerSettings => throw _privateConstructorUsedError;
SleepTimerSettings get sleepTimerSettings =>
throw _privateConstructorUsedError;
DownloadSettings get downloadSettings => throw _privateConstructorUsedError; DownloadSettings get downloadSettings => throw _privateConstructorUsedError;
NotificationSettings get notificationSettings => NotificationSettings get notificationSettings =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@ -47,12 +49,14 @@ abstract class $AppSettingsCopyWith<$Res> {
$Res call( $Res call(
{ThemeSettings themeSettings, {ThemeSettings themeSettings,
PlayerSettings playerSettings, PlayerSettings playerSettings,
SleepTimerSettings sleepTimerSettings,
DownloadSettings downloadSettings, DownloadSettings downloadSettings,
NotificationSettings notificationSettings, NotificationSettings notificationSettings,
ShakeDetectionSettings shakeDetectionSettings}); ShakeDetectionSettings shakeDetectionSettings});
$ThemeSettingsCopyWith<$Res> get themeSettings; $ThemeSettingsCopyWith<$Res> get themeSettings;
$PlayerSettingsCopyWith<$Res> get playerSettings; $PlayerSettingsCopyWith<$Res> get playerSettings;
$SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings;
$DownloadSettingsCopyWith<$Res> get downloadSettings; $DownloadSettingsCopyWith<$Res> get downloadSettings;
$NotificationSettingsCopyWith<$Res> get notificationSettings; $NotificationSettingsCopyWith<$Res> get notificationSettings;
$ShakeDetectionSettingsCopyWith<$Res> get shakeDetectionSettings; $ShakeDetectionSettingsCopyWith<$Res> get shakeDetectionSettings;
@ -75,6 +79,7 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings>
$Res call({ $Res call({
Object? themeSettings = null, Object? themeSettings = null,
Object? playerSettings = null, Object? playerSettings = null,
Object? sleepTimerSettings = null,
Object? downloadSettings = null, Object? downloadSettings = null,
Object? notificationSettings = null, Object? notificationSettings = null,
Object? shakeDetectionSettings = null, Object? shakeDetectionSettings = null,
@ -88,6 +93,10 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings>
? _value.playerSettings ? _value.playerSettings
: playerSettings // ignore: cast_nullable_to_non_nullable : playerSettings // ignore: cast_nullable_to_non_nullable
as PlayerSettings, as PlayerSettings,
sleepTimerSettings: null == sleepTimerSettings
? _value.sleepTimerSettings
: sleepTimerSettings // ignore: cast_nullable_to_non_nullable
as SleepTimerSettings,
downloadSettings: null == downloadSettings downloadSettings: null == downloadSettings
? _value.downloadSettings ? _value.downloadSettings
: downloadSettings // ignore: cast_nullable_to_non_nullable : downloadSettings // ignore: cast_nullable_to_non_nullable
@ -123,6 +132,17 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings>
}); });
} }
/// Create a copy of AppSettings
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings {
return $SleepTimerSettingsCopyWith<$Res>(_value.sleepTimerSettings,
(value) {
return _then(_value.copyWith(sleepTimerSettings: value) as $Val);
});
}
/// Create a copy of AppSettings /// Create a copy of AppSettings
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @override
@ -167,6 +187,7 @@ abstract class _$$AppSettingsImplCopyWith<$Res>
$Res call( $Res call(
{ThemeSettings themeSettings, {ThemeSettings themeSettings,
PlayerSettings playerSettings, PlayerSettings playerSettings,
SleepTimerSettings sleepTimerSettings,
DownloadSettings downloadSettings, DownloadSettings downloadSettings,
NotificationSettings notificationSettings, NotificationSettings notificationSettings,
ShakeDetectionSettings shakeDetectionSettings}); ShakeDetectionSettings shakeDetectionSettings});
@ -176,6 +197,8 @@ abstract class _$$AppSettingsImplCopyWith<$Res>
@override @override
$PlayerSettingsCopyWith<$Res> get playerSettings; $PlayerSettingsCopyWith<$Res> get playerSettings;
@override @override
$SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings;
@override
$DownloadSettingsCopyWith<$Res> get downloadSettings; $DownloadSettingsCopyWith<$Res> get downloadSettings;
@override @override
$NotificationSettingsCopyWith<$Res> get notificationSettings; $NotificationSettingsCopyWith<$Res> get notificationSettings;
@ -198,6 +221,7 @@ class __$$AppSettingsImplCopyWithImpl<$Res>
$Res call({ $Res call({
Object? themeSettings = null, Object? themeSettings = null,
Object? playerSettings = null, Object? playerSettings = null,
Object? sleepTimerSettings = null,
Object? downloadSettings = null, Object? downloadSettings = null,
Object? notificationSettings = null, Object? notificationSettings = null,
Object? shakeDetectionSettings = null, Object? shakeDetectionSettings = null,
@ -211,6 +235,10 @@ class __$$AppSettingsImplCopyWithImpl<$Res>
? _value.playerSettings ? _value.playerSettings
: playerSettings // ignore: cast_nullable_to_non_nullable : playerSettings // ignore: cast_nullable_to_non_nullable
as PlayerSettings, as PlayerSettings,
sleepTimerSettings: null == sleepTimerSettings
? _value.sleepTimerSettings
: sleepTimerSettings // ignore: cast_nullable_to_non_nullable
as SleepTimerSettings,
downloadSettings: null == downloadSettings downloadSettings: null == downloadSettings
? _value.downloadSettings ? _value.downloadSettings
: downloadSettings // ignore: cast_nullable_to_non_nullable : downloadSettings // ignore: cast_nullable_to_non_nullable
@ -233,6 +261,7 @@ class _$AppSettingsImpl implements _AppSettings {
const _$AppSettingsImpl( const _$AppSettingsImpl(
{this.themeSettings = const ThemeSettings(), {this.themeSettings = const ThemeSettings(),
this.playerSettings = const PlayerSettings(), this.playerSettings = const PlayerSettings(),
this.sleepTimerSettings = const SleepTimerSettings(),
this.downloadSettings = const DownloadSettings(), this.downloadSettings = const DownloadSettings(),
this.notificationSettings = const NotificationSettings(), this.notificationSettings = const NotificationSettings(),
this.shakeDetectionSettings = const ShakeDetectionSettings()}); this.shakeDetectionSettings = const ShakeDetectionSettings()});
@ -248,6 +277,9 @@ class _$AppSettingsImpl implements _AppSettings {
final PlayerSettings playerSettings; final PlayerSettings playerSettings;
@override @override
@JsonKey() @JsonKey()
final SleepTimerSettings sleepTimerSettings;
@override
@JsonKey()
final DownloadSettings downloadSettings; final DownloadSettings downloadSettings;
@override @override
@JsonKey() @JsonKey()
@ -258,7 +290,7 @@ class _$AppSettingsImpl implements _AppSettings {
@override @override
String toString() { String toString() {
return 'AppSettings(themeSettings: $themeSettings, playerSettings: $playerSettings, downloadSettings: $downloadSettings, notificationSettings: $notificationSettings, shakeDetectionSettings: $shakeDetectionSettings)'; return 'AppSettings(themeSettings: $themeSettings, playerSettings: $playerSettings, sleepTimerSettings: $sleepTimerSettings, downloadSettings: $downloadSettings, notificationSettings: $notificationSettings, shakeDetectionSettings: $shakeDetectionSettings)';
} }
@override @override
@ -270,6 +302,8 @@ class _$AppSettingsImpl implements _AppSettings {
other.themeSettings == themeSettings) && other.themeSettings == themeSettings) &&
(identical(other.playerSettings, playerSettings) || (identical(other.playerSettings, playerSettings) ||
other.playerSettings == playerSettings) && other.playerSettings == playerSettings) &&
(identical(other.sleepTimerSettings, sleepTimerSettings) ||
other.sleepTimerSettings == sleepTimerSettings) &&
(identical(other.downloadSettings, downloadSettings) || (identical(other.downloadSettings, downloadSettings) ||
other.downloadSettings == downloadSettings) && other.downloadSettings == downloadSettings) &&
(identical(other.notificationSettings, notificationSettings) || (identical(other.notificationSettings, notificationSettings) ||
@ -280,8 +314,14 @@ class _$AppSettingsImpl implements _AppSettings {
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => Object.hash(runtimeType, themeSettings, playerSettings, int get hashCode => Object.hash(
downloadSettings, notificationSettings, shakeDetectionSettings); runtimeType,
themeSettings,
playerSettings,
sleepTimerSettings,
downloadSettings,
notificationSettings,
shakeDetectionSettings);
/// Create a copy of AppSettings /// Create a copy of AppSettings
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@ -303,6 +343,7 @@ abstract class _AppSettings implements AppSettings {
const factory _AppSettings( const factory _AppSettings(
{final ThemeSettings themeSettings, {final ThemeSettings themeSettings,
final PlayerSettings playerSettings, final PlayerSettings playerSettings,
final SleepTimerSettings sleepTimerSettings,
final DownloadSettings downloadSettings, final DownloadSettings downloadSettings,
final NotificationSettings notificationSettings, final NotificationSettings notificationSettings,
final ShakeDetectionSettings shakeDetectionSettings}) = _$AppSettingsImpl; final ShakeDetectionSettings shakeDetectionSettings}) = _$AppSettingsImpl;
@ -315,6 +356,8 @@ abstract class _AppSettings implements AppSettings {
@override @override
PlayerSettings get playerSettings; PlayerSettings get playerSettings;
@override @override
SleepTimerSettings get sleepTimerSettings;
@override
DownloadSettings get downloadSettings; DownloadSettings get downloadSettings;
@override @override
NotificationSettings get notificationSettings; NotificationSettings get notificationSettings;
@ -552,8 +595,6 @@ mixin _$PlayerSettings {
double get speedIncrement => throw _privateConstructorUsedError; double get speedIncrement => throw _privateConstructorUsedError;
double get minSpeed => throw _privateConstructorUsedError; double get minSpeed => throw _privateConstructorUsedError;
double get maxSpeed => throw _privateConstructorUsedError; double get maxSpeed => throw _privateConstructorUsedError;
SleepTimerSettings get sleepTimerSettings =>
throw _privateConstructorUsedError;
Duration get minimumPositionForReporting => Duration get minimumPositionForReporting =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
Duration get playbackReportInterval => throw _privateConstructorUsedError; Duration get playbackReportInterval => throw _privateConstructorUsedError;
@ -585,7 +626,6 @@ abstract class $PlayerSettingsCopyWith<$Res> {
double speedIncrement, double speedIncrement,
double minSpeed, double minSpeed,
double maxSpeed, double maxSpeed,
SleepTimerSettings sleepTimerSettings,
Duration minimumPositionForReporting, Duration minimumPositionForReporting,
Duration playbackReportInterval, Duration playbackReportInterval,
Duration markCompleteWhenTimeLeft, Duration markCompleteWhenTimeLeft,
@ -593,7 +633,6 @@ abstract class $PlayerSettingsCopyWith<$Res> {
$MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings; $MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings;
$ExpandedPlayerSettingsCopyWith<$Res> get expandedPlayerSettings; $ExpandedPlayerSettingsCopyWith<$Res> get expandedPlayerSettings;
$SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings;
} }
/// @nodoc /// @nodoc
@ -619,7 +658,6 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings>
Object? speedIncrement = null, Object? speedIncrement = null,
Object? minSpeed = null, Object? minSpeed = null,
Object? maxSpeed = null, Object? maxSpeed = null,
Object? sleepTimerSettings = null,
Object? minimumPositionForReporting = null, Object? minimumPositionForReporting = null,
Object? playbackReportInterval = null, Object? playbackReportInterval = null,
Object? markCompleteWhenTimeLeft = null, Object? markCompleteWhenTimeLeft = null,
@ -658,10 +696,6 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings>
? _value.maxSpeed ? _value.maxSpeed
: maxSpeed // ignore: cast_nullable_to_non_nullable : maxSpeed // ignore: cast_nullable_to_non_nullable
as double, as double,
sleepTimerSettings: null == sleepTimerSettings
? _value.sleepTimerSettings
: sleepTimerSettings // ignore: cast_nullable_to_non_nullable
as SleepTimerSettings,
minimumPositionForReporting: null == minimumPositionForReporting minimumPositionForReporting: null == minimumPositionForReporting
? _value.minimumPositionForReporting ? _value.minimumPositionForReporting
: minimumPositionForReporting // ignore: cast_nullable_to_non_nullable : minimumPositionForReporting // ignore: cast_nullable_to_non_nullable
@ -702,17 +736,6 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings>
return _then(_value.copyWith(expandedPlayerSettings: value) as $Val); return _then(_value.copyWith(expandedPlayerSettings: value) as $Val);
}); });
} }
/// Create a copy of PlayerSettings
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings {
return $SleepTimerSettingsCopyWith<$Res>(_value.sleepTimerSettings,
(value) {
return _then(_value.copyWith(sleepTimerSettings: value) as $Val);
});
}
} }
/// @nodoc /// @nodoc
@ -732,7 +755,6 @@ abstract class _$$PlayerSettingsImplCopyWith<$Res>
double speedIncrement, double speedIncrement,
double minSpeed, double minSpeed,
double maxSpeed, double maxSpeed,
SleepTimerSettings sleepTimerSettings,
Duration minimumPositionForReporting, Duration minimumPositionForReporting,
Duration playbackReportInterval, Duration playbackReportInterval,
Duration markCompleteWhenTimeLeft, Duration markCompleteWhenTimeLeft,
@ -742,8 +764,6 @@ abstract class _$$PlayerSettingsImplCopyWith<$Res>
$MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings; $MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings;
@override @override
$ExpandedPlayerSettingsCopyWith<$Res> get expandedPlayerSettings; $ExpandedPlayerSettingsCopyWith<$Res> get expandedPlayerSettings;
@override
$SleepTimerSettingsCopyWith<$Res> get sleepTimerSettings;
} }
/// @nodoc /// @nodoc
@ -767,7 +787,6 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res>
Object? speedIncrement = null, Object? speedIncrement = null,
Object? minSpeed = null, Object? minSpeed = null,
Object? maxSpeed = null, Object? maxSpeed = null,
Object? sleepTimerSettings = null,
Object? minimumPositionForReporting = null, Object? minimumPositionForReporting = null,
Object? playbackReportInterval = null, Object? playbackReportInterval = null,
Object? markCompleteWhenTimeLeft = null, Object? markCompleteWhenTimeLeft = null,
@ -806,10 +825,6 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res>
? _value.maxSpeed ? _value.maxSpeed
: maxSpeed // ignore: cast_nullable_to_non_nullable : maxSpeed // ignore: cast_nullable_to_non_nullable
as double, as double,
sleepTimerSettings: null == sleepTimerSettings
? _value.sleepTimerSettings
: sleepTimerSettings // ignore: cast_nullable_to_non_nullable
as SleepTimerSettings,
minimumPositionForReporting: null == minimumPositionForReporting minimumPositionForReporting: null == minimumPositionForReporting
? _value.minimumPositionForReporting ? _value.minimumPositionForReporting
: minimumPositionForReporting // ignore: cast_nullable_to_non_nullable : minimumPositionForReporting // ignore: cast_nullable_to_non_nullable
@ -842,7 +857,6 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
this.speedIncrement = 0.05, this.speedIncrement = 0.05,
this.minSpeed = 0.1, this.minSpeed = 0.1,
this.maxSpeed = 4, this.maxSpeed = 4,
this.sleepTimerSettings = const SleepTimerSettings(),
this.minimumPositionForReporting = const Duration(seconds: 10), this.minimumPositionForReporting = const Duration(seconds: 10),
this.playbackReportInterval = const Duration(seconds: 10), this.playbackReportInterval = const Duration(seconds: 10),
this.markCompleteWhenTimeLeft = const Duration(seconds: 15), this.markCompleteWhenTimeLeft = const Duration(seconds: 15),
@ -884,9 +898,6 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
final double maxSpeed; final double maxSpeed;
@override @override
@JsonKey() @JsonKey()
final SleepTimerSettings sleepTimerSettings;
@override
@JsonKey()
final Duration minimumPositionForReporting; final Duration minimumPositionForReporting;
@override @override
@JsonKey() @JsonKey()
@ -900,7 +911,7 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
@override @override
String toString() { String toString() {
return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, speedIncrement: $speedIncrement, minSpeed: $minSpeed, maxSpeed: $maxSpeed, sleepTimerSettings: $sleepTimerSettings, minimumPositionForReporting: $minimumPositionForReporting, playbackReportInterval: $playbackReportInterval, markCompleteWhenTimeLeft: $markCompleteWhenTimeLeft, configurePlayerForEveryBook: $configurePlayerForEveryBook)'; return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, speedIncrement: $speedIncrement, minSpeed: $minSpeed, maxSpeed: $maxSpeed, minimumPositionForReporting: $minimumPositionForReporting, playbackReportInterval: $playbackReportInterval, markCompleteWhenTimeLeft: $markCompleteWhenTimeLeft, configurePlayerForEveryBook: $configurePlayerForEveryBook)';
} }
@override @override
@ -924,8 +935,6 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
other.minSpeed == minSpeed) && other.minSpeed == minSpeed) &&
(identical(other.maxSpeed, maxSpeed) || (identical(other.maxSpeed, maxSpeed) ||
other.maxSpeed == maxSpeed) && other.maxSpeed == maxSpeed) &&
(identical(other.sleepTimerSettings, sleepTimerSettings) ||
other.sleepTimerSettings == sleepTimerSettings) &&
(identical(other.minimumPositionForReporting, (identical(other.minimumPositionForReporting,
minimumPositionForReporting) || minimumPositionForReporting) ||
other.minimumPositionForReporting == other.minimumPositionForReporting ==
@ -953,7 +962,6 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
speedIncrement, speedIncrement,
minSpeed, minSpeed,
maxSpeed, maxSpeed,
sleepTimerSettings,
minimumPositionForReporting, minimumPositionForReporting,
playbackReportInterval, playbackReportInterval,
markCompleteWhenTimeLeft, markCompleteWhenTimeLeft,
@ -986,7 +994,6 @@ abstract class _PlayerSettings implements PlayerSettings {
final double speedIncrement, final double speedIncrement,
final double minSpeed, final double minSpeed,
final double maxSpeed, final double maxSpeed,
final SleepTimerSettings sleepTimerSettings,
final Duration minimumPositionForReporting, final Duration minimumPositionForReporting,
final Duration playbackReportInterval, final Duration playbackReportInterval,
final Duration markCompleteWhenTimeLeft, final Duration markCompleteWhenTimeLeft,
@ -1012,8 +1019,6 @@ abstract class _PlayerSettings implements PlayerSettings {
@override @override
double get maxSpeed; double get maxSpeed;
@override @override
SleepTimerSettings get sleepTimerSettings;
@override
Duration get minimumPositionForReporting; Duration get minimumPositionForReporting;
@override @override
Duration get playbackReportInterval; Duration get playbackReportInterval;
@ -1374,16 +1379,10 @@ SleepTimerSettings _$SleepTimerSettingsFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$SleepTimerSettings { mixin _$SleepTimerSettings {
Duration get defaultDuration => throw _privateConstructorUsedError; Duration get defaultDuration => throw _privateConstructorUsedError;
SleepTimerShakeSenseMode get shakeSenseMode => List<Duration> get presetDurations => throw _privateConstructorUsedError;
throw _privateConstructorUsedError; Duration get maxDuration => throw _privateConstructorUsedError;
/// the duration in which the shake is detected before the end of the timer and after the timer ends
/// only used if [shakeSenseMode] is [SleepTimerShakeSenseMode.nearEnds]
Duration get shakeSenseDuration => throw _privateConstructorUsedError;
bool get vibrateWhenReset => throw _privateConstructorUsedError;
bool get beepWhenReset => throw _privateConstructorUsedError;
bool get fadeOutAudio => throw _privateConstructorUsedError; bool get fadeOutAudio => throw _privateConstructorUsedError;
double get shakeDetectThreshold => throw _privateConstructorUsedError; Duration get fadeOutDuration => throw _privateConstructorUsedError;
/// if true, the player will automatically rewind the audio when the sleep timer is stopped /// if true, the player will automatically rewind the audio when the sleep timer is stopped
bool get autoRewindWhenStopped => throw _privateConstructorUsedError; bool get autoRewindWhenStopped => throw _privateConstructorUsedError;
@ -1422,12 +1421,10 @@ abstract class $SleepTimerSettingsCopyWith<$Res> {
@useResult @useResult
$Res call( $Res call(
{Duration defaultDuration, {Duration defaultDuration,
SleepTimerShakeSenseMode shakeSenseMode, List<Duration> presetDurations,
Duration shakeSenseDuration, Duration maxDuration,
bool vibrateWhenReset,
bool beepWhenReset,
bool fadeOutAudio, bool fadeOutAudio,
double shakeDetectThreshold, Duration fadeOutDuration,
bool autoRewindWhenStopped, bool autoRewindWhenStopped,
Map<int, Duration> autoRewindDurations, Map<int, Duration> autoRewindDurations,
bool autoTurnOnTimer, bool autoTurnOnTimer,
@ -1452,12 +1449,10 @@ class _$SleepTimerSettingsCopyWithImpl<$Res, $Val extends SleepTimerSettings>
@override @override
$Res call({ $Res call({
Object? defaultDuration = null, Object? defaultDuration = null,
Object? shakeSenseMode = null, Object? presetDurations = null,
Object? shakeSenseDuration = null, Object? maxDuration = null,
Object? vibrateWhenReset = null,
Object? beepWhenReset = null,
Object? fadeOutAudio = null, Object? fadeOutAudio = null,
Object? shakeDetectThreshold = null, Object? fadeOutDuration = null,
Object? autoRewindWhenStopped = null, Object? autoRewindWhenStopped = null,
Object? autoRewindDurations = null, Object? autoRewindDurations = null,
Object? autoTurnOnTimer = null, Object? autoTurnOnTimer = null,
@ -1470,30 +1465,22 @@ class _$SleepTimerSettingsCopyWithImpl<$Res, $Val extends SleepTimerSettings>
? _value.defaultDuration ? _value.defaultDuration
: defaultDuration // ignore: cast_nullable_to_non_nullable : defaultDuration // ignore: cast_nullable_to_non_nullable
as Duration, as Duration,
shakeSenseMode: null == shakeSenseMode presetDurations: null == presetDurations
? _value.shakeSenseMode ? _value.presetDurations
: shakeSenseMode // ignore: cast_nullable_to_non_nullable : presetDurations // ignore: cast_nullable_to_non_nullable
as SleepTimerShakeSenseMode, as List<Duration>,
shakeSenseDuration: null == shakeSenseDuration maxDuration: null == maxDuration
? _value.shakeSenseDuration ? _value.maxDuration
: shakeSenseDuration // ignore: cast_nullable_to_non_nullable : maxDuration // ignore: cast_nullable_to_non_nullable
as Duration, as Duration,
vibrateWhenReset: null == vibrateWhenReset
? _value.vibrateWhenReset
: vibrateWhenReset // ignore: cast_nullable_to_non_nullable
as bool,
beepWhenReset: null == beepWhenReset
? _value.beepWhenReset
: beepWhenReset // ignore: cast_nullable_to_non_nullable
as bool,
fadeOutAudio: null == fadeOutAudio fadeOutAudio: null == fadeOutAudio
? _value.fadeOutAudio ? _value.fadeOutAudio
: fadeOutAudio // ignore: cast_nullable_to_non_nullable : fadeOutAudio // ignore: cast_nullable_to_non_nullable
as bool, as bool,
shakeDetectThreshold: null == shakeDetectThreshold fadeOutDuration: null == fadeOutDuration
? _value.shakeDetectThreshold ? _value.fadeOutDuration
: shakeDetectThreshold // ignore: cast_nullable_to_non_nullable : fadeOutDuration // ignore: cast_nullable_to_non_nullable
as double, as Duration,
autoRewindWhenStopped: null == autoRewindWhenStopped autoRewindWhenStopped: null == autoRewindWhenStopped
? _value.autoRewindWhenStopped ? _value.autoRewindWhenStopped
: autoRewindWhenStopped // ignore: cast_nullable_to_non_nullable : autoRewindWhenStopped // ignore: cast_nullable_to_non_nullable
@ -1532,12 +1519,10 @@ abstract class _$$SleepTimerSettingsImplCopyWith<$Res>
@useResult @useResult
$Res call( $Res call(
{Duration defaultDuration, {Duration defaultDuration,
SleepTimerShakeSenseMode shakeSenseMode, List<Duration> presetDurations,
Duration shakeSenseDuration, Duration maxDuration,
bool vibrateWhenReset,
bool beepWhenReset,
bool fadeOutAudio, bool fadeOutAudio,
double shakeDetectThreshold, Duration fadeOutDuration,
bool autoRewindWhenStopped, bool autoRewindWhenStopped,
Map<int, Duration> autoRewindDurations, Map<int, Duration> autoRewindDurations,
bool autoTurnOnTimer, bool autoTurnOnTimer,
@ -1560,12 +1545,10 @@ class __$$SleepTimerSettingsImplCopyWithImpl<$Res>
@override @override
$Res call({ $Res call({
Object? defaultDuration = null, Object? defaultDuration = null,
Object? shakeSenseMode = null, Object? presetDurations = null,
Object? shakeSenseDuration = null, Object? maxDuration = null,
Object? vibrateWhenReset = null,
Object? beepWhenReset = null,
Object? fadeOutAudio = null, Object? fadeOutAudio = null,
Object? shakeDetectThreshold = null, Object? fadeOutDuration = null,
Object? autoRewindWhenStopped = null, Object? autoRewindWhenStopped = null,
Object? autoRewindDurations = null, Object? autoRewindDurations = null,
Object? autoTurnOnTimer = null, Object? autoTurnOnTimer = null,
@ -1578,30 +1561,22 @@ class __$$SleepTimerSettingsImplCopyWithImpl<$Res>
? _value.defaultDuration ? _value.defaultDuration
: defaultDuration // ignore: cast_nullable_to_non_nullable : defaultDuration // ignore: cast_nullable_to_non_nullable
as Duration, as Duration,
shakeSenseMode: null == shakeSenseMode presetDurations: null == presetDurations
? _value.shakeSenseMode ? _value._presetDurations
: shakeSenseMode // ignore: cast_nullable_to_non_nullable : presetDurations // ignore: cast_nullable_to_non_nullable
as SleepTimerShakeSenseMode, as List<Duration>,
shakeSenseDuration: null == shakeSenseDuration maxDuration: null == maxDuration
? _value.shakeSenseDuration ? _value.maxDuration
: shakeSenseDuration // ignore: cast_nullable_to_non_nullable : maxDuration // ignore: cast_nullable_to_non_nullable
as Duration, as Duration,
vibrateWhenReset: null == vibrateWhenReset
? _value.vibrateWhenReset
: vibrateWhenReset // ignore: cast_nullable_to_non_nullable
as bool,
beepWhenReset: null == beepWhenReset
? _value.beepWhenReset
: beepWhenReset // ignore: cast_nullable_to_non_nullable
as bool,
fadeOutAudio: null == fadeOutAudio fadeOutAudio: null == fadeOutAudio
? _value.fadeOutAudio ? _value.fadeOutAudio
: fadeOutAudio // ignore: cast_nullable_to_non_nullable : fadeOutAudio // ignore: cast_nullable_to_non_nullable
as bool, as bool,
shakeDetectThreshold: null == shakeDetectThreshold fadeOutDuration: null == fadeOutDuration
? _value.shakeDetectThreshold ? _value.fadeOutDuration
: shakeDetectThreshold // ignore: cast_nullable_to_non_nullable : fadeOutDuration // ignore: cast_nullable_to_non_nullable
as double, as Duration,
autoRewindWhenStopped: null == autoRewindWhenStopped autoRewindWhenStopped: null == autoRewindWhenStopped
? _value.autoRewindWhenStopped ? _value.autoRewindWhenStopped
: autoRewindWhenStopped // ignore: cast_nullable_to_non_nullable : autoRewindWhenStopped // ignore: cast_nullable_to_non_nullable
@ -1635,12 +1610,16 @@ class __$$SleepTimerSettingsImplCopyWithImpl<$Res>
class _$SleepTimerSettingsImpl implements _SleepTimerSettings { class _$SleepTimerSettingsImpl implements _SleepTimerSettings {
const _$SleepTimerSettingsImpl( const _$SleepTimerSettingsImpl(
{this.defaultDuration = const Duration(minutes: 15), {this.defaultDuration = const Duration(minutes: 15),
this.shakeSenseMode = SleepTimerShakeSenseMode.always, final List<Duration> presetDurations = const [
this.shakeSenseDuration = const Duration(seconds: 30), Duration(minutes: 5),
this.vibrateWhenReset = true, Duration(minutes: 10),
this.beepWhenReset = false, Duration(minutes: 15),
Duration(minutes: 20),
Duration(minutes: 30)
],
this.maxDuration = const Duration(minutes: 100),
this.fadeOutAudio = false, this.fadeOutAudio = false,
this.shakeDetectThreshold = 0.5, this.fadeOutDuration = const Duration(seconds: 20),
this.autoRewindWhenStopped = false, this.autoRewindWhenStopped = false,
final Map<int, Duration> autoRewindDurations = const { final Map<int, Duration> autoRewindDurations = const {
5: Duration(seconds: 10), 5: Duration(seconds: 10),
@ -1650,10 +1629,11 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings {
120: Duration(minutes: 2) 120: Duration(minutes: 2)
}, },
this.autoTurnOnTimer = false, this.autoTurnOnTimer = false,
this.alwaysAutoTurnOnTimer = true, this.alwaysAutoTurnOnTimer = false,
this.autoTurnOnTime = const Duration(hours: 22, minutes: 0), this.autoTurnOnTime = const Duration(hours: 22, minutes: 0),
this.autoTurnOffTime = const Duration(hours: 6, minutes: 0)}) this.autoTurnOffTime = const Duration(hours: 6, minutes: 0)})
: _autoRewindDurations = autoRewindDurations; : _presetDurations = presetDurations,
_autoRewindDurations = autoRewindDurations;
factory _$SleepTimerSettingsImpl.fromJson(Map<String, dynamic> json) => factory _$SleepTimerSettingsImpl.fromJson(Map<String, dynamic> json) =>
_$$SleepTimerSettingsImplFromJson(json); _$$SleepTimerSettingsImplFromJson(json);
@ -1661,27 +1641,24 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings {
@override @override
@JsonKey() @JsonKey()
final Duration defaultDuration; final Duration defaultDuration;
final List<Duration> _presetDurations;
@override @override
@JsonKey() @JsonKey()
final SleepTimerShakeSenseMode shakeSenseMode; List<Duration> get presetDurations {
if (_presetDurations is EqualUnmodifiableListView) return _presetDurations;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_presetDurations);
}
/// the duration in which the shake is detected before the end of the timer and after the timer ends
/// only used if [shakeSenseMode] is [SleepTimerShakeSenseMode.nearEnds]
@override @override
@JsonKey() @JsonKey()
final Duration shakeSenseDuration; final Duration maxDuration;
@override
@JsonKey()
final bool vibrateWhenReset;
@override
@JsonKey()
final bool beepWhenReset;
@override @override
@JsonKey() @JsonKey()
final bool fadeOutAudio; final bool fadeOutAudio;
@override @override
@JsonKey() @JsonKey()
final double shakeDetectThreshold; final Duration fadeOutDuration;
/// if true, the player will automatically rewind the audio when the sleep timer is stopped /// if true, the player will automatically rewind the audio when the sleep timer is stopped
@override @override
@ -1723,7 +1700,7 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings {
@override @override
String toString() { String toString() {
return 'SleepTimerSettings(defaultDuration: $defaultDuration, shakeSenseMode: $shakeSenseMode, shakeSenseDuration: $shakeSenseDuration, vibrateWhenReset: $vibrateWhenReset, beepWhenReset: $beepWhenReset, fadeOutAudio: $fadeOutAudio, shakeDetectThreshold: $shakeDetectThreshold, autoRewindWhenStopped: $autoRewindWhenStopped, autoRewindDurations: $autoRewindDurations, autoTurnOnTimer: $autoTurnOnTimer, alwaysAutoTurnOnTimer: $alwaysAutoTurnOnTimer, autoTurnOnTime: $autoTurnOnTime, autoTurnOffTime: $autoTurnOffTime)'; return 'SleepTimerSettings(defaultDuration: $defaultDuration, presetDurations: $presetDurations, maxDuration: $maxDuration, fadeOutAudio: $fadeOutAudio, fadeOutDuration: $fadeOutDuration, autoRewindWhenStopped: $autoRewindWhenStopped, autoRewindDurations: $autoRewindDurations, autoTurnOnTimer: $autoTurnOnTimer, alwaysAutoTurnOnTimer: $alwaysAutoTurnOnTimer, autoTurnOnTime: $autoTurnOnTime, autoTurnOffTime: $autoTurnOffTime)';
} }
@override @override
@ -1733,18 +1710,14 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings {
other is _$SleepTimerSettingsImpl && other is _$SleepTimerSettingsImpl &&
(identical(other.defaultDuration, defaultDuration) || (identical(other.defaultDuration, defaultDuration) ||
other.defaultDuration == defaultDuration) && other.defaultDuration == defaultDuration) &&
(identical(other.shakeSenseMode, shakeSenseMode) || const DeepCollectionEquality()
other.shakeSenseMode == shakeSenseMode) && .equals(other._presetDurations, _presetDurations) &&
(identical(other.shakeSenseDuration, shakeSenseDuration) || (identical(other.maxDuration, maxDuration) ||
other.shakeSenseDuration == shakeSenseDuration) && other.maxDuration == maxDuration) &&
(identical(other.vibrateWhenReset, vibrateWhenReset) ||
other.vibrateWhenReset == vibrateWhenReset) &&
(identical(other.beepWhenReset, beepWhenReset) ||
other.beepWhenReset == beepWhenReset) &&
(identical(other.fadeOutAudio, fadeOutAudio) || (identical(other.fadeOutAudio, fadeOutAudio) ||
other.fadeOutAudio == fadeOutAudio) && other.fadeOutAudio == fadeOutAudio) &&
(identical(other.shakeDetectThreshold, shakeDetectThreshold) || (identical(other.fadeOutDuration, fadeOutDuration) ||
other.shakeDetectThreshold == shakeDetectThreshold) && other.fadeOutDuration == fadeOutDuration) &&
(identical(other.autoRewindWhenStopped, autoRewindWhenStopped) || (identical(other.autoRewindWhenStopped, autoRewindWhenStopped) ||
other.autoRewindWhenStopped == autoRewindWhenStopped) && other.autoRewindWhenStopped == autoRewindWhenStopped) &&
const DeepCollectionEquality() const DeepCollectionEquality()
@ -1764,12 +1737,10 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings {
int get hashCode => Object.hash( int get hashCode => Object.hash(
runtimeType, runtimeType,
defaultDuration, defaultDuration,
shakeSenseMode, const DeepCollectionEquality().hash(_presetDurations),
shakeSenseDuration, maxDuration,
vibrateWhenReset,
beepWhenReset,
fadeOutAudio, fadeOutAudio,
shakeDetectThreshold, fadeOutDuration,
autoRewindWhenStopped, autoRewindWhenStopped,
const DeepCollectionEquality().hash(_autoRewindDurations), const DeepCollectionEquality().hash(_autoRewindDurations),
autoTurnOnTimer, autoTurnOnTimer,
@ -1797,12 +1768,10 @@ class _$SleepTimerSettingsImpl implements _SleepTimerSettings {
abstract class _SleepTimerSettings implements SleepTimerSettings { abstract class _SleepTimerSettings implements SleepTimerSettings {
const factory _SleepTimerSettings( const factory _SleepTimerSettings(
{final Duration defaultDuration, {final Duration defaultDuration,
final SleepTimerShakeSenseMode shakeSenseMode, final List<Duration> presetDurations,
final Duration shakeSenseDuration, final Duration maxDuration,
final bool vibrateWhenReset,
final bool beepWhenReset,
final bool fadeOutAudio, final bool fadeOutAudio,
final double shakeDetectThreshold, final Duration fadeOutDuration,
final bool autoRewindWhenStopped, final bool autoRewindWhenStopped,
final Map<int, Duration> autoRewindDurations, final Map<int, Duration> autoRewindDurations,
final bool autoTurnOnTimer, final bool autoTurnOnTimer,
@ -1816,20 +1785,13 @@ abstract class _SleepTimerSettings implements SleepTimerSettings {
@override @override
Duration get defaultDuration; Duration get defaultDuration;
@override @override
SleepTimerShakeSenseMode get shakeSenseMode; List<Duration> get presetDurations;
/// the duration in which the shake is detected before the end of the timer and after the timer ends
/// only used if [shakeSenseMode] is [SleepTimerShakeSenseMode.nearEnds]
@override @override
Duration get shakeSenseDuration; Duration get maxDuration;
@override
bool get vibrateWhenReset;
@override
bool get beepWhenReset;
@override @override
bool get fadeOutAudio; bool get fadeOutAudio;
@override @override
double get shakeDetectThreshold; Duration get fadeOutDuration;
/// if true, the player will automatically rewind the audio when the sleep timer is stopped /// if true, the player will automatically rewind the audio when the sleep timer is stopped
@override @override

View file

@ -16,6 +16,10 @@ _$AppSettingsImpl _$$AppSettingsImplFromJson(Map<String, dynamic> json) =>
? const PlayerSettings() ? const PlayerSettings()
: PlayerSettings.fromJson( : PlayerSettings.fromJson(
json['playerSettings'] as Map<String, dynamic>), json['playerSettings'] as Map<String, dynamic>),
sleepTimerSettings: json['sleepTimerSettings'] == null
? const SleepTimerSettings()
: SleepTimerSettings.fromJson(
json['sleepTimerSettings'] as Map<String, dynamic>),
downloadSettings: json['downloadSettings'] == null downloadSettings: json['downloadSettings'] == null
? const DownloadSettings() ? const DownloadSettings()
: DownloadSettings.fromJson( : DownloadSettings.fromJson(
@ -34,6 +38,7 @@ Map<String, dynamic> _$$AppSettingsImplToJson(_$AppSettingsImpl instance) =>
<String, dynamic>{ <String, dynamic>{
'themeSettings': instance.themeSettings, 'themeSettings': instance.themeSettings,
'playerSettings': instance.playerSettings, 'playerSettings': instance.playerSettings,
'sleepTimerSettings': instance.sleepTimerSettings,
'downloadSettings': instance.downloadSettings, 'downloadSettings': instance.downloadSettings,
'notificationSettings': instance.notificationSettings, 'notificationSettings': instance.notificationSettings,
'shakeDetectionSettings': instance.shakeDetectionSettings, 'shakeDetectionSettings': instance.shakeDetectionSettings,
@ -77,10 +82,6 @@ _$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map<String, dynamic> json) =>
speedIncrement: (json['speedIncrement'] as num?)?.toDouble() ?? 0.05, speedIncrement: (json['speedIncrement'] as num?)?.toDouble() ?? 0.05,
minSpeed: (json['minSpeed'] as num?)?.toDouble() ?? 0.1, minSpeed: (json['minSpeed'] as num?)?.toDouble() ?? 0.1,
maxSpeed: (json['maxSpeed'] as num?)?.toDouble() ?? 4, maxSpeed: (json['maxSpeed'] as num?)?.toDouble() ?? 4,
sleepTimerSettings: json['sleepTimerSettings'] == null
? const SleepTimerSettings()
: SleepTimerSettings.fromJson(
json['sleepTimerSettings'] as Map<String, dynamic>),
minimumPositionForReporting: json['minimumPositionForReporting'] == null minimumPositionForReporting: json['minimumPositionForReporting'] == null
? const Duration(seconds: 10) ? const Duration(seconds: 10)
: Duration( : Duration(
@ -109,7 +110,6 @@ Map<String, dynamic> _$$PlayerSettingsImplToJson(
'speedIncrement': instance.speedIncrement, 'speedIncrement': instance.speedIncrement,
'minSpeed': instance.minSpeed, 'minSpeed': instance.minSpeed,
'maxSpeed': instance.maxSpeed, 'maxSpeed': instance.maxSpeed,
'sleepTimerSettings': instance.sleepTimerSettings,
'minimumPositionForReporting': 'minimumPositionForReporting':
instance.minimumPositionForReporting.inMicroseconds, instance.minimumPositionForReporting.inMicroseconds,
'playbackReportInterval': instance.playbackReportInterval.inMicroseconds, 'playbackReportInterval': instance.playbackReportInterval.inMicroseconds,
@ -150,17 +150,23 @@ _$SleepTimerSettingsImpl _$$SleepTimerSettingsImplFromJson(
defaultDuration: json['defaultDuration'] == null defaultDuration: json['defaultDuration'] == null
? const Duration(minutes: 15) ? const Duration(minutes: 15)
: Duration(microseconds: (json['defaultDuration'] as num).toInt()), : Duration(microseconds: (json['defaultDuration'] as num).toInt()),
shakeSenseMode: $enumDecodeNullable( presetDurations: (json['presetDurations'] as List<dynamic>?)
_$SleepTimerShakeSenseModeEnumMap, json['shakeSenseMode']) ?? ?.map((e) => Duration(microseconds: (e as num).toInt()))
SleepTimerShakeSenseMode.always, .toList() ??
shakeSenseDuration: json['shakeSenseDuration'] == null const [
? const Duration(seconds: 30) Duration(minutes: 5),
: Duration(microseconds: (json['shakeSenseDuration'] as num).toInt()), Duration(minutes: 10),
vibrateWhenReset: json['vibrateWhenReset'] as bool? ?? true, Duration(minutes: 15),
beepWhenReset: json['beepWhenReset'] as bool? ?? false, Duration(minutes: 20),
Duration(minutes: 30)
],
maxDuration: json['maxDuration'] == null
? const Duration(minutes: 100)
: Duration(microseconds: (json['maxDuration'] as num).toInt()),
fadeOutAudio: json['fadeOutAudio'] as bool? ?? false, fadeOutAudio: json['fadeOutAudio'] as bool? ?? false,
shakeDetectThreshold: fadeOutDuration: json['fadeOutDuration'] == null
(json['shakeDetectThreshold'] as num?)?.toDouble() ?? 0.5, ? const Duration(seconds: 20)
: Duration(microseconds: (json['fadeOutDuration'] as num).toInt()),
autoRewindWhenStopped: json['autoRewindWhenStopped'] as bool? ?? false, autoRewindWhenStopped: json['autoRewindWhenStopped'] as bool? ?? false,
autoRewindDurations: autoRewindDurations:
(json['autoRewindDurations'] as Map<String, dynamic>?)?.map( (json['autoRewindDurations'] as Map<String, dynamic>?)?.map(
@ -175,7 +181,7 @@ _$SleepTimerSettingsImpl _$$SleepTimerSettingsImplFromJson(
120: Duration(minutes: 2) 120: Duration(minutes: 2)
}, },
autoTurnOnTimer: json['autoTurnOnTimer'] as bool? ?? false, autoTurnOnTimer: json['autoTurnOnTimer'] as bool? ?? false,
alwaysAutoTurnOnTimer: json['alwaysAutoTurnOnTimer'] as bool? ?? true, alwaysAutoTurnOnTimer: json['alwaysAutoTurnOnTimer'] as bool? ?? false,
autoTurnOnTime: json['autoTurnOnTime'] == null autoTurnOnTime: json['autoTurnOnTime'] == null
? const Duration(hours: 22, minutes: 0) ? const Duration(hours: 22, minutes: 0)
: Duration(microseconds: (json['autoTurnOnTime'] as num).toInt()), : Duration(microseconds: (json['autoTurnOnTime'] as num).toInt()),
@ -188,13 +194,11 @@ Map<String, dynamic> _$$SleepTimerSettingsImplToJson(
_$SleepTimerSettingsImpl instance) => _$SleepTimerSettingsImpl instance) =>
<String, dynamic>{ <String, dynamic>{
'defaultDuration': instance.defaultDuration.inMicroseconds, 'defaultDuration': instance.defaultDuration.inMicroseconds,
'shakeSenseMode': 'presetDurations':
_$SleepTimerShakeSenseModeEnumMap[instance.shakeSenseMode]!, instance.presetDurations.map((e) => e.inMicroseconds).toList(),
'shakeSenseDuration': instance.shakeSenseDuration.inMicroseconds, 'maxDuration': instance.maxDuration.inMicroseconds,
'vibrateWhenReset': instance.vibrateWhenReset,
'beepWhenReset': instance.beepWhenReset,
'fadeOutAudio': instance.fadeOutAudio, 'fadeOutAudio': instance.fadeOutAudio,
'shakeDetectThreshold': instance.shakeDetectThreshold, 'fadeOutDuration': instance.fadeOutDuration.inMicroseconds,
'autoRewindWhenStopped': instance.autoRewindWhenStopped, 'autoRewindWhenStopped': instance.autoRewindWhenStopped,
'autoRewindDurations': instance.autoRewindDurations 'autoRewindDurations': instance.autoRewindDurations
.map((k, e) => MapEntry(k.toString(), e.inMicroseconds)), .map((k, e) => MapEntry(k.toString(), e.inMicroseconds)),
@ -204,12 +208,6 @@ Map<String, dynamic> _$$SleepTimerSettingsImplToJson(
'autoTurnOffTime': instance.autoTurnOffTime.inMicroseconds, 'autoTurnOffTime': instance.autoTurnOffTime.inMicroseconds,
}; };
const _$SleepTimerShakeSenseModeEnumMap = {
SleepTimerShakeSenseMode.never: 'never',
SleepTimerShakeSenseMode.always: 'always',
SleepTimerShakeSenseMode.nearEnds: 'nearEnds',
};
_$DownloadSettingsImpl _$$DownloadSettingsImplFromJson( _$DownloadSettingsImpl _$$DownloadSettingsImplFromJson(
Map<String, dynamic> json) => Map<String, dynamic> json) =>
_$DownloadSettingsImpl( _$DownloadSettingsImpl(

View file

@ -6,6 +6,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_settings_ui/flutter_settings_ui.dart'; import 'package:flutter_settings_ui/flutter_settings_ui.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:vaani/api/authenticated_user_provider.dart'; import 'package:vaani/api/authenticated_user_provider.dart';
import 'package:vaani/api/server_provider.dart'; import 'package:vaani/api/server_provider.dart';
import 'package:vaani/router/router.dart'; import 'package:vaani/router/router.dart';
@ -26,7 +27,7 @@ class AppSettingsPage extends HookConsumerWidget {
final registeredServersAsList = registeredServers.toList(); final registeredServersAsList = registeredServers.toList();
final availableUsers = ref.watch(authenticatedUserProvider); final availableUsers = ref.watch(authenticatedUserProvider);
final serverURIController = useTextEditingController(); final serverURIController = useTextEditingController();
final sleepTimerSettings = appSettings.playerSettings.sleepTimerSettings; final sleepTimerSettings = appSettings.sleepTimerSettings;
return SimpleSettingsPage( return SimpleSettingsPage(
title: const Text('App Settings'), title: const Text('App Settings'),
@ -91,15 +92,15 @@ class AppSettingsPage extends HookConsumerWidget {
'Automatically turn on the sleep timer based on the time of day', 'Automatically turn on the sleep timer based on the time of day',
), ),
leading: sleepTimerSettings.autoTurnOnTimer leading: sleepTimerSettings.autoTurnOnTimer
? const Icon(Icons.timer) ? const Icon(Symbols.time_auto, fill: 1)
: const Icon(Icons.timer_off), : const Icon(Symbols.timer_off, fill: 1),
onPressed: (context) { onPressed: (context) {
context.pushNamed(Routes.autoSleepTimerSettings.name); context.pushNamed(Routes.autoSleepTimerSettings.name);
}, },
value: sleepTimerSettings.autoTurnOnTimer, value: sleepTimerSettings.autoTurnOnTimer,
onToggle: (value) { onToggle: (value) {
ref.read(appSettingsProvider.notifier).update( ref.read(appSettingsProvider.notifier).update(
appSettings.copyWith.playerSettings.sleepTimerSettings( appSettings.copyWith.sleepTimerSettings(
autoTurnOnTimer: value, autoTurnOnTimer: value,
), ),
); );

View file

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_settings_ui/flutter_settings_ui.dart'; import 'package:flutter_settings_ui/flutter_settings_ui.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/app_settings_provider.dart';
import 'package:vaani/settings/view/simple_settings_page.dart'; import 'package:vaani/settings/view/simple_settings_page.dart';
import 'package:vaani/shared/extensions/time_of_day.dart'; import 'package:vaani/shared/extensions/time_of_day.dart';
@ -13,8 +14,13 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final appSettings = ref.watch(appSettingsProvider); final appSettings = ref.watch(appSettingsProvider);
final sleepTimerSettings = appSettings.playerSettings.sleepTimerSettings; final sleepTimerSettings = appSettings.sleepTimerSettings;
var enabled = sleepTimerSettings.autoTurnOnTimer &&
!sleepTimerSettings.alwaysAutoTurnOnTimer;
final selectedValueColor = enabled
? Theme.of(context).colorScheme.primary
: Theme.of(context).disabledColor;
return SimpleSettingsPage( return SimpleSettingsPage(
title: const Text('Auto Sleep Timer Settings'), title: const Text('Auto Sleep Timer Settings'),
sections: [ sections: [
@ -31,11 +37,11 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget {
'Automatically turn on the sleep timer based on the time of day', 'Automatically turn on the sleep timer based on the time of day',
), ),
leading: sleepTimerSettings.autoTurnOnTimer leading: sleepTimerSettings.autoTurnOnTimer
? const Icon(Icons.timer) ? const Icon(Symbols.time_auto)
: const Icon(Icons.timer_off), : const Icon(Symbols.timer_off),
onToggle: (value) { onToggle: (value) {
ref.read(appSettingsProvider.notifier).update( ref.read(appSettingsProvider.notifier).update(
appSettings.copyWith.playerSettings.sleepTimerSettings( appSettings.copyWith.sleepTimerSettings(
autoTurnOnTimer: value, autoTurnOnTimer: value,
), ),
); );
@ -44,8 +50,9 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget {
), ),
// auto turn on time settings, enabled only when autoTurnOnTimer is enabled // auto turn on time settings, enabled only when autoTurnOnTimer is enabled
SettingsTile.navigation( SettingsTile.navigation(
enabled: sleepTimerSettings.autoTurnOnTimer, enabled: enabled,
title: const Text('Auto Turn On Time'), leading: const Icon(Symbols.timer_play),
title: const Text('From'),
description: const Text( description: const Text(
'Turn on the sleep timer at the specified time', 'Turn on the sleep timer at the specified time',
), ),
@ -57,22 +64,24 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget {
); );
if (selected != null) { if (selected != null) {
ref.read(appSettingsProvider.notifier).update( ref.read(appSettingsProvider.notifier).update(
appSettings.copyWith.playerSettings.sleepTimerSettings( appSettings.copyWith.sleepTimerSettings(
autoTurnOnTime: selected.toDuration(), autoTurnOnTime: selected.toDuration(),
), ),
); );
} }
}, },
value: Text( trailing: Text(
sleepTimerSettings.autoTurnOnTime.toTimeOfDay().format(context), sleepTimerSettings.autoTurnOnTime.toTimeOfDay().format(context),
style: TextStyle(color: selectedValueColor),
), ),
), ),
SettingsTile.navigation( SettingsTile.navigation(
title: const Text('Auto Turn Off Time'), enabled: enabled,
leading: const Icon(Symbols.timer_pause),
title: const Text('Until'),
description: const Text( description: const Text(
'Turn off the sleep timer at the specified time', 'Turn off the sleep timer at the specified time',
), ),
enabled: sleepTimerSettings.autoTurnOnTimer,
onPressed: (context) async { onPressed: (context) async {
// navigate to the time picker // navigate to the time picker
final selected = await showTimePicker( final selected = await showTimePicker(
@ -81,18 +90,37 @@ class AutoSleepTimerSettingsPage extends HookConsumerWidget {
); );
if (selected != null) { if (selected != null) {
ref.read(appSettingsProvider.notifier).update( ref.read(appSettingsProvider.notifier).update(
appSettings.copyWith.playerSettings.sleepTimerSettings( appSettings.copyWith.sleepTimerSettings(
autoTurnOffTime: selected.toDuration(), autoTurnOffTime: selected.toDuration(),
), ),
); );
} }
}, },
value: Text( trailing: Text(
sleepTimerSettings.autoTurnOffTime sleepTimerSettings.autoTurnOffTime
.toTimeOfDay() .toTimeOfDay()
.format(context), .format(context),
style: TextStyle(color: selectedValueColor),
), ),
), ),
// switch tile for always auto turn on timer no matter what
SettingsTile.switchTile(
leading: const Icon(Symbols.all_inclusive),
title: const Text('Always Auto Turn On Timer'),
description: const Text(
'Always turn on the sleep timer, no matter what',
),
onToggle: (value) {
ref.read(appSettingsProvider.notifier).update(
appSettings.copyWith.sleepTimerSettings(
alwaysAutoTurnOnTimer: value,
),
);
},
enabled: sleepTimerSettings.autoTurnOnTimer,
initialValue: sleepTimerSettings.alwaysAutoTurnOnTimer,
),
], ],
), ),
], ],

View file

@ -9,14 +9,27 @@ extension DurationFormat on Duration {
final minutes = inMinutes.remainder(60); final minutes = inMinutes.remainder(60);
final seconds = inSeconds.remainder(60); final seconds = inSeconds.remainder(60);
if (hours > 0) { if (hours > 0) {
return '${hours}h ${minutes}m'; // skip minutes if it's 0
if (minutes == 0) {
return smartSingleFormat;
}
return '${Duration(hours: hours).smartBinaryFormat} ${Duration(minutes: minutes).smartSingleFormat}';
} else if (minutes > 0) { } else if (minutes > 0) {
return '${minutes}m ${seconds}s'; if (seconds == 0) {
return smartSingleFormat;
}
return '${Duration(minutes: minutes).smartSingleFormat} ${Duration(seconds: seconds).smartSingleFormat}';
} else { } else {
return '${seconds}s'; return smartSingleFormat;
} }
} }
/// formats the duration using only 1 unit
/// if the duration is more than 1 hour, it will return `10h`
/// if the duration is less than 1 hour, it will return `30m`
/// if the duration is less than 1 minute, it will return `20s`
///
/// rest of the duration will be ignored
String get smartSingleFormat { String get smartSingleFormat {
if (inHours > 0) { if (inHours > 0) {
return '${inHours}h'; return '${inHours}h';

View file

@ -2,7 +2,10 @@ import 'package:flutter/material.dart';
extension ToTimeOfDay on Duration { extension ToTimeOfDay on Duration {
TimeOfDay toTimeOfDay() { TimeOfDay toTimeOfDay() {
return TimeOfDay(hour: inHours, minute: inMinutes % 60); return TimeOfDay(
hour: inHours % 24,
minute: inMinutes % 60,
);
} }
} }
@ -28,4 +31,16 @@ extension TimeOfDayExtension on TimeOfDay {
bool isBefore(TimeOfDay other) => this < other; bool isBefore(TimeOfDay other) => this < other;
bool isAfter(TimeOfDay other) => this > other; bool isAfter(TimeOfDay other) => this > other;
bool isBetween(TimeOfDay start, TimeOfDay end) {
// needs more logic to handle the case where start is after end
//but on the other day
if (start == end) {
return this == start;
}
if (start < end) {
return this >= start && this <= end;
}
return this >= start || this <= end;
}
} }

View file

@ -28,3 +28,64 @@ void useTimer(VoidCallback callback, Duration delay) {
[delay], [delay],
); );
} }
/// Creates [FixedExtentScrollController] that will be disposed automatically.
///
/// See also:
/// - [FixedExtentScrollController]
FixedExtentScrollController useFixedExtentScrollController({
String? debugLabel,
List<Object?>? keys,
int initialItem = 0,
void Function(ScrollPosition)? onAttach,
void Function(ScrollPosition)? onDetach,
}) {
return use(
_FixedExtentScrollControllerHook(
debugLabel: debugLabel,
keys: keys,
initialItem: initialItem,
onAttach: onAttach,
onDetach: onDetach,
),
);
}
class _FixedExtentScrollControllerHook
extends Hook<FixedExtentScrollController> {
const _FixedExtentScrollControllerHook({
this.debugLabel,
super.keys,
required this.initialItem,
this.onAttach,
this.onDetach,
});
final int initialItem;
final void Function(ScrollPosition)? onAttach;
final void Function(ScrollPosition)? onDetach;
final String? debugLabel;
@override
HookState<FixedExtentScrollController, Hook<FixedExtentScrollController>>
createState() => _FixedExtentScrollControllerHookState();
}
class _FixedExtentScrollControllerHookState extends HookState<
FixedExtentScrollController, _FixedExtentScrollControllerHook> {
late final controller = FixedExtentScrollController(
initialItem: hook.initialItem,
onAttach: hook.onAttach,
onDetach: hook.onDetach,
);
@override
FixedExtentScrollController build(BuildContext context) => controller;
@override
void dispose() => controller.dispose();
@override
String get debugLabel => 'useFixedExtentScrollController';
}

View file

@ -814,6 +814,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.11.1" version: "0.11.1"
material_symbols_icons:
dependency: "direct main"
description:
name: material_symbols_icons
sha256: "66416c4e30bd363508e12669634fc4f3250b83b69e862de67f4f9c480cf42414"
url: "https://pub.dev"
source: hosted
version: "4.2785.1"
media_kit: media_kit:
dependency: transitive dependency: transitive
description: description:

View file

@ -70,6 +70,7 @@ dependencies:
list_wheel_scroll_view_nls: ^0.0.3 list_wheel_scroll_view_nls: ^0.0.3
logging: ^1.2.0 logging: ^1.2.0
lottie: ^3.1.0 lottie: ^3.1.0
material_symbols_icons: ^4.2785.1
media_kit_libs_linux: any media_kit_libs_linux: any
media_kit_libs_windows_audio: any media_kit_libs_windows_audio: any
miniplayer: miniplayer: