更改播放逻辑

This commit is contained in:
rang 2025-12-08 17:54:08 +08:00
parent 290b68336f
commit 420438c0df
29 changed files with 810 additions and 514 deletions

View file

@ -3,7 +3,7 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/constants/sizes.dart';
import 'package:vaani/features/player/providers/currently_playing_provider.dart';
import 'package:vaani/features/player/providers/abs_provider.dart';
import 'package:vaani/features/player/view/widgets/player_player_pause_button.dart';
import 'package:vaani/features/player/view/widgets/player_progress_bar.dart';
import 'package:vaani/features/skip_start_end/view/skip_start_end_button.dart';

View file

@ -5,8 +5,8 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shelfsdk/audiobookshelf_api.dart';
import 'package:vaani/constants/sizes.dart';
import 'package:vaani/features/player/providers/abs_provider.dart';
import 'package:vaani/features/player/providers/audiobook_player.dart';
import 'package:vaani/features/player/providers/currently_playing_provider.dart';
import 'package:vaani/features/player/view/player_expanded.dart'
show PlayerExpandedImage;
import 'package:vaani/features/player/view/player_minimized.dart';
@ -74,9 +74,9 @@ class PlayerExpandedDesktop extends HookConsumerWidget {
// buttonSkipBackwards
const AudiobookPlayerSeekButton(isForward: false),
AudiobookPlayerPlayPauseButton(),
// buttonSkipForwards
// // buttonSkipForwards
const AudiobookPlayerSeekButton(isForward: true),
// next chapter
// // next chapter
const AudiobookPlayerSeekChapterButton(
isForward: true),
],

View file

