refactor: use provider based is track loading implementation

This commit is contained in:
Kingkor Roy Tirtho 2024-06-24 21:01:09 +06:00
parent a83dd64476
commit 75173e5096
9 changed files with 216 additions and 207 deletions

View File

@ -11,7 +11,7 @@ import 'package:spotube/pages/home/home.dart';
import 'package:spotube/pages/library/library.dart'; import 'package:spotube/pages/library/library.dart';
import 'package:spotube/pages/lyrics/lyrics.dart'; import 'package:spotube/pages/lyrics/lyrics.dart';
import 'package:spotube/pages/search/search.dart'; import 'package:spotube/pages/search/search.dart';
import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/querying_track_info.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/platform.dart';
@ -96,8 +96,8 @@ class SeekIntent extends Intent {
class SeekAction extends Action<SeekIntent> { class SeekAction extends Action<SeekIntent> {
@override @override
invoke(intent) async { invoke(intent) async {
final playlist = intent.ref.read(audioPlayerProvider.notifier); final isFetchingActiveTrack = intent.ref.read(queryingTrackInfoProvider);
if (playlist.isFetching()) { if (isFetchingActiveTrack) {
DirectionalFocusAction().invoke( DirectionalFocusAction().invoke(
DirectionalFocusIntent( DirectionalFocusIntent(
intent.forward ? TraversalDirection.right : TraversalDirection.left, intent.forward ? TraversalDirection.right : TraversalDirection.left,

View File

@ -17,7 +17,7 @@ import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/duration.dart'; import 'package:spotube/extensions/duration.dart';
import 'package:spotube/extensions/image.dart'; import 'package:spotube/extensions/image.dart';
import 'package:spotube/models/local_track.dart'; import 'package:spotube/models/local_track.dart';
import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/querying_track_info.dart';
import 'package:spotube/provider/audio_player/state.dart'; import 'package:spotube/provider/audio_player/state.dart';
import 'package:spotube/provider/blacklist_provider.dart'; import 'package:spotube/provider/blacklist_provider.dart';
@ -84,191 +84,190 @@ class TrackTile extends HookConsumerWidget {
}, },
child: HoverBuilder( child: HoverBuilder(
permanentState: isSelected || constrains.smAndDown ? true : null, permanentState: isSelected || constrains.smAndDown ? true : null,
builder: (context, isHovering) { builder: (context, isHovering) => ListTile(
return ListTile( selected: isSelected,
selected: isSelected, onTap: () async {
onTap: () async { try {
try { isLoading.value = true;
isLoading.value = true; await onTap?.call();
await onTap?.call(); } finally {
} finally { if (context.mounted) {
if (context.mounted) { isLoading.value = false;
isLoading.value = false;
}
} }
}, }
onLongPress: onLongPress, },
enabled: !isBlackListed, onLongPress: onLongPress,
contentPadding: EdgeInsets.zero, enabled: !isBlackListed,
tileColor: contentPadding: EdgeInsets.zero,
isBlackListed ? theme.colorScheme.errorContainer : null, tileColor: isBlackListed ? theme.colorScheme.errorContainer : null,
horizontalTitleGap: 12, horizontalTitleGap: 12,
leadingAndTrailingTextStyle: theme.textTheme.bodyMedium, leadingAndTrailingTextStyle: theme.textTheme.bodyMedium,
leading: Row( leading: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
...?leadingActions, ...?leadingActions,
if (index != null && onChanged == null && constrains.mdAndUp) if (index != null && onChanged == null && constrains.mdAndUp)
SizedBox( SizedBox(
width: 50, width: 50,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 6), padding: const EdgeInsets.symmetric(horizontal: 6),
child: Text( child: Text(
'${(index ?? 0) + 1}', '${(index ?? 0) + 1}',
maxLines: 1, maxLines: 1,
style: theme.textTheme.bodySmall, style: theme.textTheme.bodySmall,
textAlign: TextAlign.center, textAlign: TextAlign.center,
),
), ),
)
else if (constrains.smAndDown)
const SizedBox(width: 16),
if (onChanged != null)
Checkbox(
value: selected,
onChanged: onChanged,
), ),
Stack( )
children: [ else if (constrains.smAndDown)
ClipRRect( const SizedBox(width: 16),
borderRadius: BorderRadius.circular(4), if (onChanged != null)
child: AspectRatio( Checkbox(
aspectRatio: 1, value: selected,
child: UniversalImage( onChanged: onChanged,
path: (track.album?.images).asUrlString(
placeholder: ImagePlaceholder.albumArt,
),
fit: BoxFit.cover,
),
),
),
Positioned.fill(
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: isHovering
? Colors.black.withOpacity(0.4)
: Colors.transparent,
),
),
),
Positioned.fill(
child: Center(
child: IconTheme(
data: theme.iconTheme
.copyWith(size: 26, color: Colors.white),
child: Skeleton.ignore(
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: (isPlaying &&
ref
.watch(audioPlayerProvider
.notifier)
.isFetching()) ||
isLoading.value
? const SizedBox(
width: 26,
height: 26,
child: CircularProgressIndicator(
strokeWidth: 1.5,
color: Colors.white,
),
)
: isPlaying
? Icon(
SpotubeIcons.pause,
color: theme.colorScheme.primary,
)
: !isHovering
? const SizedBox.shrink()
: const Icon(SpotubeIcons.play),
),
),
),
),
),
],
), ),
], Stack(
), children: [
title: Row( ClipRRect(
children: [ borderRadius: BorderRadius.circular(4),
Expanded( child: AspectRatio(
flex: 6, aspectRatio: 1,
child: switch (track) { child: UniversalImage(
LocalTrack() => Text( path: (track.album?.images).asUrlString(
track.name!, placeholder: ImagePlaceholder.albumArt,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
_ => LinkText(
track.name!,
"/track/${track.id}",
push: true,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
},
),
if (constrains.mdAndUp) ...[
const SizedBox(width: 8),
Expanded(
flex: 4,
child: switch (track) {
LocalTrack() => Text(
track.album!.name!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
), ),
_ => Align( fit: BoxFit.cover,
alignment: Alignment.centerLeft, ),
child: LinkText( ),
track.album!.name!, ),
"/album/${track.album?.id}", Positioned.fill(
extra: track.album, child: AnimatedContainer(
push: true, duration: const Duration(milliseconds: 300),
overflow: TextOverflow.ellipsis, decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: isHovering
? Colors.black.withOpacity(0.4)
: Colors.transparent,
),
),
),
Positioned.fill(
child: Center(
child: IconTheme(
data: theme.iconTheme
.copyWith(size: 26, color: Colors.white),
child: Skeleton.ignore(
child: Consumer(
builder: (context, ref, _) {
final isFetchingActiveTrack =
ref.watch(queryingTrackInfoProvider);
return AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: (isPlaying && isFetchingActiveTrack) ||
isLoading.value
? const SizedBox(
width: 26,
height: 26,
child: CircularProgressIndicator(
strokeWidth: 1.5,
color: Colors.white,
),
)
: isPlaying
? Icon(
SpotubeIcons.pause,
color: theme.colorScheme.primary,
)
: !isHovering
? const SizedBox.shrink()
: const Icon(SpotubeIcons.play),
);
},
), ),
) ),
}, ),
),
), ),
], ],
], ),
), ],
subtitle: Align( ),
alignment: Alignment.centerLeft, title: Row(
child: track is LocalTrack children: [
? Text( Expanded(
track.artists?.asString() ?? '', flex: 6,
) child: switch (track) {
: ClipRect( LocalTrack() => Text(
child: ConstrainedBox( track.name!,
constraints: const BoxConstraints(maxHeight: 40), maxLines: 1,
child: ArtistLink(artists: track.artists ?? []), overflow: TextOverflow.ellipsis,
),
), ),
), _ => LinkText(
trailing: Row( track.name!,
mainAxisSize: MainAxisSize.min, "/track/${track.id}",
children: [ push: true,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
},
),
if (constrains.mdAndUp) ...[
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Expanded(
Duration(milliseconds: track.durationMs ?? 0) flex: 4,
.toHumanReadableString(padZero: false), child: switch (track) {
maxLines: 1, LocalTrack() => Text(
overflow: TextOverflow.ellipsis, track.album!.name!,
), maxLines: 1,
TrackOptions( overflow: TextOverflow.ellipsis,
track: track, ),
playlistId: playlistId, _ => Align(
userPlaylist: userPlaylist, alignment: Alignment.centerLeft,
showMenuCbRef: showOptionCbRef, child: LinkText(
track.album!.name!,
"/album/${track.album?.id}",
extra: track.album,
push: true,
overflow: TextOverflow.ellipsis,
),
)
},
), ),
], ],
), ],
); ),
}, subtitle: Align(
alignment: Alignment.centerLeft,
child: track is LocalTrack
? Text(
track.artists?.asString() ?? '',
)
: ClipRect(
child: ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 40),
child: ArtistLink(artists: track.artists ?? []),
),
),
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(width: 8),
Text(
Duration(milliseconds: track.durationMs ?? 0)
.toHumanReadableString(padZero: false),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
TrackOptions(
track: track,
playlistId: playlistId,
userPlaylist: userPlaylist,
showMenuCbRef: showOptionCbRef,
),
],
),
),
), ),
); );
}); });

