From a985c19ad8d6b21af08bec63a2a343b497b81de9 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Mon, 4 Jul 2022 09:36:22 +0600 Subject: [PATCH] PLayback Status property added for loading indicators --- lib/components/Album/AlbumCard.dart | 5 +++-- lib/components/Player/PlayerControls.dart | 12 +++++++----- lib/components/Playlist/PlaylistCard.dart | 1 + lib/components/Shared/PlaybuttonCard.dart | 18 +++++++++++++----- lib/hooks/playback.dart | 5 ++++- lib/models/SpotubeTrack.dart | 3 --- lib/provider/Playback.dart | 19 +++++++++++++++++++ 7 files changed, 47 insertions(+), 16 deletions(-) diff --git a/lib/components/Album/AlbumCard.dart b/lib/components/Album/AlbumCard.dart index 465d79e2..7785d84f 100644 --- a/lib/components/Album/AlbumCard.dart +++ b/lib/components/Album/AlbumCard.dart @@ -25,8 +25,9 @@ class AlbumCard extends HookConsumerWidget { return PlaybuttonCard( imageUrl: imageToUrlString(album.images), margin: EdgeInsets.symmetric(horizontal: marginH.toDouble()), - isPlaying: - playback.playlist?.id != null && playback.playlist?.id == album.id, + isPlaying: playback.playlist?.id == album.id, + isLoading: playback.status == PlaybackStatus.loading && + playback.playlist?.id == album.id, title: album.name!, description: "Album • ${artistsToString(album.artists ?? [])}", diff --git a/lib/components/Player/PlayerControls.dart b/lib/components/Player/PlayerControls.dart index e61f06b1..33f41b1f 100644 --- a/lib/components/Player/PlayerControls.dart +++ b/lib/components/Player/PlayerControls.dart @@ -123,11 +123,13 @@ class PlayerControls extends HookConsumerWidget { onPrevious(); }), IconButton( - icon: Icon( - playback.isPlaying - ? Icons.pause_rounded - : Icons.play_arrow_rounded, - ), + icon: playback.status == PlaybackStatus.loading + ? const CircularProgressIndicator() + : Icon( + playback.isPlaying + ? Icons.pause_rounded + : Icons.play_arrow_rounded, + ), color: iconColor, onPressed: _playOrPause, ), diff --git a/lib/components/Playlist/PlaylistCard.dart b/lib/components/Playlist/PlaylistCard.dart index 135af4f9..3c5fcbbb 100644 --- a/lib/components/Playlist/PlaylistCard.dart +++ b/lib/components/Playlist/PlaylistCard.dart @@ -25,6 +25,7 @@ class PlaylistCard extends HookConsumerWidget { title: playlist.name!, imageUrl: imageToUrlString(playlist.images), isPlaying: isPlaylistPlaying, + isLoading: playback.status == PlaybackStatus.loading && isPlaylistPlaying, onTap: () { GoRouter.of(context).push( "/playlist/${playlist.id}", diff --git a/lib/components/Shared/PlaybuttonCard.dart b/lib/components/Shared/PlaybuttonCard.dart index 06a4e26f..ebb68a00 100644 --- a/lib/components/Shared/PlaybuttonCard.dart +++ b/lib/components/Shared/PlaybuttonCard.dart @@ -9,10 +9,12 @@ class PlaybuttonCard extends StatelessWidget { final EdgeInsetsGeometry? margin; final String imageUrl; final bool isPlaying; + final bool isLoading; final String title; const PlaybuttonCard({ required this.imageUrl, required this.isPlaying, + required this.isLoading, required this.title, this.margin, this.description, @@ -62,11 +64,17 @@ class PlaybuttonCard extends StatelessWidget { child: Builder(builder: (context) { return ElevatedButton( onPressed: onPlaybuttonPressed, - child: Icon( - isPlaying - ? Icons.pause_rounded - : Icons.play_arrow_rounded, - ), + child: isLoading + ? const SizedBox( + height: 23, + width: 23, + child: CircularProgressIndicator(), + ) + : Icon( + isPlaying + ? Icons.pause_rounded + : Icons.play_arrow_rounded, + ), style: ButtonStyle( shape: MaterialStateProperty.all( const CircleBorder(), diff --git a/lib/hooks/playback.dart b/lib/hooks/playback.dart index f62fee26..34ae47dd 100644 --- a/lib/hooks/playback.dart +++ b/lib/hooks/playback.dart @@ -1,3 +1,4 @@ +import 'package:spotify/spotify.dart'; import 'package:spotube/models/Logger.dart'; import 'package:spotube/provider/Playback.dart'; @@ -35,7 +36,9 @@ Future Function([dynamic]) useTogglePlayPause(Playback playback) { } else if (playback.track != null && playback.currentDuration == 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 { await playback.togglePlayPause(); } diff --git a/lib/models/SpotubeTrack.dart b/lib/models/SpotubeTrack.dart index 5b2657d4..bad8a51b 100644 --- a/lib/models/SpotubeTrack.dart +++ b/lib/models/SpotubeTrack.dart @@ -63,12 +63,9 @@ class SpotubeTrack extends Track { "duration": duration.toString(), "durationMs": durationMs, "explicit": explicit, - // "externalIds": externalIds, - // "externalUrls": externalUrls, "href": href, "id": id, "isPlayable": isPlayable, - // "linkedFrom": linkedFrom, "name": name, "popularity": popularity, "previewUrl": previewUrl, diff --git a/lib/provider/Playback.dart b/lib/provider/Playback.dart index a543b7a2..6abf60c9 100644 --- a/lib/provider/Playback.dart +++ b/lib/provider/Playback.dart @@ -27,6 +27,12 @@ import 'package:youtube_explode_dart/youtube_explode_dart.dart' hide Playlist; import 'package:collection/collection.dart'; import 'package:spotube/extensions/list-sort-multiple.dart'; +enum PlaybackStatus { + playing, + loading, + idle, +} + class Playback extends PersistedChangeNotifier { // player properties bool isShuffled; @@ -53,6 +59,8 @@ class Playback extends PersistedChangeNotifier { final List _subscriptions; final _logger = getLogger(Playback); + PlaybackStatus status; + Playback({ required this.player, required this.youtube, @@ -63,6 +71,7 @@ class Playback extends PersistedChangeNotifier { isPlaying = false, currentDuration = Duration.zero, _subscriptions = [], + status = PlaybackStatus.idle, super() { if (Platform.isLinux) { _linuxAudioService = LinuxAudioService(this); @@ -82,6 +91,7 @@ class Playback extends PersistedChangeNotifier { seekForward(); } else { isPlaying = false; + status = PlaybackStatus.idle; currentDuration = Duration.zero; notifyListeners(); } @@ -115,6 +125,8 @@ class Playback extends PersistedChangeNotifier { if (index < 0 || index > playlist.tracks.length - 1) return; this.playlist = playlist; final played = this.playlist!.tracks[index]; + status = PlaybackStatus.loading; + notifyListeners(); await play(played).then((_) { int i = this .playlist! @@ -131,6 +143,10 @@ class Playback extends PersistedChangeNotifier { try { // the track is already playing so no need to change that if (track.id == this.track?.id) return; + if (status != PlaybackStatus.loading) { + status = PlaybackStatus.loading; + notifyListeners(); + } final tag = MediaItem( id: track.id!, title: track.name!, @@ -149,6 +165,8 @@ class Playback extends PersistedChangeNotifier { notifyListeners(); updatePersistence(); await player.play(UrlSource(track.ytUri)); + status = PlaybackStatus.playing; + notifyListeners(); } catch (e, stack) { _logger.e("play", e, stack); } @@ -198,6 +216,7 @@ class Playback extends PersistedChangeNotifier { isShuffled = false; playlist = null; track = null; + status = PlaybackStatus.idle; currentDuration = Duration.zero; notifyListeners(); updatePersistence(clearNullEntries: true);