@ -1,12 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/constants/sizes.dart';
import 'package:vaani/features/player/providers/abs_provider.dart';
import 'package:vaani/features/player/providers/audiobook_player.dart';
import 'package:vaani/features/player/providers/currently_playing_provider.dart';
import 'package:vaani/features/player/view/widgets/player_player_pause_button.dart';
import 'package:vaani/router/router.dart';
import 'package:vaani/shared/extensions/chapter.dart';
@ -21,12 +18,11 @@ class PlayerMinimized extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final currentBook = ref.watch(absStateProvider.select((v) => v.book));
final currentBook = ref.watch(currentBookProvider);
if (currentBook == null) {
return SizedBox.shrink();
}
final currentChapter =
ref.watch(absStateProvider.select((v) => v.currentChapter));
final currentChapter = ref.watch(currentChapterProvider);
return PlayerMinimizedFramework(
children: [
@ -63,14 +59,14 @@ class PlayerMinimized extends HookConsumerWidget {
mainAxisSize: MainAxisSize.min,
children: [
// AutoScrollText(
PlatformText(
Text(
'${currentBook.metadata.title ?? ''} - ${currentChapter?.title ?? ''}',
maxLines: 1, overflow: TextOverflow.ellipsis,
// velocity:
// const Velocity(pixelsPerSecond: Offset(16, 0)),
style: Theme.of(context).textTheme.bodyLarge,
),
PlatformText(
Text(
currentBook.metadata.asBookMetadataExpanded.authorName ?? '',
maxLines: 1,
overflow: TextOverflow.ellipsis,
@ -89,7 +85,7 @@ class PlayerMinimized extends HookConsumerWidget {
// rewind button
Padding(
padding: const EdgeInsets.only(left: 8),
child: PlatformIconButton(
child: IconButton(
icon: const Icon(
Icons.replay_30,
size: AppElementSizes.iconSizeSmall,
@ -116,13 +112,14 @@ class PlayerMinimizedFramework extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// final player = ref.watch(playerProvider);
final currentChapter =
ref.watch(absStateProvider.select((v) => v.currentChapter));
final currentChapter = ref.watch(currentChapterProvider);
final progress =
// useStream(player.positionStreamInChapter, initialData: Duration.zero);
useStream(ref.read(absStateProvider.notifier).positionStreamInChapter,
initialData: Duration.zero);
useStream(
ref.read(absAudioPlayerProvider).positionInChapterStream,
initialData: Duration.zero,
);
return GestureDetector(
onTap: () {
if (GoRouterState.of(context).topRoute?.name != Routes.player.name) {

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/constants/sizes.dart';
import 'package:vaani/features/player/providers/audiobook_player.dart';
import 'package:vaani/features/player/providers/abs_provider.dart';
class AudiobookPlayerSeekButton extends HookConsumerWidget {
const AudiobookPlayerSeekButton({
@ -14,7 +14,7 @@ class AudiobookPlayerSeekButton extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final player = ref.watch(playerProvider);
final player = ref.read(absAudioPlayerProvider);
return IconButton(
icon: Icon(
isForward ? Icons.forward_30 : Icons.replay_30,

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/constants/sizes.dart';
import 'package:vaani/features/player/providers/audiobook_player.dart';
import 'package:vaani/features/player/providers/abs_provider.dart';
class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
const AudiobookPlayerSeekChapterButton({
@ -14,25 +14,26 @@ class AudiobookPlayerSeekChapterButton extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final player = ref.watch(playerProvider);
return IconButton(
icon: Icon(
isForward ? Icons.skip_next : Icons.skip_previous,
size: AppElementSizes.iconSizeSmall,
),
onPressed: () {
if (player.book == null) {
final player = ref.read(absAudioPlayerProvider);
final book = ref.read(currentBookProvider);
if (book == null) {
return;
}
// if chapter does not exist, go to the start or end of the book
if (player.currentChapter == null) {
player.seekInBook(isForward ? player.book!.duration : Duration.zero);
if (ref.read(currentChapterProvider) == null) {
player.seekInBook(isForward ? book.duration : Duration.zero);
return;
}
if (isForward) {
player.skipToNext();
player.next();
} else {
player.skipToPrevious();
player.previous();
}
},
);

View file

@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/features/player/providers/abs_provider.dart';
import 'package:vaani/features/player/providers/audiobook_player.dart';
import 'package:vaani/features/player/providers/currently_playing_provider.dart';
import 'package:vaani/features/player/view/player_expanded.dart'
show pendingPlayerModals;
import 'package:vaani/features/player/view/widgets/playing_indicator_icon.dart';

View file

@ -1,9 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/features/player/core/player_status.dart';
import 'package:vaani/features/player/providers/player_status_provider.dart';
import 'package:vaani/features/player/providers/audiobook_player.dart';
import 'package:vaani/features/player/providers/abs_provider.dart'
hide PlayerState;
import 'package:vaani/shared/audio_player.dart';
class AudiobookPlayerPlayPauseButton extends HookConsumerWidget {
const AudiobookPlayerPlayPauseButton({
@ -14,42 +13,39 @@ class AudiobookPlayerPlayPauseButton extends HookConsumerWidget {
final double iconSize;
@override
Widget build(BuildContext context, WidgetRef ref) {
final playerStatus =
ref.watch(playerStatusProvider.select((v) => v.playStatus));
final playerState = ref.watch(playerStateProvider);
return PlatformIconButton(
icon: _getIcon(playerStatus, context),
onPressed: () => _actionButtonPressed(playerStatus, ref),
return IconButton(
icon: _getIcon(playerState, context),
onPressed: () => _actionButtonPressed(playerState, ref),
);
}
Widget _getIcon(PlayStatus playerStatus, BuildContext context) {
switch (playerStatus) {
case PlayStatus.playing:
return Icon(size: iconSize, PlatformIcons(context).pause);
case PlayStatus.paused:
return Icon(size: iconSize, PlatformIcons(context).playArrow);
case PlayStatus.loading:
return PlatformCircularProgressIndicator();
default:
return Icon(size: iconSize, PlatformIcons(context).playArrow);
Widget _getIcon(PlayerState playerState, BuildContext context) {
if (playerState.playing) {
return Icon(size: iconSize, Icons.pause);
} else {
switch (playerState.processingState) {
case ProcessingState.loading || ProcessingState.buffering:
return CircularProgressIndicator();
default:
return Icon(size: iconSize, Icons.play_arrow);
}
}
}
void _actionButtonPressed(PlayStatus playerStatus, WidgetRef ref) async {
final player = ref.read(playerProvider);
switch (playerStatus) {
case PlayStatus.loading:
break;
case PlayStatus.playing:
await player.pause();
break;
case PlayStatus.completed:
await player.seekInBook(const Duration(seconds: 0));
await player.play();
break;
default:
await player.play();
void _actionButtonPressed(PlayerState playerState, WidgetRef ref) async {
final player = ref.read(absAudioPlayerProvider);
if (playerState.playing) {
await player.pause();
} else {
switch (playerState.processingState) {
case ProcessingState.completed:
await player.seekInBook(const Duration(seconds: 0));
await player.play();
default:
await player.play();
}
}
}
}

View file

@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/constants/sizes.dart';
import 'package:vaani/features/player/providers/abs_provider.dart';
import 'package:vaani/features/player/providers/audiobook_player.dart';
import 'package:vaani/features/player/providers/currently_playing_provider.dart';
class AudiobookChapterProgressBar extends HookConsumerWidget {
const AudiobookChapterProgressBar({
@ -13,14 +13,14 @@ class AudiobookChapterProgressBar extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final player = ref.watch(playerProvider);
final player = ref.watch(absAudioPlayerProvider);
final currentChapter = ref.watch(currentChapterProvider);
final position = useStream(
player.positionStreamInBook,
player.positionInBookStream,
initialData: const Duration(seconds: 0),
);
final buffered = useStream(
player.bufferedPositionStreamInBook,
player.bufferedPositionInBookStream,
initialData: const Duration(seconds: 0),
);
@ -64,9 +64,9 @@ class AudiobookProgressBar extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final player = ref.watch(playerProvider);
final player = ref.read(absAudioPlayerProvider);
final position = useStream(
player.slowPositionStreamInBook,
player.positionInBookStream,
initialData: const Duration(seconds: 0),
);

View file

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:logging/logging.dart';
import 'package:vaani/features/per_book_settings/providers/book_settings_provider.dart';
import 'package:vaani/features/player/providers/audiobook_player.dart';
import 'package:vaani/features/player/providers/abs_provider.dart';
import 'package:vaani/features/player/view/player_expanded.dart';
import 'package:vaani/features/player/view/widgets/speed_selector.dart';
import 'package:vaani/features/settings/app_settings_provider.dart';
@ -16,12 +16,13 @@ class PlayerSpeedAdjustButton extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final player = ref.watch(playerProvider);
final bookId = player.book?.libraryItemId ?? '_';
final player = ref.read(absAudioPlayerProvider);
final book = ref.read(currentBookProvider);
final bookId = book?.libraryItemId ?? '_';
final bookSettings = ref.watch(bookSettingsProvider(bookId));
final appSettings = ref.watch(appSettingsProvider);
return TextButton(
child: Text('${player.player.speed}x'),
child: Text('${player.speed}x'),
onPressed: () async {
pendingPlayerModals++;
_logger.fine('opening speed selector');