View File

@ -10,6 +10,7 @@ import 'package:spotube/extensions/image.dart';
import 'package:spotube/extensions/track.dart'; import 'package:spotube/extensions/track.dart';
import 'package:spotube/models/connect/connect.dart'; import 'package:spotube/models/connect/connect.dart';
import 'package:spotube/pages/album/album.dart'; import 'package:spotube/pages/album/album.dart';
import 'package:spotube/provider/audio_player/querying_track_info.dart';
import 'package:spotube/provider/connect/connect.dart'; import 'package:spotube/provider/connect/connect.dart';
import 'package:spotube/provider/history/history.dart'; import 'package:spotube/provider/history/history.dart';
import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/audio_player.dart';
@ -35,6 +36,7 @@ class AlbumCard extends HookConsumerWidget {
useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying; useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying;
final playlistNotifier = ref.watch(audioPlayerProvider.notifier); final playlistNotifier = ref.watch(audioPlayerProvider.notifier);
final historyNotifier = ref.read(playbackHistoryProvider.notifier); final historyNotifier = ref.read(playbackHistoryProvider.notifier);
final isFetchingActiveTrack = ref.watch(queryingTrackInfoProvider);
bool isPlaylistPlaying = useMemoized( bool isPlaylistPlaying = useMemoized(
() => playlist.containsCollection(album.id!), () => playlist.containsCollection(album.id!),
@ -59,8 +61,8 @@ class AlbumCard extends HookConsumerWidget {
), ),
margin: const EdgeInsets.symmetric(horizontal: 10), margin: const EdgeInsets.symmetric(horizontal: 10),
isPlaying: isPlaylistPlaying, isPlaying: isPlaylistPlaying,
isLoading: (isPlaylistPlaying && playlistNotifier.isFetching()) || isLoading:
updating.value, (isPlaylistPlaying && isFetchingActiveTrack) || updating.value,
title: album.name!, title: album.name!,
description: description:
"${album.albumType?.formatted}${album.artists?.asString() ?? ""}", "${album.albumType?.formatted}${album.artists?.asString() ?? ""}",

View File

@ -11,7 +11,7 @@ import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/duration.dart'; import 'package:spotube/extensions/duration.dart';
import 'package:spotube/modules/player/use_progress.dart'; import 'package:spotube/modules/player/use_progress.dart';
import 'package:spotube/models/logger.dart'; import 'package:spotube/models/logger.dart';
import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/querying_track_info.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
class PlayerControls extends HookConsumerWidget { class PlayerControls extends HookConsumerWidget {
@ -43,8 +43,7 @@ class PlayerControls extends HookConsumerWidget {
SeekIntent: SeekAction(), SeekIntent: SeekAction(),
}, },
[]); []);
ref.watch(audioPlayerProvider); final isFetchingActiveTrack = ref.watch(queryingTrackInfoProvider);
final playlistNotifier = ref.watch(audioPlayerProvider.notifier);
final playing = final playing =
useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying; useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying;
@ -132,7 +131,7 @@ class PlayerControls extends HookConsumerWidget {
// than total duration. Keeping it resolved // than total duration. Keeping it resolved
value: progress.value.toDouble(), value: progress.value.toDouble(),
secondaryTrackValue: bufferProgress, secondaryTrackValue: bufferProgress,
onChanged: playlistNotifier.isFetching() onChanged: isFetchingActiveTrack
? null ? null
: (v) { : (v) {
progress.value = v; progress.value = v;
@ -183,7 +182,7 @@ class PlayerControls extends HookConsumerWidget {
: context.l10n.shuffle_playlist, : context.l10n.shuffle_playlist,
icon: const Icon(SpotubeIcons.shuffle), icon: const Icon(SpotubeIcons.shuffle),
style: shuffled ? activeButtonStyle : buttonStyle, style: shuffled ? activeButtonStyle : buttonStyle,
onPressed: playlistNotifier.isFetching() onPressed: isFetchingActiveTrack
? null ? null
: () { : () {
if (shuffled) { if (shuffled) {
@ -198,7 +197,7 @@ class PlayerControls extends HookConsumerWidget {
tooltip: context.l10n.previous_track, tooltip: context.l10n.previous_track,
icon: const Icon(SpotubeIcons.skipBack), icon: const Icon(SpotubeIcons.skipBack),
style: buttonStyle, style: buttonStyle,
onPressed: playlistNotifier.isFetching() onPressed: isFetchingActiveTrack
? null ? null
: audioPlayer.skipToPrevious, : audioPlayer.skipToPrevious,
), ),
@ -206,7 +205,7 @@ class PlayerControls extends HookConsumerWidget {
tooltip: playing tooltip: playing
? context.l10n.pause_playback ? context.l10n.pause_playback
: context.l10n.resume_playback, : context.l10n.resume_playback,
icon: playlistNotifier.isFetching() icon: isFetchingActiveTrack
? SizedBox( ? SizedBox(
height: 20, height: 20,
width: 20, width: 20,
@ -219,7 +218,7 @@ class PlayerControls extends HookConsumerWidget {
playing ? SpotubeIcons.pause : SpotubeIcons.play, playing ? SpotubeIcons.pause : SpotubeIcons.play,
), ),
style: resumePauseStyle, style: resumePauseStyle,
onPressed: playlistNotifier.isFetching() onPressed: isFetchingActiveTrack
? null ? null
: Actions.handler<PlayPauseIntent>( : Actions.handler<PlayPauseIntent>(
context, context,
@ -230,9 +229,8 @@ class PlayerControls extends HookConsumerWidget {
tooltip: context.l10n.next_track, tooltip: context.l10n.next_track,
icon: const Icon(SpotubeIcons.skipForward), icon: const Icon(SpotubeIcons.skipForward),
style: buttonStyle, style: buttonStyle,
onPressed: playlistNotifier.isFetching() onPressed:
? null isFetchingActiveTrack ? null : audioPlayer.skipToNext,
: audioPlayer.skipToNext,
), ),
StreamBuilder<PlaylistMode>( StreamBuilder<PlaylistMode>(
stream: audioPlayer.loopModeStream, stream: audioPlayer.loopModeStream,
@ -253,7 +251,7 @@ class PlayerControls extends HookConsumerWidget {
loopMode == PlaylistMode.loop loopMode == PlaylistMode.loop
? activeButtonStyle ? activeButtonStyle
: buttonStyle, : buttonStyle,
onPressed: playlistNotifier.isFetching() onPressed: isFetchingActiveTrack
? null ? null
: () async { : () async {
await audioPlayer.setLoopMode(loopMode); await audioPlayer.setLoopMode(loopMode);

View File

@ -12,6 +12,7 @@ import 'package:spotube/collections/intents.dart';
import 'package:spotube/modules/player/use_progress.dart'; import 'package:spotube/modules/player/use_progress.dart';
import 'package:spotube/modules/player/player.dart'; import 'package:spotube/modules/player/player.dart';
import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/audio_player.dart';
import 'package:spotube/provider/audio_player/querying_track_info.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
class PlayerOverlay extends HookConsumerWidget { class PlayerOverlay extends HookConsumerWidget {
@ -24,7 +25,7 @@ class PlayerOverlay extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final playlistNotifier = ref.watch(audioPlayerProvider.notifier); final isFetchingActiveTrack = ref.watch(queryingTrackInfoProvider);
final playlist = ref.watch(audioPlayerProvider); final playlist = ref.watch(audioPlayerProvider);
final canShow = playlist.activeTrack != null; final canShow = playlist.activeTrack != null;
@ -127,14 +128,14 @@ class PlayerOverlay extends HookConsumerWidget {
SpotubeIcons.skipBack, SpotubeIcons.skipBack,
color: textColor, color: textColor,
), ),
onPressed: playlistNotifier.isFetching() onPressed: isFetchingActiveTrack
? null ? null
: audioPlayer.skipToPrevious, : audioPlayer.skipToPrevious,
), ),
Consumer( Consumer(
builder: (context, ref, _) { builder: (context, ref, _) {
return IconButton( return IconButton(
icon: playlistNotifier.isFetching() icon: isFetchingActiveTrack
? const SizedBox( ? const SizedBox(
height: 20, height: 20,
width: 20, width: 20,
@ -158,7 +159,7 @@ class PlayerOverlay extends HookConsumerWidget {
SpotubeIcons.skipForward, SpotubeIcons.skipForward,
color: textColor, color: textColor,
), ),
onPressed: playlistNotifier.isFetching() onPressed: isFetchingActiveTrack
? null ? null
: audioPlayer.skipToNext, : audioPlayer.skipToNext,
), ),

View File

@ -16,6 +16,7 @@ import 'package:spotube/extensions/duration.dart';
import 'package:spotube/hooks/utils/use_debounce.dart'; import 'package:spotube/hooks/utils/use_debounce.dart';
import 'package:spotube/models/database/database.dart'; import 'package:spotube/models/database/database.dart';
import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/audio_player.dart';
import 'package:spotube/provider/audio_player/querying_track_info.dart';
import 'package:spotube/provider/server/active_sourced_track.dart'; import 'package:spotube/provider/server/active_sourced_track.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
@ -54,7 +55,7 @@ class SiblingTracksSheet extends HookConsumerWidget {
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final theme = Theme.of(context); final theme = Theme.of(context);
final playlist = ref.watch(audioPlayerProvider); final playlist = ref.watch(audioPlayerProvider);
final playlistNotifier = ref.watch(audioPlayerProvider.notifier); final isFetchingActiveTrack = ref.watch(queryingTrackInfoProvider);
final preferences = ref.watch(userPreferencesProvider); final preferences = ref.watch(userPreferencesProvider);
final isSearching = useState(false); final isSearching = useState(false);
@ -130,7 +131,7 @@ class SiblingTracksSheet extends HookConsumerWidget {
]); ]);
final siblings = useMemoized( final siblings = useMemoized(
() => playlistNotifier.isFetching() () => isFetchingActiveTrack
? [ ? [
(activeTrack as SourcedTrack).sourceInfo, (activeTrack as SourcedTrack).sourceInfo,
...activeTrack.siblings, ...activeTrack.siblings,
@ -176,12 +177,12 @@ class SiblingTracksSheet extends HookConsumerWidget {
Text("${sourceInfo.artist}"), Text("${sourceInfo.artist}"),
], ],
), ),
enabled: !playlistNotifier.isFetching(), enabled: !isFetchingActiveTrack,
selected: !playlistNotifier.isFetching() && selected: !isFetchingActiveTrack &&
sourceInfo.id == (activeTrack as SourcedTrack).sourceInfo.id, sourceInfo.id == (activeTrack as SourcedTrack).sourceInfo.id,
selectedTileColor: theme.popupMenuTheme.color, selectedTileColor: theme.popupMenuTheme.color,
onTap: () { onTap: () {
if (!playlistNotifier.isFetching() && if (!isFetchingActiveTrack &&
sourceInfo.id != (activeTrack as SourcedTrack).sourceInfo.id) { sourceInfo.id != (activeTrack as SourcedTrack).sourceInfo.id) {
activeTrackNotifier.swapSibling(sourceInfo); activeTrackNotifier.swapSibling(sourceInfo);
Navigator.of(context).pop(); Navigator.of(context).pop();

View File

@ -7,6 +7,7 @@ import 'package:spotube/components/playbutton_card.dart';
import 'package:spotube/extensions/image.dart'; import 'package:spotube/extensions/image.dart';
import 'package:spotube/models/connect/connect.dart'; import 'package:spotube/models/connect/connect.dart';
import 'package:spotube/pages/playlist/playlist.dart'; import 'package:spotube/pages/playlist/playlist.dart';
import 'package:spotube/provider/audio_player/querying_track_info.dart';
import 'package:spotube/provider/connect/connect.dart'; import 'package:spotube/provider/connect/connect.dart';
import 'package:spotube/provider/history/history.dart'; import 'package:spotube/provider/history/history.dart';
import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/audio_player.dart';
@ -24,6 +25,7 @@ class PlaylistCard extends HookConsumerWidget {
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final playlistQueue = ref.watch(audioPlayerProvider); final playlistQueue = ref.watch(audioPlayerProvider);
final playlistNotifier = ref.watch(audioPlayerProvider.notifier); final playlistNotifier = ref.watch(audioPlayerProvider.notifier);
final isFetchingActiveTrack = ref.watch(queryingTrackInfoProvider);
final historyNotifier = ref.read(playbackHistoryProvider.notifier); final historyNotifier = ref.read(playbackHistoryProvider.notifier);
final playing = final playing =
@ -65,8 +67,7 @@ class PlaylistCard extends HookConsumerWidget {
placeholder: ImagePlaceholder.collection, placeholder: ImagePlaceholder.collection,
), ),
isPlaying: isPlaylistPlaying, isPlaying: isPlaylistPlaying,
isLoading: (isPlaylistPlaying && playlistNotifier.isFetching()) || isLoading: (isPlaylistPlaying && isFetchingActiveTrack) || updating.value,
updating.value,
isOwner: playlist.owner?.id == me.asData?.value.id && isOwner: playlist.owner?.id == me.asData?.value.id &&
me.asData?.value.id != null, me.asData?.value.id != null,
onTap: () { onTap: () {

View File

@ -299,11 +299,6 @@ class AudioPlayerNotifier extends Notifier<AudioPlayerState> {
await audioPlayer.moveTrack(oldIndex, newIndex); await audioPlayer.moveTrack(oldIndex, newIndex);
} }
bool isFetching() {
if (state.activeTrack == null) return false;
return ref.read(sourcedTrackProvider(state.activeTrack!)).isLoading;
}
Future<void> stop() async { Future<void> stop() async {
await audioPlayer.stop(); await audioPlayer.stop();
ref.read(discordProvider.notifier).clear(); ref.read(discordProvider.notifier).clear();

View File

@ -0,0 +1,12 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/provider/audio_player/audio_player.dart';
import 'package:spotube/provider/server/sourced_track.dart';
final queryingTrackInfoProvider = Provider<bool>((ref) {
final activeTrack =
ref.watch(audioPlayerProvider.select((s) => s.activeTrack));
if (activeTrack == null) return false;
return ref.read(sourcedTrackProvider(activeTrack)).isLoading;
});