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
2f078742d0
commit
b2130a53cc
6 changed files with 27 additions and 88 deletions
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue