From f79223cd41c61d9836d25e7bc2811c6515ba00c8 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Fri, 6 Jan 2023 12:10:03 +0600 Subject: [PATCH] feat: individual shuffle and repeat/loop button of player --- lib/components/library/user_albums.dart | 7 +-- lib/components/library/user_artists.dart | 13 +++--- lib/components/library/user_local_tracks.dart | 13 +++--- lib/components/library/user_playlists.dart | 34 +++++++++------ lib/components/player/player_controls.dart | 43 ++++++++++++------- .../track_table/track_collection_view.dart | 13 +++--- lib/models/current_playlist.dart | 2 +- lib/provider/playback_provider.dart | 41 ++++++------------ lib/services/linux_audio_service.dart | 12 +++--- 9 files changed, 95 insertions(+), 83 deletions(-) diff --git a/lib/components/library/user_albums.dart b/lib/components/library/user_albums.dart index e8301471a..76d0f5508 100644 --- a/lib/components/library/user_albums.dart +++ b/lib/components/library/user_albums.dart @@ -39,11 +39,12 @@ class UserAlbums extends HookConsumerWidget { final searchText = useState(''); final albums = useMemoized(() { + if (searchText.value.isEmpty) { + return albumsQuery.data?.toList() ?? []; + } return albumsQuery.data ?.map((e) => Tuple2( - searchText.value.isEmpty - ? 100 - : weightedRatio(e.name!, searchText.value), + weightedRatio(e.name!, searchText.value), e, )) .sorted((a, b) => b.item1.compareTo(a.item1)) diff --git a/lib/components/library/user_artists.dart b/lib/components/library/user_artists.dart index 2ef70fe34..c0edd0ddd 100644 --- a/lib/components/library/user_artists.dart +++ b/lib/components/library/user_artists.dart @@ -33,12 +33,15 @@ class UserArtists extends HookConsumerWidget { final searchText = useState(''); final filteredArtists = useMemoized(() { - return artistQuery.pages - .expand((page) => page?.items ?? const Iterable.empty()) + final artists = artistQuery.pages + .expand((page) => page?.items ?? const Iterable.empty()); + + if (searchText.value.isEmpty) { + return artists.toList(); + } + return artists .map((e) => Tuple2( - searchText.value.isEmpty - ? 100 - : weightedRatio(e.name!, searchText.value), + weightedRatio(e.name!, searchText.value), e, )) .sorted((a, b) => b.item1.compareTo(a.item1)) diff --git a/lib/components/library/user_local_tracks.dart b/lib/components/library/user_local_tracks.dart index 7da7e9527..845dc2620 100644 --- a/lib/components/library/user_local_tracks.dart +++ b/lib/components/library/user_local_tracks.dart @@ -250,14 +250,15 @@ class UserLocalTracks extends HookConsumerWidget { }, [sortBy.value, tracks]); final filteredTracks = useMemoized(() { + if (searchText.value.isEmpty) { + return sortedTracks; + } return sortedTracks .map((e) => Tuple2( - searchText.value.isEmpty - ? 100 - : weightedRatio( - "${e.name} - ${TypeConversionUtils.artists_X_String(e.artists ?? [])}", - searchText.value, - ), + weightedRatio( + "${e.name} - ${TypeConversionUtils.artists_X_String(e.artists ?? [])}", + searchText.value, + ), e, )) .toList() diff --git a/lib/components/library/user_playlists.dart b/lib/components/library/user_playlists.dart index 11a3646a1..fb7f3efed 100644 --- a/lib/components/library/user_playlists.dart +++ b/lib/components/library/user_playlists.dart @@ -52,20 +52,26 @@ class UserPlaylists extends HookConsumerWidget { likedTracksPlaylist.images = [image]; final playlists = useMemoized( - () => [ - likedTracksPlaylist, - ...?playlistsQuery.data, - ] - .map((e) => Tuple2( - searchText.value.isEmpty - ? 100 - : weightedRatio(e.name!, searchText.value), - e, - )) - .sorted((a, b) => b.item1.compareTo(a.item1)) - .where((e) => e.item1 > 50) - .map((e) => e.item2) - .toList(), + () { + if (searchText.value.isEmpty) { + return [ + likedTracksPlaylist, + ...?playlistsQuery.data, + ]; + } + return [ + likedTracksPlaylist, + ...?playlistsQuery.data, + ] + .map((e) => Tuple2( + weightedRatio(e.name!, searchText.value), + e, + )) + .sorted((a, b) => b.item1.compareTo(a.item1)) + .where((e) => e.item1 > 50) + .map((e) => e.item2) + .toList(); + }, [playlistsQuery.data, searchText.value], ); diff --git a/lib/components/player/player_controls.dart b/lib/components/player/player_controls.dart index 8a3895abf..643cda82e 100644 --- a/lib/components/player/player_controls.dart +++ b/lib/components/player/player_controls.dart @@ -139,22 +139,20 @@ class PlayerControls extends HookConsumerWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ PlatformIconButton( - tooltip: playback.isLoop - ? "Repeat playlist" - : playback.isShuffled - ? "Loop track" - : "Shuffle playlist", + tooltip: playback.isShuffled + ? "Unshuffle playlist" + : "Shuffle playlist", icon: Icon( - playback.isLoop - ? Icons.repeat_one_rounded - : playback.isShuffled - ? Icons.shuffle_rounded - : Icons.repeat_rounded, + Icons.shuffle_rounded, + color: playback.isShuffled + ? PlatformTheme.of(context).primaryColor + : null, ), - onPressed: - playback.track == null || playback.playlist == null - ? null - : playback.cyclePlaybackMode, + onPressed: playback.playlist == null + ? null + : () { + playback.setIsShuffled(!playback.isShuffled); + }, ), PlatformIconButton( tooltip: "Previous track", @@ -209,7 +207,22 @@ class PlayerControls extends HookConsumerWidget { } } : null, - ) + ), + PlatformIconButton( + tooltip: + !playback.isLoop ? "Loop Track" : "Repeat playlist", + icon: Icon( + playback.isLoop + ? Icons.repeat_one_rounded + : Icons.repeat_rounded, + ), + onPressed: + playback.track == null || playback.playlist == null + ? null + : () { + playback.setIsLoop(!playback.isLoop); + }, + ), ], ), const SizedBox(height: 5) diff --git a/lib/components/shared/track_table/track_collection_view.dart b/lib/components/shared/track_table/track_collection_view.dart index 2240538e7..03792ac84 100644 --- a/lib/components/shared/track_table/track_collection_view.dart +++ b/lib/components/shared/track_table/track_collection_view.dart @@ -103,14 +103,15 @@ class TrackCollectionView extends HookConsumerWidget { final searchText = useState(""); final filteredTracks = useMemoized(() { + if (searchText.value.isEmpty) { + return tracksSnapshot.data; + } return tracksSnapshot.data ?.map((e) => Tuple2( - searchText.value.isEmpty - ? 100 - : weightedRatio( - "${e.name} - ${TypeConversionUtils.artists_X_String(e.artists ?? [])}", - searchText.value, - ), + weightedRatio( + "${e.name} - ${TypeConversionUtils.artists_X_String(e.artists ?? [])}", + searchText.value, + ), e, )) .toList() diff --git a/lib/models/current_playlist.dart b/lib/models/current_playlist.dart index 34d953ef2..1c3f8e167 100644 --- a/lib/models/current_playlist.dart +++ b/lib/models/current_playlist.dart @@ -40,7 +40,7 @@ class CurrentPlaylist { // won't shuffle if already shuffled if (_tempTrack == null) { _tempTrack = [...tracks]; - tracks.shuffle(); + tracks = List.from(tracks)..shuffle(); if (topTrack != null) { tracks.remove(topTrack); tracks.insert(0, topTrack); diff --git a/lib/provider/playback_provider.dart b/lib/provider/playback_provider.dart index 7645cc619..7c1f0193a 100644 --- a/lib/provider/playback_provider.dart +++ b/lib/provider/playback_provider.dart @@ -39,15 +39,10 @@ enum AudioQuality { low, } -enum PlaybackMode { - repeat, - shuffle, - normal, -} - class Playback extends PersistedChangeNotifier { // player properties - PlaybackMode playbackMode; + bool isShuffled; + bool isLoop; bool isPlaying; Duration currentDuration; double volume; @@ -83,7 +78,8 @@ class Playback extends PersistedChangeNotifier { this.mobileAudioService, }) : volume = 1, isPlaying = false, - playbackMode = PlaybackMode.normal, + isShuffled = false, + isLoop = false, currentDuration = Duration.zero, _subscriptions = [], status = PlaybackStatus.idle, @@ -287,25 +283,18 @@ class Playback extends PersistedChangeNotifier { isPlaying ? await pause() : await resume(); } - void cyclePlaybackMode() { - switch (playbackMode) { - case PlaybackMode.normal: - playbackMode = PlaybackMode.shuffle; - playlist?.shuffle(track); - break; - case PlaybackMode.shuffle: - playbackMode = PlaybackMode.repeat; - playlist?.unshuffle(); - break; - case PlaybackMode.repeat: - playbackMode = PlaybackMode.normal; - break; + void setIsShuffled(bool shuffle) { + isShuffled = shuffle; + if (isShuffled) { + playlist?.shuffle(track); + } else { + playlist?.unshuffle(); } notifyListeners(); } - void setPlaybackMode(PlaybackMode mode) { - playbackMode = mode; + void setIsLoop(bool loop) { + isLoop = loop; notifyListeners(); } @@ -325,7 +314,8 @@ class Playback extends PersistedChangeNotifier { await player.stop(); await player.release(); isPlaying = false; - playbackMode = PlaybackMode.normal; + isShuffled = false; + isLoop = false; playlist = null; track = null; status = PlaybackStatus.idle; @@ -685,9 +675,6 @@ class Playback extends PersistedChangeNotifier { }; } - bool get isLoop => playbackMode == PlaybackMode.repeat; - bool get isShuffled => playbackMode == PlaybackMode.shuffle; - bool get isNormal => playbackMode == PlaybackMode.normal; UnmodifiableListView