PLayback Status property added for loading indicators

This commit is contained in:
Kingkor Roy Tirtho 2022-07-04 09:36:22 +06:00
parent ddc3555015
commit a985c19ad8
7 changed files with 47 additions and 16 deletions

View File

@ -25,8 +25,9 @@ class AlbumCard extends HookConsumerWidget {
return PlaybuttonCard( return PlaybuttonCard(
imageUrl: imageToUrlString(album.images), imageUrl: imageToUrlString(album.images),
margin: EdgeInsets.symmetric(horizontal: marginH.toDouble()), margin: EdgeInsets.symmetric(horizontal: marginH.toDouble()),
isPlaying: isPlaying: playback.playlist?.id == album.id,
playback.playlist?.id != null && playback.playlist?.id == album.id, isLoading: playback.status == PlaybackStatus.loading &&
playback.playlist?.id == album.id,
title: album.name!, title: album.name!,
description: description:
"Album • ${artistsToString<ArtistSimple>(album.artists ?? [])}", "Album • ${artistsToString<ArtistSimple>(album.artists ?? [])}",

View File

@ -123,11 +123,13 @@ class PlayerControls extends HookConsumerWidget {
onPrevious(); onPrevious();
}), }),
IconButton( IconButton(
icon: Icon( icon: playback.status == PlaybackStatus.loading
playback.isPlaying ? const CircularProgressIndicator()
? Icons.pause_rounded : Icon(
: Icons.play_arrow_rounded, playback.isPlaying
), ? Icons.pause_rounded
: Icons.play_arrow_rounded,
),
color: iconColor, color: iconColor,
onPressed: _playOrPause, onPressed: _playOrPause,
), ),

View File

