feat: show loading indicator on play track

This commit is contained in:
Kingkor Roy Tirtho 2023-09-11 11:05:42 +06:00
parent 1540999f50
commit d12ea48b97
7 changed files with 57 additions and 47 deletions

View File

@ -131,7 +131,7 @@ final localTracksProvider = FutureProvider<List<LocalTrack>>((ref) async {
class UserLocalTracks extends HookConsumerWidget {
const UserLocalTracks({Key? key}) : super(key: key);
void playLocalTracks(
Future<void> playLocalTracks(
WidgetRef ref,
List<LocalTrack> tracks, {
LocalTrack? currentTrack,
@ -203,10 +203,10 @@ class UserLocalTracks extends HookConsumerWidget {
const SizedBox(width: 10),
FilledButton(
onPressed: trackSnapshot.value != null
? () {
? () async {
if (trackSnapshot.value?.isNotEmpty == true) {
if (!isPlaylistPlaying) {
playLocalTracks(
await playLocalTracks(
ref,
trackSnapshot.value!,
);
@ -295,8 +295,8 @@ class UserLocalTracks extends HookConsumerWidget {
index: index,
track: track,
userPlaylist: false,
onTap: () {
playLocalTracks(
onTap: () async {
await playLocalTracks(
ref,
sortedTracks,
currentTrack: track,

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:fl_query/fl_query.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
@ -27,7 +29,7 @@ class TrackCollectionView<T> extends HookConsumerWidget {
final Query<List<TrackSimple>, T> tracksSnapshot;
final String titleImage;
final PlayButtonState playingState;
final void Function([Track? currentTrack]) onPlay;
final Future<void> Function([Track? currentTrack]) onPlay;
final void Function([Track? currentTrack]) onShuffledPlay;
final void Function() onAddToQueue;
final void Function() onShare;

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
@ -21,7 +23,7 @@ class TrackTile extends HookConsumerWidget {
final Track track;
final bool selected;
final ValueChanged<bool?>? onChanged;
final VoidCallback? onTap;
final Future<void> Function()? onTap;
final VoidCallback? onLongPress;
final bool userPlaylist;
final String? playlistId;
@ -62,6 +64,10 @@ class TrackTile extends HookConsumerWidget {
final isPlaying = track.id == playlist.activeTrack?.id;
final isLoading = useState(false);
final isSelected = isPlaying || isLoading.value;
return LayoutBuilder(builder: (context, constrains) {
return Listener(
onPointerDown: (event) {
@ -76,11 +82,18 @@ class TrackTile extends HookConsumerWidget {
);
},
child: HoverBuilder(
permanentState: isPlaying || constrains.smAndDown ? true : null,
permanentState: isSelected || constrains.smAndDown ? true : null,
builder: (context, isHovering) {
return ListTile(
selected: isPlaying,
onTap: onTap,
selected: isSelected,
onTap: () async {
try {
isLoading.value = true;
await onTap?.call();
} finally {
isLoading.value = false;
}
},
onLongPress: onLongPress,
enabled: !isBlackListed,
contentPadding: EdgeInsets.zero,
@ -145,22 +158,23 @@ class TrackTile extends HookConsumerWidget {
.copyWith(size: 26, color: Colors.white),
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: !isHovering
? const SizedBox.shrink()
: isPlaying && playlist.isFetching
? const SizedBox(
width: 26,
height: 26,
child: CircularProgressIndicator(
strokeWidth: 1.5,
color: Colors.white,
),
child: (isPlaying && playlist.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,
)
: isPlaying
? Icon(
SpotubeIcons.pause,
color: theme.colorScheme.primary,
)
: !isHovering
? const SizedBox.shrink()
: const Icon(SpotubeIcons.play),
),
),

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
@ -27,7 +29,7 @@ final trackCollectionSortState =
StateProvider.family<SortBy, String>((ref, _) => SortBy.none);
class TracksTableView extends HookConsumerWidget {
final void Function(Track currentTrack)? onTrackPlayButtonPressed;
final Future<void> Function(Track currentTrack)? onTrackPlayButtonPressed;
final List<Track> tracks;
final bool userPlaylist;
final String? playlistId;
@ -58,8 +60,7 @@ class TracksTableView extends HookConsumerWidget {
final downloader = ref.watch(downloadManagerProvider.notifier);
final apiType =
ref.watch(userPreferencesProvider.select((s) => s.youtubeApiType));
final tableHeadStyle =
const TextStyle(fontWeight: FontWeight.bold, fontSize: 16);
const tableHeadStyle = TextStyle(fontWeight: FontWeight.bold, fontSize: 16);
final selected = useState<List<String>>([]);
final showCheck = useState<bool>(false);
@ -297,7 +298,7 @@ class TracksTableView extends HookConsumerWidget {
selected: selected.value.contains(track.id),
userPlaylist: userPlaylist,
playlistId: playlistId,
onTap: () {
onTap: () async {
if (showCheck.value) {
final alreadyChecked = selected.value.contains(track.id);
if (alreadyChecked) {
@ -314,9 +315,8 @@ class TracksTableView extends HookConsumerWidget {
),
),
);
if (!isBlackListed) {
onTrackPlayButtonPressed?.call(track);
}
if (isBlackListed) return;
await onTrackPlayButtonPressed?.call(track);
}
},
onLongPress: () {

View File

@ -85,10 +85,10 @@ class AlbumPage extends HookConsumerWidget {
album: album,
routePath: "/album/${album.id}",
bottomSpace: mediaQuery.mdAndDown,
onPlay: ([track]) {
onPlay: ([track]) async {
if (tracksSnapshot.hasData) {
if (!isAlbumPlaying) {
playPlaylist(
await playPlaylist(
tracksSnapshot.data!
.map((track) =>
TypeConversionUtils.simpleTrack_X_Track(track, album))
@ -96,7 +96,7 @@ class AlbumPage extends HookConsumerWidget {
ref,
);
} else if (isAlbumPlaying && track != null) {
playPlaylist(
await playPlaylist(
tracksSnapshot.data!
.map((track) =>
TypeConversionUtils.simpleTrack_X_Track(track, album))
@ -105,7 +105,7 @@ class AlbumPage extends HookConsumerWidget {
ref,
);
} else {
playback
await playback
.removeTracks(tracksSnapshot.data!.map((track) => track.id!));
}
}

View File

@ -390,7 +390,7 @@ class ArtistPage extends HookConsumerWidget {
return TrackTile(
index: i,
track: track,
onTap: () {
onTap: () async {
playPlaylist(
topTracks.toList(),
currentTrack: track,

View File

@ -104,22 +104,16 @@ class PlaylistView extends HookConsumerWidget {
tracksSnapshot: tracksSnapshot,
description: playlist.description,
isOwned: ownPlaylist,
onPlay: ([track]) {
onPlay: ([track]) async {
if (tracksSnapshot.hasData) {
if (!isPlaylistPlaying) {
playPlaylist(
tracksSnapshot.data!,
ref,
currentTrack: track,
);
} else if (isPlaylistPlaying && track != null) {
playPlaylist(
if (!isPlaylistPlaying || (isPlaylistPlaying && track != null)) {
await playPlaylist(
tracksSnapshot.data!,
ref,
currentTrack: track,
);
} else {
playlistNotifier
await playlistNotifier
.removeTracks(tracksSnapshot.data!.map((e) => e.id!));
}
}