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
|
ref
|
||||||
.read(appSettingsProvider)
|
.read(appSettingsProvider)
|
||||||
.playerSettings
|
.playerSettings
|
||||||
.preferredVolume,
|
.preferredDefaultVolume,
|
||||||
);
|
);
|
||||||
// toggle play/pause
|
// toggle play/pause
|
||||||
player.togglePlayPause();
|
await player.play();
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.play_arrow_rounded),
|
icon: const Icon(Icons.play_arrow_rounded),
|
||||||
label: const Text('Play/Resume'),
|
label: const Text('Play/Resume'),
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,10 @@ class AudiobookPlayer extends AudioPlayer {
|
||||||
if (_book == null) {
|
if (_book == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
// if the list is empty, return null
|
||||||
|
if (_book!.chapters.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return _book!.chapters.firstWhere(
|
return _book!.chapters.firstWhere(
|
||||||
(element) {
|
(element) {
|
||||||
return element.start <= positionInBook && element.end >= positionInBook;
|
return element.start <= positionInBook && element.end >= positionInBook;
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class AudiobookPlayer extends HookConsumerWidget {
|
||||||
// the image width when the player is expanded
|
// the image width when the player is expanded
|
||||||
final maxImgSize = availWidth * 0.9;
|
final maxImgSize = availWidth * 0.9;
|
||||||
|
|
||||||
final preferredVolume = appSettings.playerSettings.preferredVolume;
|
final preferredVolume = appSettings.playerSettings.preferredDefaultVolume;
|
||||||
return Theme(
|
return Theme(
|
||||||
data: ThemeData(
|
data: ThemeData(
|
||||||
colorScheme: imageTheme.valueOrNull ?? Theme.of(context).colorScheme,
|
colorScheme: imageTheme.valueOrNull ?? Theme.of(context).colorScheme,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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:shelfsdk/audiobookshelf_api.dart';
|
||||||
import 'package:whispering_pages/constants/sizes.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/audiobook_player.dart';
|
||||||
import 'package:whispering_pages/features/player/providers/currently_playing_provider.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/providers/player_form.dart';
|
||||||
import 'package:whispering_pages/features/player/view/audiobook_player.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';
|
import 'package:whispering_pages/shared/extensions/inverse_lerp.dart';
|
||||||
|
|
||||||
class PlayerWhenExpanded extends HookConsumerWidget {
|
class PlayerWhenExpanded extends HookConsumerWidget {
|
||||||
|
|
@ -127,27 +129,27 @@ class PlayerWhenExpanded extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
|
|
||||||
// the chapter title
|
// the chapter title
|
||||||
currentChapter == null
|
Opacity(
|
||||||
? const SizedBox()
|
opacity: earlyPercentage,
|
||||||
: Opacity(
|
child: Padding(
|
||||||
opacity: earlyPercentage,
|
padding: EdgeInsets.only(
|
||||||
child: Padding(
|
top: AppElementSizes.paddingRegular * 4 * earlyPercentage,
|
||||||
padding: EdgeInsets.only(
|
// horizontal: 16.0,
|
||||||
top: AppElementSizes.paddingRegular * 4 * earlyPercentage,
|
),
|
||||||
// horizontal: 16.0,
|
// child: SizedBox(
|
||||||
),
|
// same as the image width
|
||||||
// child: SizedBox(
|
// width: imageSize,
|
||||||
// same as the image width
|
child: currentChapter == null
|
||||||
// width: imageSize,
|
? const SizedBox()
|
||||||
child: Text(
|
: Text(
|
||||||
currentChapter.title,
|
currentChapter.title,
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
// ),
|
// ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// the book name and author
|
// the book name and author
|
||||||
Opacity(
|
Opacity(
|
||||||
|
|
@ -232,10 +234,7 @@ class PlayerWhenExpanded extends HookConsumerWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
// speed control
|
// speed control
|
||||||
IconButton(
|
const PlayerSpeedAdjustButton(),
|
||||||
icon: const Icon(Icons.speed),
|
|
||||||
onPressed: () {},
|
|
||||||
),
|
|
||||||
// sleep timer
|
// sleep timer
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.timer),
|
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 {
|
class AudiobookPlayerSeekButton extends HookConsumerWidget {
|
||||||
const AudiobookPlayerSeekButton({
|
const AudiobookPlayerSeekButton({
|
||||||
super.key,
|
super.key,
|
||||||
|
|
@ -301,6 +359,43 @@ class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final player = ref.watch(audiobookPlayerProvider);
|
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(
|
return IconButton(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
isForward ? Icons.skip_next : Icons.skip_previous,
|
isForward ? Icons.skip_next : Icons.skip_previous,
|
||||||
|
|
@ -310,37 +405,15 @@ class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
|
||||||
if (player.book == null) {
|
if (player.book == null) {
|
||||||
return;
|
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) {
|
if (isForward) {
|
||||||
// instead of seeking to the end of the chapter, go to the next chapter start
|
seekForward();
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// if player position is less than 5 seconds into the chapter, go to the previous chapter
|
seekBackward();
|
||||||
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),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,9 @@ class PlayerSettings with _$PlayerSettings {
|
||||||
MinimizedPlayerSettings miniPlayerSettings,
|
MinimizedPlayerSettings miniPlayerSettings,
|
||||||
@Default(ExpandedPlayerSettings())
|
@Default(ExpandedPlayerSettings())
|
||||||
ExpandedPlayerSettings expandedPlayerSettings,
|
ExpandedPlayerSettings expandedPlayerSettings,
|
||||||
@Default(1) double preferredVolume,
|
@Default(1) double preferredDefaultVolume,
|
||||||
@Default(1) double preferredSpeed,
|
@Default(1) double preferredDefaultSpeed,
|
||||||
|
@Default([0.8, 1, 1.25, 1.5, 1.75, 2]) List<double> speedOptions,
|
||||||
@Default(Duration(minutes: 15)) Duration sleepTimer,
|
@Default(Duration(minutes: 15)) Duration sleepTimer,
|
||||||
}) = _PlayerSettings;
|
}) = _PlayerSettings;
|
||||||
|
|
||||||
|
|
@ -46,6 +47,7 @@ class ExpandedPlayerSettings with _$ExpandedPlayerSettings {
|
||||||
factory ExpandedPlayerSettings.fromJson(Map<String, dynamic> json) =>
|
factory ExpandedPlayerSettings.fromJson(Map<String, dynamic> json) =>
|
||||||
_$ExpandedPlayerSettingsFromJson(json);
|
_$ExpandedPlayerSettingsFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class MinimizedPlayerSettings with _$MinimizedPlayerSettings {
|
class MinimizedPlayerSettings with _$MinimizedPlayerSettings {
|
||||||
const factory MinimizedPlayerSettings({
|
const factory MinimizedPlayerSettings({
|
||||||
|
|
|
||||||
|
|
@ -226,8 +226,9 @@ mixin _$PlayerSettings {
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
ExpandedPlayerSettings get expandedPlayerSettings =>
|
ExpandedPlayerSettings get expandedPlayerSettings =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
double get preferredVolume => throw _privateConstructorUsedError;
|
double get preferredDefaultVolume => throw _privateConstructorUsedError;
|
||||||
double get preferredSpeed => throw _privateConstructorUsedError;
|
double get preferredDefaultSpeed => throw _privateConstructorUsedError;
|
||||||
|
List<double> get speedOptions => throw _privateConstructorUsedError;
|
||||||
Duration get sleepTimer => throw _privateConstructorUsedError;
|
Duration get sleepTimer => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
@ -245,8 +246,9 @@ abstract class $PlayerSettingsCopyWith<$Res> {
|
||||||
$Res call(
|
$Res call(
|
||||||
{MinimizedPlayerSettings miniPlayerSettings,
|
{MinimizedPlayerSettings miniPlayerSettings,
|
||||||
ExpandedPlayerSettings expandedPlayerSettings,
|
ExpandedPlayerSettings expandedPlayerSettings,
|
||||||
double preferredVolume,
|
double preferredDefaultVolume,
|
||||||
double preferredSpeed,
|
double preferredDefaultSpeed,
|
||||||
|
List<double> speedOptions,
|
||||||
Duration sleepTimer});
|
Duration sleepTimer});
|
||||||
|
|
||||||
$MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings;
|
$MinimizedPlayerSettingsCopyWith<$Res> get miniPlayerSettings;
|
||||||
|
|
@ -268,8 +270,9 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings>
|
||||||
$Res call({
|
$Res call({
|
||||||
Object? miniPlayerSettings = null,
|
Object? miniPlayerSettings = null,
|
||||||
Object? expandedPlayerSettings = null,
|
Object? expandedPlayerSettings = null,
|
||||||
Object? preferredVolume = null,
|
Object? preferredDefaultVolume = null,
|
||||||
Object? preferredSpeed = null,
|
Object? preferredDefaultSpeed = null,
|
||||||
|
Object? speedOptions = null,
|
||||||
Object? sleepTimer = null,
|
Object? sleepTimer = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_value.copyWith(
|
return _then(_value.copyWith(
|
||||||
|
|
@ -281,14 +284,18 @@ class _$PlayerSettingsCopyWithImpl<$Res, $Val extends PlayerSettings>
|
||||||
? _value.expandedPlayerSettings
|
? _value.expandedPlayerSettings
|
||||||
: expandedPlayerSettings // ignore: cast_nullable_to_non_nullable
|
: expandedPlayerSettings // ignore: cast_nullable_to_non_nullable
|
||||||
as ExpandedPlayerSettings,
|
as ExpandedPlayerSettings,
|
||||||
preferredVolume: null == preferredVolume
|
preferredDefaultVolume: null == preferredDefaultVolume
|
||||||
? _value.preferredVolume
|
? _value.preferredDefaultVolume
|
||||||
: preferredVolume // ignore: cast_nullable_to_non_nullable
|
: preferredDefaultVolume // ignore: cast_nullable_to_non_nullable
|
||||||
as double,
|
as double,
|
||||||
preferredSpeed: null == preferredSpeed
|
preferredDefaultSpeed: null == preferredDefaultSpeed
|
||||||
? _value.preferredSpeed
|
? _value.preferredDefaultSpeed
|
||||||
: preferredSpeed // ignore: cast_nullable_to_non_nullable
|
: preferredDefaultSpeed // ignore: cast_nullable_to_non_nullable
|
||||||
as double,
|
as double,
|
||||||
|
speedOptions: null == speedOptions
|
||||||
|
? _value.speedOptions
|
||||||
|
: speedOptions // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<double>,
|
||||||
sleepTimer: null == sleepTimer
|
sleepTimer: null == sleepTimer
|
||||||
? _value.sleepTimer
|
? _value.sleepTimer
|
||||||
: sleepTimer // ignore: cast_nullable_to_non_nullable
|
: sleepTimer // ignore: cast_nullable_to_non_nullable
|
||||||
|
|
@ -326,8 +333,9 @@ abstract class _$$PlayerSettingsImplCopyWith<$Res>
|
||||||
$Res call(
|
$Res call(
|
||||||
{MinimizedPlayerSettings miniPlayerSettings,
|
{MinimizedPlayerSettings miniPlayerSettings,
|
||||||
ExpandedPlayerSettings expandedPlayerSettings,
|
ExpandedPlayerSettings expandedPlayerSettings,
|
||||||
double preferredVolume,
|
double preferredDefaultVolume,
|
||||||
double preferredSpeed,
|
double preferredDefaultSpeed,
|
||||||
|
List<double> speedOptions,
|
||||||
Duration sleepTimer});
|
Duration sleepTimer});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -349,8 +357,9 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res>
|
||||||
$Res call({
|
$Res call({
|
||||||
Object? miniPlayerSettings = null,
|
Object? miniPlayerSettings = null,
|
||||||
Object? expandedPlayerSettings = null,
|
Object? expandedPlayerSettings = null,
|
||||||
Object? preferredVolume = null,
|
Object? preferredDefaultVolume = null,
|
||||||
Object? preferredSpeed = null,
|
Object? preferredDefaultSpeed = null,
|
||||||
|
Object? speedOptions = null,
|
||||||
Object? sleepTimer = null,
|
Object? sleepTimer = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_$PlayerSettingsImpl(
|
return _then(_$PlayerSettingsImpl(
|
||||||
|
|
@ -362,14 +371,18 @@ class __$$PlayerSettingsImplCopyWithImpl<$Res>
|
||||||
? _value.expandedPlayerSettings
|
? _value.expandedPlayerSettings
|
||||||
: expandedPlayerSettings // ignore: cast_nullable_to_non_nullable
|
: expandedPlayerSettings // ignore: cast_nullable_to_non_nullable
|
||||||
as ExpandedPlayerSettings,
|
as ExpandedPlayerSettings,
|
||||||
preferredVolume: null == preferredVolume
|
preferredDefaultVolume: null == preferredDefaultVolume
|
||||||
? _value.preferredVolume
|
? _value.preferredDefaultVolume
|
||||||
: preferredVolume // ignore: cast_nullable_to_non_nullable
|
: preferredDefaultVolume // ignore: cast_nullable_to_non_nullable
|
||||||
as double,
|
as double,
|
||||||
preferredSpeed: null == preferredSpeed
|
preferredDefaultSpeed: null == preferredDefaultSpeed
|
||||||
? _value.preferredSpeed
|
? _value.preferredDefaultSpeed
|
||||||
: preferredSpeed // ignore: cast_nullable_to_non_nullable
|
: preferredDefaultSpeed // ignore: cast_nullable_to_non_nullable
|
||||||
as double,
|
as double,
|
||||||
|
speedOptions: null == speedOptions
|
||||||
|
? _value._speedOptions
|
||||||
|
: speedOptions // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<double>,
|
||||||
sleepTimer: null == sleepTimer
|
sleepTimer: null == sleepTimer
|
||||||
? _value.sleepTimer
|
? _value.sleepTimer
|
||||||
: sleepTimer // ignore: cast_nullable_to_non_nullable
|
: sleepTimer // ignore: cast_nullable_to_non_nullable
|
||||||
|
|
@ -384,9 +397,11 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
|
||||||
const _$PlayerSettingsImpl(
|
const _$PlayerSettingsImpl(
|
||||||
{this.miniPlayerSettings = const MinimizedPlayerSettings(),
|
{this.miniPlayerSettings = const MinimizedPlayerSettings(),
|
||||||
this.expandedPlayerSettings = const ExpandedPlayerSettings(),
|
this.expandedPlayerSettings = const ExpandedPlayerSettings(),
|
||||||
this.preferredVolume = 1,
|
this.preferredDefaultVolume = 1,
|
||||||
this.preferredSpeed = 1,
|
this.preferredDefaultSpeed = 1,
|
||||||
this.sleepTimer = const Duration(minutes: 15)});
|
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) =>
|
factory _$PlayerSettingsImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
_$$PlayerSettingsImplFromJson(json);
|
_$$PlayerSettingsImplFromJson(json);
|
||||||
|
|
@ -399,17 +414,26 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
|
||||||
final ExpandedPlayerSettings expandedPlayerSettings;
|
final ExpandedPlayerSettings expandedPlayerSettings;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final double preferredVolume;
|
final double preferredDefaultVolume;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@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
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final Duration sleepTimer;
|
final Duration sleepTimer;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
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
|
@override
|
||||||
|
|
@ -421,18 +445,26 @@ class _$PlayerSettingsImpl implements _PlayerSettings {
|
||||||
other.miniPlayerSettings == miniPlayerSettings) &&
|
other.miniPlayerSettings == miniPlayerSettings) &&
|
||||||
(identical(other.expandedPlayerSettings, expandedPlayerSettings) ||
|
(identical(other.expandedPlayerSettings, expandedPlayerSettings) ||
|
||||||
other.expandedPlayerSettings == expandedPlayerSettings) &&
|
other.expandedPlayerSettings == expandedPlayerSettings) &&
|
||||||
(identical(other.preferredVolume, preferredVolume) ||
|
(identical(other.preferredDefaultVolume, preferredDefaultVolume) ||
|
||||||
other.preferredVolume == preferredVolume) &&
|
other.preferredDefaultVolume == preferredDefaultVolume) &&
|
||||||
(identical(other.preferredSpeed, preferredSpeed) ||
|
(identical(other.preferredDefaultSpeed, preferredDefaultSpeed) ||
|
||||||
other.preferredSpeed == preferredSpeed) &&
|
other.preferredDefaultSpeed == preferredDefaultSpeed) &&
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other._speedOptions, _speedOptions) &&
|
||||||
(identical(other.sleepTimer, sleepTimer) ||
|
(identical(other.sleepTimer, sleepTimer) ||
|
||||||
other.sleepTimer == sleepTimer));
|
other.sleepTimer == sleepTimer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType, miniPlayerSettings,
|
int get hashCode => Object.hash(
|
||||||
expandedPlayerSettings, preferredVolume, preferredSpeed, sleepTimer);
|
runtimeType,
|
||||||
|
miniPlayerSettings,
|
||||||
|
expandedPlayerSettings,
|
||||||
|
preferredDefaultVolume,
|
||||||
|
preferredDefaultSpeed,
|
||||||
|
const DeepCollectionEquality().hash(_speedOptions),
|
||||||
|
sleepTimer);
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
|
|
@ -453,8 +485,9 @@ abstract class _PlayerSettings implements PlayerSettings {
|
||||||
const factory _PlayerSettings(
|
const factory _PlayerSettings(
|
||||||
{final MinimizedPlayerSettings miniPlayerSettings,
|
{final MinimizedPlayerSettings miniPlayerSettings,
|
||||||
final ExpandedPlayerSettings expandedPlayerSettings,
|
final ExpandedPlayerSettings expandedPlayerSettings,
|
||||||
final double preferredVolume,
|
final double preferredDefaultVolume,
|
||||||
final double preferredSpeed,
|
final double preferredDefaultSpeed,
|
||||||
|
final List<double> speedOptions,
|
||||||
final Duration sleepTimer}) = _$PlayerSettingsImpl;
|
final Duration sleepTimer}) = _$PlayerSettingsImpl;
|
||||||
|
|
||||||
factory _PlayerSettings.fromJson(Map<String, dynamic> json) =
|
factory _PlayerSettings.fromJson(Map<String, dynamic> json) =
|
||||||
|
|
@ -465,9 +498,11 @@ abstract class _PlayerSettings implements PlayerSettings {
|
||||||
@override
|
@override
|
||||||
ExpandedPlayerSettings get expandedPlayerSettings;
|
ExpandedPlayerSettings get expandedPlayerSettings;
|
||||||
@override
|
@override
|
||||||
double get preferredVolume;
|
double get preferredDefaultVolume;
|
||||||
@override
|
@override
|
||||||
double get preferredSpeed;
|
double get preferredDefaultSpeed;
|
||||||
|
@override
|
||||||
|
List<double> get speedOptions;
|
||||||
@override
|
@override
|
||||||
Duration get sleepTimer;
|
Duration get sleepTimer;
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,14 @@ _$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map<String, dynamic> json) =>
|
||||||
? const ExpandedPlayerSettings()
|
? const ExpandedPlayerSettings()
|
||||||
: ExpandedPlayerSettings.fromJson(
|
: ExpandedPlayerSettings.fromJson(
|
||||||
json['expandedPlayerSettings'] as Map<String, dynamic>),
|
json['expandedPlayerSettings'] as Map<String, dynamic>),
|
||||||
preferredVolume: (json['preferredVolume'] as num?)?.toDouble() ?? 1,
|
preferredDefaultVolume:
|
||||||
preferredSpeed: (json['preferredSpeed'] as num?)?.toDouble() ?? 1,
|
(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
|
sleepTimer: json['sleepTimer'] == null
|
||||||
? const Duration(minutes: 15)
|
? const Duration(minutes: 15)
|
||||||
: Duration(microseconds: (json['sleepTimer'] as num).toInt()),
|
: Duration(microseconds: (json['sleepTimer'] as num).toInt()),
|
||||||
|
|
@ -46,8 +52,9 @@ Map<String, dynamic> _$$PlayerSettingsImplToJson(
|
||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'miniPlayerSettings': instance.miniPlayerSettings,
|
'miniPlayerSettings': instance.miniPlayerSettings,
|
||||||
'expandedPlayerSettings': instance.expandedPlayerSettings,
|
'expandedPlayerSettings': instance.expandedPlayerSettings,
|
||||||
'preferredVolume': instance.preferredVolume,
|
'preferredDefaultVolume': instance.preferredDefaultVolume,
|
||||||
'preferredSpeed': instance.preferredSpeed,
|
'preferredDefaultSpeed': instance.preferredDefaultSpeed,
|
||||||
|
'speedOptions': instance.speedOptions,
|
||||||
'sleepTimer': instance.sleepTimer.inMicroseconds,
|
'sleepTimer': instance.sleepTimer.inMicroseconds,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue