mirror of
https://github.com/Dr-Blank/Vaani.git
synced 2025-12-06 11:09:28 +00:00
Refactor chapter seeking logic in AudiobookPlayerSeekChapterButton
This commit is contained in:
parent
aefe5299ca
commit
73e8f4bfa6
7 changed files with 217 additions and 96 deletions
|
|
@ -304,10 +304,10 @@ class LibraryItemActions extends HookConsumerWidget {
|
|||
ref
|
||||
.read(appSettingsProvider)
|
||||
.playerSettings
|
||||
.preferredVolume,
|
||||
.preferredDefaultVolume,
|
||||
);
|
||||
// toggle play/pause
|
||||
player.togglePlayPause();
|
||||
await player.play();
|
||||
},
|
||||
icon: const Icon(Icons.play_arrow_rounded),
|
||||
label: const Text('Play/Resume'),
|
||||
|
|
|
|||
|
|
@ -225,6 +225,10 @@ class AudiobookPlayer extends AudioPlayer {
|
|||
if (_book == null) {
|
||||
return null;
|
||||
}
|
||||
// if the list is empty, return null
|
||||
if (_book!.chapters.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return _book!.chapters.firstWhere(
|
||||
(element) {
|
||||
return element.start <= positionInBook && element.end >= positionInBook;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ class AudiobookPlayer extends HookConsumerWidget {
|
|||
// the image width when the player is expanded
|
||||
final maxImgSize = availWidth * 0.9;
|
||||
|
||||
final preferredVolume = appSettings.playerSettings.preferredVolume;
|
||||
final preferredVolume = appSettings.playerSettings.preferredDefaultVolume;
|
||||
return Theme(
|
||||
data: ThemeData(
|
||||
colorScheme: imageTheme.valueOrNull ?? Theme.of(context).colorScheme,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:miniplayer/miniplayer.dart';
|
||||
import 'package:shelfsdk/audiobookshelf_api.dart';
|
||||
import 'package:whispering_pages/constants/sizes.dart';
|
||||
import 'package:whispering_pages/features/player/providers/audiobook_player.dart';
|
||||
import 'package:whispering_pages/features/player/providers/currently_playing_provider.dart';
|
||||
import 'package:whispering_pages/features/player/providers/player_form.dart';
|
||||
import 'package:whispering_pages/features/player/view/audiobook_player.dart';
|
||||
import 'package:whispering_pages/settings/app_settings_provider.dart';
|
||||
import 'package:whispering_pages/shared/extensions/inverse_lerp.dart';
|
||||
|
||||
class PlayerWhenExpanded extends HookConsumerWidget {
|
||||
|
|
@ -127,27 +129,27 @@ class PlayerWhenExpanded extends HookConsumerWidget {
|
|||
),
|
||||
|
||||
// the chapter title
|
||||
currentChapter == null
|
||||
? const SizedBox()
|
||||
: Opacity(
|
||||
opacity: earlyPercentage,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: AppElementSizes.paddingRegular * 4 * earlyPercentage,
|
||||
// horizontal: 16.0,
|
||||
),
|
||||
// child: SizedBox(
|
||||
// same as the image width
|
||||
// width: imageSize,
|
||||
child: Text(
|
||||
Opacity(
|
||||
opacity: earlyPercentage,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: AppElementSizes.paddingRegular * 4 * earlyPercentage,
|
||||
// horizontal: 16.0,
|
||||
),
|
||||
// child: SizedBox(
|
||||
// same as the image width
|
||||
// width: imageSize,
|
||||
child: currentChapter == null
|
||||
? const SizedBox()
|
||||
: Text(
|
||||
currentChapter.title,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
// ),
|
||||
),
|
||||
),
|
||||
// ),
|
||||
),
|
||||
),
|
||||
|
||||
// the book name and author
|
||||
Opacity(
|
||||
|
|
@ -232,10 +234,7 @@ class PlayerWhenExpanded extends HookConsumerWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
// speed control
|
||||
IconButton(
|
||||
icon: const Icon(Icons.speed),
|
||||
onPressed: () {},
|
||||
),
|
||||
const PlayerSpeedAdjustButton(),
|
||||
// sleep timer
|
||||
IconButton(
|
||||
icon: const Icon(Icons.timer),
|
||||
|
|
@ -260,6 +259,65 @@ class PlayerWhenExpanded extends HookConsumerWidget {
|
|||
}
|
||||
}
|
||||
|
||||
class PlayerSpeedAdjustButton extends HookConsumerWidget {
|
||||
const PlayerSpeedAdjustButton({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final player = ref.watch(audiobookPlayerProvider);
|
||||
return TextButton(
|
||||
child: Text('${player.speed}x'),
|
||||
// icon: const Icon(Icons.speed),
|
||||
onPressed: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return SpeedSelector(
|
||||
onSpeedSelected: (speed) {
|
||||
player.setSpeed(speed);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SpeedSelector extends HookConsumerWidget {
|
||||
const SpeedSelector({
|
||||
super.key,
|
||||
required this.onSpeedSelected,
|
||||
});
|
||||
|
||||
final void Function(double speed) onSpeedSelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final appSettings = ref.watch(appSettingsProvider);
|
||||
final speeds = appSettings.playerSettings.speedOptions;
|
||||
final currentSpeed = ref.watch(audiobookPlayerProvider).speed;
|
||||
return SizedBox(
|
||||
child: ListView.builder(
|
||||
itemCount: speeds.length,
|
||||
itemBuilder: (context, index) {
|
||||
final speed = speeds[index];
|
||||
return ListTile(
|
||||
title: Text(speed.toString()),
|
||||
onTap: () {
|
||||
onSpeedSelected(speed);
|
||||
},
|
||||
trailing: currentSpeed == speed ? const Icon(Icons.check) : null,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AudiobookPlayerSeekButton extends HookConsumerWidget {
|
||||
const AudiobookPlayerSeekButton({
|
||||
super.key,
|
||||
|
|
@ -301,6 +359,43 @@ class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
|
|||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final player = ref.watch(audiobookPlayerProvider);
|
||||
|
||||
// add a small offset so the display does not show the previous chapter for a split second
|
||||
const offset = Duration(milliseconds: 10);
|
||||
|
||||
/// time into the current chapter to determine if we should go to the previous chapter or the start of the current chapter
|
||||
const doNotSeekBackIfLessThan = Duration(seconds: 5);
|
||||
|
||||
/// seek forward to the next chapter
|
||||
void seekForward() {
|
||||
final index = player.book!.chapters.indexOf(player.currentChapter!);
|
||||
if (index < player.book!.chapters.length - 1) {
|
||||
player.seek(
|
||||
player.book!.chapters[index + 1].start + offset,
|
||||
);
|
||||
} else {
|
||||
player.seek(player.currentChapter!.end);
|
||||
}
|
||||
}
|
||||
|
||||
/// seek backward to the previous chapter or the start of the current chapter
|
||||
void seekBackward() {
|
||||
final currentPlayingChapterIndex =
|
||||
player.book!.chapters.indexOf(player.currentChapter!);
|
||||
final chapterPosition =
|
||||
player.positionInBook - player.currentChapter!.start;
|
||||
BookChapter chapterToSeekTo;
|
||||
// if player position is less than 5 seconds into the chapter, go to the previous chapter
|
||||
if (chapterPosition < doNotSeekBackIfLessThan &&
|
||||
currentPlayingChapterIndex > 0) {
|
||||
chapterToSeekTo = player.book!.chapters[currentPlayingChapterIndex - 1];
|
||||
} else {
|
||||
chapterToSeekTo = player.currentChapter!;
|
||||
}
|
||||
player.seek(
|
||||
chapterToSeekTo.start + offset,
|
||||
);
|
||||
}
|
||||
|
||||
return IconButton(
|
||||
icon: Icon(
|
||||
isForward ? Icons.skip_next : Icons.skip_previous,
|
||||
|
|
@ -310,37 +405,15 @@ class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
|
|||
if (player.book == null) {
|
||||
return;
|
||||
}
|
||||
// if chapter does not exist, go to the start or end of the book
|
||||
if (player.currentChapter == null) {
|
||||
player.seek(isForward ? player.book!.duration : Duration.zero);
|
||||
return;
|
||||
}
|
||||
if (isForward) {
|
||||
// instead of seeking to the end of the chapter, go to the next chapter start
|
||||
// player.seek(player.currentChapter!.end);
|
||||
final index = player.book!.chapters.indexOf(player.currentChapter!);
|
||||
if (index < player.book!.chapters.length - 1) {
|
||||
player.seek(
|
||||
player.book!.chapters[index + 1].start +
|
||||
const Duration(
|
||||
milliseconds: 10,
|
||||
), // add a small offset so the display does not show the previous chapter for a split second
|
||||
);
|
||||
} else {
|
||||
player.seek(player.currentChapter!.end);
|
||||
}
|
||||
seekForward();
|
||||
} else {
|
||||
// if player position is less than 5 seconds into the chapter, go to the previous chapter
|
||||
final chapterPosition =
|
||||
player.positionInBook - player.currentChapter!.start;
|
||||
if (chapterPosition < const Duration(seconds: 5)) {
|
||||
final index = player.book!.chapters.indexOf(player.currentChapter!);
|
||||
if (index > 0) {
|
||||
player.seek(
|
||||
player.book!.chapters[index - 1].start +
|
||||
const Duration(milliseconds: 10),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
player.seek(
|
||||
player.currentChapter!.start + const Duration(milliseconds: 10),
|
||||
);
|
||||
}
|
||||
seekBackward();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -27,8 +27,9 @@ class PlayerSettings with _$PlayerSettings {
|
|||
MinimizedPlayerSettings miniPlayerSettings,
|
||||
@Default(ExpandedPlayerSettings())
|
||||
ExpandedPlayerSettings expandedPlayerSettings,
|
||||
@Default(1) double preferredVolume,
|
||||
@Default(1) double preferredSpeed,
|
||||
@Default(1) double preferredDefaultVolume,
|
||||
@Default(1) double preferredDefaultSpeed,
|
||||
@Default([0.8, 1, 1.25, 1.5, 1.75, 2]) List<double> speedOptions,
|
||||
@Default(Duration(minutes: 15)) Duration sleepTimer,
|
||||
}) = _PlayerSettings;
|
||||
|
||||
|
|
@ -46,6 +47,7 @@ class ExpandedPlayerSettings with _$ExpandedPlayerSettings {
|
|||
factory ExpandedPlayerSettings.fromJson(Map<String, dynamic> json) =>
|
||||
_$ExpandedPlayerSettingsFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class MinimizedPlayerSettings with _$MinimizedPlayerSettings {
|
||||
const factory MinimizedPlayerSettings({
|
||||
|
|
|
|||
|
|
@ -226,8 +226,9 @@ mixin _$PlayerSettings {
|
|||
throw _privateConstructorUsedError;
|
||||
ExpandedPlayerSettings get expandedPlayerSettings =>
|
||||
throw _privateConstructorUsedError;
|
||||
double get preferredVolume => throw _privateConstructorUsedError;
|
||||
double get preferredSpeed => throw _privateConstructorUsedError;
|
||||
double get preferredDefaultVolume => throw _privateConstructorUsedError;
|
||||
double get preferredDefaultSpeed => throw _privateConstructorUsedError;
|
||||
List<double> get speedOptions => throw _privateConstructorUsedError;
|
||||
Duration get sleepTimer => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
|
@ -245,8 +246,9 @@ abstract class $PlayerSettingsCopyWith<$Res> {
|
|||
$Res call(
|
||||
{MinimizedPlayerSettings miniPlayerSettings,
|
||||
ExpandedPlayerSettings expandedPlayerSettings,
|
||||
double preferredVolume,
|
||||
double preferredSpeed,
|
||||
double preferredDefaultVolume,
|
||||
double preferredDefaultSpeed,
|
||||
List<double> speedOptions,
|
||||
Duration sleepTimer});
|
||||
|
||||
$MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings;
|
||||
|
|
@ -268,8 +270,9 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings>
|
|||
$Res call({
|
||||
Object? miniPlayerSettings = null,
|
||||
Object? expandedPlayerSettings = null,
|
||||
Object? preferredVolume = null,
|
||||
Object? preferredSpeed = null,
|
||||
Object? preferredDefaultVolume = null,
|
||||
Object? preferredDefaultSpeed = null,
|
||||
Object? speedOptions = null,
|
||||
Object? sleepTimer = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
|
|
@ -281,14 +284,18 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings>
|
|||
? _value.expandedPlayerSettings
|
||||
: expandedPlayerSettings // ignore: cast_nullable_to_non_nullable
|
||||
as ExpandedPlayerSettings,
|
||||
preferredVolume: null == preferredVolume
|
||||
? _value.preferredVolume
|
||||
: preferredVolume // ignore: cast_nullable_to_non_nullable
|
||||
preferredDefaultVolume: null == preferredDefaultVolume
|
||||
? _value.preferredDefaultVolume
|
||||
: preferredDefaultVolume // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
preferredSpeed: null == preferredSpeed
|
||||
? _value.preferredSpeed
|
||||
: preferredSpeed // ignore: cast_nullable_to_non_nullable
|
||||
preferredDefaultSpeed: null == preferredDefaultSpeed
|
||||
? _value.preferredDefaultSpeed
|
||||
: preferredDefaultSpeed // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
speedOptions: null == speedOptions
|
||||
? _value.speedOptions
|
||||
: speedOptions // ignore: cast_nullable_to_non_nullable
|
||||
as List<double>,
|
||||
sleepTimer: null == sleepTimer
|
||||
? _value.sleepTimer
|
||||
: sleepTimer // ignore: cast_nullable_to_non_nullable
|
||||
|
|
@ -326,8 +333,9 @@ abstract class _$$PlayerSettingsImplCopyWith<$Res>
|
|||
$Res call(
|
||||
{MinimizedPlayerSettings miniPlayerSettings,
|
||||
ExpandedPlayerSettings expandedPlayerSettings,
|
||||
double preferredVolume,
|
||||
double preferredSpeed,
|
||||
double preferredDefaultVolume,
|
||||
double preferredDefaultSpeed,
|
||||
List<double> speedOptions,
|
||||
Duration sleepTimer});
|
||||
|
||||
@override
|
||||
|
|
@ -349,8 +357,9 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res>
|
|||
$Res call({
|
||||
Object? miniPlayerSettings = null,
|
||||
Object? expandedPlayerSettings = null,
|
||||
Object? preferredVolume = null,
|
||||
Object? preferredSpeed = null,
|
||||
Object? preferredDefaultVolume = null,
|
||||
Object? preferredDefaultSpeed = null,
|
||||
Object? speedOptions = null,
|
||||
Object? sleepTimer = null,
|
||||
}) {
|
||||
return _then(_$PlayerSettingsImpl(
|
||||
|
|
@ -362,14 +371,18 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res>
|
|||
? _value.expandedPlayerSettings
|
||||
: expandedPlayerSettings // ignore: cast_nullable_to_non_nullable
|
||||
as ExpandedPlayerSettings,
|
||||
preferredVolume: null == preferredVolume
|
||||
? _value.preferredVolume
|
||||
: preferredVolume // ignore: cast_nullable_to_non_nullable
|
||||
preferredDefaultVolume: null == preferredDefaultVolume
|
||||
? _value.preferredDefaultVolume
|
||||
: preferredDefaultVolume // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
preferredSpeed: null == preferredSpeed
|
||||
? _value.preferredSpeed
|
||||
: preferredSpeed // ignore: cast_nullable_to_non_nullable
|
||||
preferredDefaultSpeed: null == preferredDefaultSpeed
|
||||
? _value.preferredDefaultSpeed
|
||||
: preferredDefaultSpeed // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
speedOptions: null == speedOptions
|
||||
? _value._speedOptions
|
||||
: speedOptions // ignore: cast_nullable_to_non_nullable
|
||||
as List<double>,
|
||||
sleepTimer: null == sleepTimer
|
||||
? _value.sleepTimer
|
||||
: sleepTimer // ignore: cast_nullable_to_non_nullable
|
||||
|
|
@ -384,9 +397,11 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
|
|||
const _$PlayerSettingsImpl(
|
||||
{this.miniPlayerSettings = const MinimizedPlayerSettings(),
|
||||
this.expandedPlayerSettings = const ExpandedPlayerSettings(),
|
||||
this.preferredVolume = 1,
|
||||
this.preferredSpeed = 1,
|
||||
this.sleepTimer = const Duration(minutes: 15)});
|
||||
this.preferredDefaultVolume = 1,
|
||||
this.preferredDefaultSpeed = 1,
|
||||
final List<double> speedOptions = const [0.8, 1, 1.25, 1.5, 1.75, 2],
|
||||
this.sleepTimer = const Duration(minutes: 15)})
|
||||
: _speedOptions = speedOptions;
|
||||
|
||||
factory _$PlayerSettingsImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$PlayerSettingsImplFromJson(json);
|
||||
|
|
@ -399,17 +414,26 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
|
|||
final ExpandedPlayerSettings expandedPlayerSettings;
|
||||
@override
|
||||
@JsonKey()
|
||||
final double preferredVolume;
|
||||
final double preferredDefaultVolume;
|
||||
@override
|
||||
@JsonKey()
|
||||
final double preferredSpeed;
|
||||
final double preferredDefaultSpeed;
|
||||
final List<double> _speedOptions;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<double> get speedOptions {
|
||||
if (_speedOptions is EqualUnmodifiableListView) return _speedOptions;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_speedOptions);
|
||||
}
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final Duration sleepTimer;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredVolume: $preferredVolume, preferredSpeed: $preferredSpeed, sleepTimer: $sleepTimer)';
|
||||
return 'PlayerSettings(miniPlayerSettings: $miniPlayerSettings, expandedPlayerSettings: $expandedPlayerSettings, preferredDefaultVolume: $preferredDefaultVolume, preferredDefaultSpeed: $preferredDefaultSpeed, speedOptions: $speedOptions, sleepTimer: $sleepTimer)';
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -421,18 +445,26 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
|
|||
other.miniPlayerSettings == miniPlayerSettings) &&
|
||||
(identical(other.expandedPlayerSettings, expandedPlayerSettings) ||
|
||||
other.expandedPlayerSettings == expandedPlayerSettings) &&
|
||||
(identical(other.preferredVolume, preferredVolume) ||
|
||||
other.preferredVolume == preferredVolume) &&
|
||||
(identical(other.preferredSpeed, preferredSpeed) ||
|
||||
other.preferredSpeed == preferredSpeed) &&
|
||||
(identical(other.preferredDefaultVolume, preferredDefaultVolume) ||
|
||||
other.preferredDefaultVolume == preferredDefaultVolume) &&
|
||||
(identical(other.preferredDefaultSpeed, preferredDefaultSpeed) ||
|
||||
other.preferredDefaultSpeed == preferredDefaultSpeed) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._speedOptions, _speedOptions) &&
|
||||
(identical(other.sleepTimer, sleepTimer) ||
|
||||
other.sleepTimer == sleepTimer));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, miniPlayerSettings,
|
||||
expandedPlayerSettings, preferredVolume, preferredSpeed, sleepTimer);
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
miniPlayerSettings,
|
||||
expandedPlayerSettings,
|
||||
preferredDefaultVolume,
|
||||
preferredDefaultSpeed,
|
||||
const DeepCollectionEquality().hash(_speedOptions),
|
||||
sleepTimer);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
|
|
@ -453,8 +485,9 @@ abstract class _PlayerSettings implements PlayerSettings {
|
|||
const factory _PlayerSettings(
|
||||
{final MinimizedPlayerSettings miniPlayerSettings,
|
||||
final ExpandedPlayerSettings expandedPlayerSettings,
|
||||
final double preferredVolume,
|
||||
final double preferredSpeed,
|
||||
final double preferredDefaultVolume,
|
||||
final double preferredDefaultSpeed,
|
||||
final List<double> speedOptions,
|
||||
final Duration sleepTimer}) = _$PlayerSettingsImpl;
|
||||
|
||||
factory _PlayerSettings.fromJson(Map<String, dynamic> json) =
|
||||
|
|
@ -465,9 +498,11 @@ abstract class _PlayerSettings implements PlayerSettings {
|
|||
@override
|
||||
ExpandedPlayerSettings get expandedPlayerSettings;
|
||||
@override
|
||||
double get preferredVolume;
|
||||
double get preferredDefaultVolume;
|
||||
@override
|
||||
double get preferredSpeed;
|
||||
double get preferredDefaultSpeed;
|
||||
@override
|
||||
List<double> get speedOptions;
|
||||
@override
|
||||
Duration get sleepTimer;
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -34,8 +34,14 @@ _$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map<String, dynamic> json) =>
|
|||
? const ExpandedPlayerSettings()
|
||||
: ExpandedPlayerSettings.fromJson(
|
||||
json['expandedPlayerSettings'] as Map<String, dynamic>),
|
||||
preferredVolume: (json['preferredVolume'] as num?)?.toDouble() ?? 1,
|
||||
preferredSpeed: (json['preferredSpeed'] as num?)?.toDouble() ?? 1,
|
||||
preferredDefaultVolume:
|
||||
(json['preferredDefaultVolume'] as num?)?.toDouble() ?? 1,
|
||||
preferredDefaultSpeed:
|
||||
(json['preferredDefaultSpeed'] as num?)?.toDouble() ?? 1,
|
||||
speedOptions: (json['speedOptions'] as List<dynamic>?)
|
||||
?.map((e) => (e as num).toDouble())
|
||||
.toList() ??
|
||||
const [0.8, 1, 1.25, 1.5, 1.75, 2],
|
||||
sleepTimer: json['sleepTimer'] == null
|
||||
? const Duration(minutes: 15)
|
||||
: Duration(microseconds: (json['sleepTimer'] as num).toInt()),
|
||||
|
|
@ -46,8 +52,9 @@ Map<String, dynamic> _$$PlayerSettingsImplToJson(
|
|||
<String, dynamic>{
|
||||
'miniPlayerSettings': instance.miniPlayerSettings,
|
||||
'expandedPlayerSettings': instance.expandedPlayerSettings,
|
||||
'preferredVolume': instance.preferredVolume,
|
||||
'preferredSpeed': instance.preferredSpeed,
|
||||
'preferredDefaultVolume': instance.preferredDefaultVolume,
|
||||
'preferredDefaultSpeed': instance.preferredDefaultSpeed,
|
||||
'speedOptions': instance.speedOptions,
|
||||
'sleepTimer': instance.sleepTimer.inMicroseconds,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue