Refactor chapter seeking logic in AudiobookPlayerSeekChapterButton

This commit is contained in:
Dr-Blank 2024-05-20 07:45:06 -04:00
parent 2f078742d0
commit b2130a53cc
No known key found for this signature in database
GPG key ID: 7452CC63F210A266
6 changed files with 27 additions and 88 deletions

View file

@ -204,6 +204,22 @@ class AudiobookPlayer extends AudioPlayer {
}); });
} }
/// a convenience getter for slow position stream
Stream<Duration> get slowPositionStream {
final superPositionStream = createPositionStream(
steps: 100,
minPeriod: const Duration(milliseconds: 500),
maxPeriod: const Duration(seconds: 1),
);
// now we need to map the position to the book instead of the current track
return superPositionStream.map((position) {
if (_book == null) {
return Duration.zero;
}
return position + _book!.tracks[sequenceState!.currentIndex].startOffset;
});
}
/// get current chapter /// get current chapter
BookChapter? get currentChapter { BookChapter? get currentChapter {
if (_book == null) { if (_book == null) {

View file

@ -14,7 +14,7 @@ BookExpanded? currentlyPlayingBook(CurrentlyPlayingBookRef ref) {
@riverpod @riverpod
BookChapter? currentPlayingChapter(CurrentPlayingChapterRef ref) { BookChapter? currentPlayingChapter(CurrentPlayingChapterRef ref) {
final player = ref.watch(audiobookPlayerProvider); final player = ref.watch(audiobookPlayerProvider);
player.positionStream.listen((_) { player.slowPositionStream.listen((_) {
ref.invalidateSelf(); ref.invalidateSelf();
}); });

View file

@ -24,7 +24,7 @@ final currentlyPlayingBookProvider =
typedef CurrentlyPlayingBookRef = AutoDisposeProviderRef<BookExpanded?>; typedef CurrentlyPlayingBookRef = AutoDisposeProviderRef<BookExpanded?>;
String _$currentPlayingChapterHash() => String _$currentPlayingChapterHash() =>
r'91ca01ee93e0d556c77237ceebb3f9281d2d2b3f'; r'a084da724e3d8bb1b1475e867ab3200d7d61d827';
/// provided the current chapter of the book being played /// provided the current chapter of the book being played
/// ///

View file

@ -56,9 +56,6 @@ class AudiobookPlayer extends HookConsumerWidget {
} }
}); });
const progressBar = AudiobookTotalProgressBar();
const chapterProgressBar = AudiobookChapterProgressBar();
// theme from image // theme from image
final imageTheme = ref.watch( final imageTheme = ref.watch(
themeOfLibraryItemProvider( themeOfLibraryItemProvider(
@ -189,78 +186,6 @@ class AudiobookPlayerPlayPauseButton extends HookConsumerWidget {
} }
} }
/// A progress bar that shows the total progress of the audiobook
///
/// for chapter progress, use [AudiobookChapterProgressBar]
class AudiobookTotalProgressBar extends HookConsumerWidget {
const AudiobookTotalProgressBar({
super.key,
this.barHeight = 5.0,
this.barCapShape = BarCapShape.round,
this.thumbRadius = 10.0,
this.thumbGlowRadius = 30.0,
this.thumbCanPaintOutsideBar = true,
this.timeLabelLocation,
this.timeLabelType,
this.timeLabelTextStyle,
this.timeLabelPadding = 0.0,
});
final double barHeight;
final BarCapShape barCapShape;
final double thumbRadius;
final double thumbGlowRadius;
final bool thumbCanPaintOutsideBar;
final TimeLabelLocation? timeLabelLocation;
final TimeLabelType? timeLabelType;
final TextStyle? timeLabelTextStyle;
final double timeLabelPadding;
@override
Widget build(BuildContext context, WidgetRef ref) {
final player = ref.watch(audiobookPlayerProvider);
final position = useStream(
player.positionStream,
initialData: const Duration(seconds: 0),
);
final buffered = useStream(
player.bufferedPositionStream,
initialData: const Duration(seconds: 0),
);
final currentIndex = useStream(
player.currentIndexStream,
initialData: 0,
);
var durationOfPreviousTracks =
player.book?.tracks.sublist(0, currentIndex.data).fold(
const Duration(seconds: 0),
(previousValue, element) => previousValue + element.duration,
) ??
const Duration(seconds: 0);
final totalProgress = durationOfPreviousTracks +
(position.data ?? const Duration(seconds: 0));
final totalBuffered = durationOfPreviousTracks +
(buffered.data ?? const Duration(seconds: 0));
return ProgressBar(
progress: totalProgress,
total: player.book?.duration ?? const Duration(seconds: 0),
onSeek: player.seek,
buffered: totalBuffered,
bufferedBarColor: Theme.of(context).colorScheme.secondary,
thumbRadius: thumbRadius,
thumbGlowRadius: thumbGlowRadius,
thumbCanPaintOutsideBar: thumbCanPaintOutsideBar,
barHeight: barHeight,
barCapShape: barCapShape,
timeLabelLocation: timeLabelLocation,
timeLabelType: timeLabelType,
timeLabelTextStyle: timeLabelTextStyle,
timeLabelPadding: timeLabelPadding,
);
}
}
class AudiobookChapterProgressBar extends HookConsumerWidget { class AudiobookChapterProgressBar extends HookConsumerWidget {
const AudiobookChapterProgressBar({ const AudiobookChapterProgressBar({
super.key, super.key,
@ -281,13 +206,11 @@ class AudiobookChapterProgressBar extends HookConsumerWidget {
// now find the chapter that corresponds to the current time // now find the chapter that corresponds to the current time
// and calculate the progress of the current chapter // and calculate the progress of the current chapter
final currentChapterProgress = final currentChapterProgress = currentChapter == null
currentChapter == null
? null ? null
: (player.positionInBook - currentChapter.start); : (player.positionInBook - currentChapter.start);
final currentChapterBuffered = final currentChapterBuffered = currentChapter == null
currentChapter == null
? null ? null
: (player.bufferedPositionInBook - currentChapter.start); : (player.bufferedPositionInBook - currentChapter.start);

View file

@ -279,9 +279,9 @@ class AudiobookPlayerSeekButton extends HookConsumerWidget {
), ),
onPressed: () { onPressed: () {
if (isForward) { if (isForward) {
player.seek(player.position + const Duration(seconds: 30)); player.seek(player.positionInBook + const Duration(seconds: 30));
} else { } else {
player.seek(player.position - const Duration(seconds: 30)); player.seek(player.positionInBook - const Duration(seconds: 30));
} }
}, },
); );
@ -318,7 +318,7 @@ class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
player.seek( player.seek(
player.book!.chapters[index + 1].start + player.book!.chapters[index + 1].start +
const Duration( const Duration(
microseconds: 50, milliseconds: 10,
), // add a small offset so the display does not show the previous chapter for a split second ), // add a small offset so the display does not show the previous chapter for a split second
); );
} else { } else {
@ -327,18 +327,18 @@ class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
} else { } else {
// if player position is less than 5 seconds into the chapter, go to the previous chapter // if player position is less than 5 seconds into the chapter, go to the previous chapter
final chapterPosition = final chapterPosition =
player.position - player.currentChapter!.start; player.positionInBook - player.currentChapter!.start;
if (chapterPosition < const Duration(seconds: 5)) { if (chapterPosition < const Duration(seconds: 5)) {
final index = player.book!.chapters.indexOf(player.currentChapter!); final index = player.book!.chapters.indexOf(player.currentChapter!);
if (index > 0) { if (index > 0) {
player.seek( player.seek(
player.book!.chapters[index - 1].start + player.book!.chapters[index - 1].start +
const Duration(microseconds: 50), const Duration(milliseconds: 10),
); );
} }
} else { } else {
player.seek( player.seek(
player.currentChapter!.start + const Duration(microseconds: 50), player.currentChapter!.start + const Duration(milliseconds: 10),
); );
} }
} }

View file

@ -33,7 +33,7 @@ class PlayerWhenMinimized extends HookConsumerWidget {
final player = ref.watch(audiobookPlayerProvider); final player = ref.watch(audiobookPlayerProvider);
final vanishingPercentage = 1 - percentageMiniplayer; final vanishingPercentage = 1 - percentageMiniplayer;
final progress = final progress =
useStream(player.positionStream, initialData: Duration.zero); useStream(player.slowPositionStream, initialData: Duration.zero);
final bookMetaExpanded = ref.watch(currentBookMetadataProvider); final bookMetaExpanded = ref.watch(currentBookMetadataProvider);