@ -25,6 +25,7 @@ class PlaylistCard extends HookConsumerWidget {
title: playlist.name!, title: playlist.name!,
imageUrl: imageToUrlString(playlist.images), imageUrl: imageToUrlString(playlist.images),
isPlaying: isPlaylistPlaying, isPlaying: isPlaylistPlaying,
isLoading: playback.status == PlaybackStatus.loading && isPlaylistPlaying,
onTap: () { onTap: () {
GoRouter.of(context).push( GoRouter.of(context).push(
"/playlist/${playlist.id}", "/playlist/${playlist.id}",

View File

@ -9,10 +9,12 @@ class PlaybuttonCard extends StatelessWidget {
final EdgeInsetsGeometry? margin; final EdgeInsetsGeometry? margin;
final String imageUrl; final String imageUrl;
final bool isPlaying; final bool isPlaying;
final bool isLoading;
final String title; final String title;
const PlaybuttonCard({ const PlaybuttonCard({
required this.imageUrl, required this.imageUrl,
required this.isPlaying, required this.isPlaying,
required this.isLoading,
required this.title, required this.title,
this.margin, this.margin,
this.description, this.description,
@ -62,11 +64,17 @@ class PlaybuttonCard extends StatelessWidget {
child: Builder(builder: (context) { child: Builder(builder: (context) {
return ElevatedButton( return ElevatedButton(
onPressed: onPlaybuttonPressed, onPressed: onPlaybuttonPressed,
child: Icon( child: isLoading
isPlaying ? const SizedBox(
? Icons.pause_rounded height: 23,
: Icons.play_arrow_rounded, width: 23,
), child: CircularProgressIndicator(),
)
: Icon(
isPlaying
? Icons.pause_rounded
: Icons.play_arrow_rounded,
),
style: ButtonStyle( style: ButtonStyle(
shape: MaterialStateProperty.all( shape: MaterialStateProperty.all(
const CircleBorder(), const CircleBorder(),

View File

@ -1,3 +1,4 @@
import 'package:spotify/spotify.dart';
import 'package:spotube/models/Logger.dart'; import 'package:spotube/models/Logger.dart';
import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/Playback.dart';
@ -35,7 +36,9 @@ Future<void> Function([dynamic]) useTogglePlayPause(Playback playback) {
} else if (playback.track != null && } else if (playback.track != null &&
playback.currentDuration == Duration.zero && playback.currentDuration == Duration.zero &&
await playback.player.getCurrentPosition() == Duration.zero) { await playback.player.getCurrentPosition() == Duration.zero) {
await playback.play(playback.track!); final track = Track.fromJson(playback.track!.toJson());
playback.track = null;
await playback.play(track);
} else { } else {
await playback.togglePlayPause(); await playback.togglePlayPause();
} }

View File

@ -63,12 +63,9 @@ class SpotubeTrack extends Track {
"duration": duration.toString(), "duration": duration.toString(),
"durationMs": durationMs, "durationMs": durationMs,
"explicit": explicit, "explicit": explicit,
// "externalIds": externalIds,
// "externalUrls": externalUrls,
"href": href, "href": href,
"id": id, "id": id,
"isPlayable": isPlayable, "isPlayable": isPlayable,
// "linkedFrom": linkedFrom,
"name": name, "name": name,
"popularity": popularity, "popularity": popularity,
"previewUrl": previewUrl, "previewUrl": previewUrl,

View File

@ -27,6 +27,12 @@ import 'package:youtube_explode_dart/youtube_explode_dart.dart' hide Playlist;
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:spotube/extensions/list-sort-multiple.dart'; import 'package:spotube/extensions/list-sort-multiple.dart';
enum PlaybackStatus {
playing,
loading,
idle,
}
class Playback extends PersistedChangeNotifier { class Playback extends PersistedChangeNotifier {
// player properties // player properties
bool isShuffled; bool isShuffled;
@ -53,6 +59,8 @@ class Playback extends PersistedChangeNotifier {
final List<StreamSubscription> _subscriptions; final List<StreamSubscription> _subscriptions;
final _logger = getLogger(Playback); final _logger = getLogger(Playback);
PlaybackStatus status;
Playback({ Playback({
required this.player, required this.player,
required this.youtube, required this.youtube,
@ -63,6 +71,7 @@ class Playback extends PersistedChangeNotifier {
isPlaying = false, isPlaying = false,
currentDuration = Duration.zero, currentDuration = Duration.zero,
_subscriptions = [], _subscriptions = [],
status = PlaybackStatus.idle,
super() { super() {
if (Platform.isLinux) { if (Platform.isLinux) {
_linuxAudioService = LinuxAudioService(this); _linuxAudioService = LinuxAudioService(this);
@ -82,6 +91,7 @@ class Playback extends PersistedChangeNotifier {
seekForward(); seekForward();
} else { } else {
isPlaying = false; isPlaying = false;
status = PlaybackStatus.idle;
currentDuration = Duration.zero; currentDuration = Duration.zero;
notifyListeners(); notifyListeners();
} }
@ -115,6 +125,8 @@ class Playback extends PersistedChangeNotifier {
if (index < 0 || index > playlist.tracks.length - 1) return; if (index < 0 || index > playlist.tracks.length - 1) return;
this.playlist = playlist; this.playlist = playlist;
final played = this.playlist!.tracks[index]; final played = this.playlist!.tracks[index];
status = PlaybackStatus.loading;
notifyListeners();
await play(played).then((_) { await play(played).then((_) {
int i = this int i = this
.playlist! .playlist!
@ -131,6 +143,10 @@ class Playback extends PersistedChangeNotifier {
try { try {
// the track is already playing so no need to change that // the track is already playing so no need to change that
if (track.id == this.track?.id) return; if (track.id == this.track?.id) return;
if (status != PlaybackStatus.loading) {
status = PlaybackStatus.loading;
notifyListeners();
}
final tag = MediaItem( final tag = MediaItem(
id: track.id!, id: track.id!,
title: track.name!, title: track.name!,
@ -149,6 +165,8 @@ class Playback extends PersistedChangeNotifier {
notifyListeners(); notifyListeners();
updatePersistence(); updatePersistence();
await player.play(UrlSource(track.ytUri)); await player.play(UrlSource(track.ytUri));
status = PlaybackStatus.playing;
notifyListeners();
} catch (e, stack) { } catch (e, stack) {
_logger.e("play", e, stack); _logger.e("play", e, stack);
} }
@ -198,6 +216,7 @@ class Playback extends PersistedChangeNotifier {
isShuffled = false; isShuffled = false;
playlist = null; playlist = null;
track = null; track = null;
status = PlaybackStatus.idle;
currentDuration = Duration.zero; currentDuration = Duration.zero;
notifyListeners(); notifyListeners();
updatePersistence(clearNullEntries: true); updatePersistence(clearNullEntries: true);