From a86b6bc40b1193cdd680c8da832b12c0c3bebaff Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Thu, 24 Feb 2022 13:26:21 +0600 Subject: [PATCH] persisted volume support Placeholder image instead of progress indicator in PlaybuttonCard Custom Fade Page Transition --- assets/placeholder.png | Bin 0 -> 8886 bytes lib/components/Album/AlbumCard.dart | 7 +- lib/components/Artist/ArtistCard.dart | 18 ++-- lib/components/Artist/ArtistProfile.dart | 5 +- lib/components/Category/CategoryCard.dart | 15 ++-- lib/components/Home.dart | 7 +- lib/components/Lyrics.dart | 7 +- lib/components/Player/Player.dart | 33 ++++++-- lib/components/Playlist/PlaylistCard.dart | 7 +- lib/components/Shared/PlaybuttonCard.dart | 7 +- lib/components/Shared/SpotubePageRoute.dart | 18 ++++ lib/components/Shared/TracksTableView.dart | 5 +- lib/helpers/artists-to-clickable-artists.dart | 5 +- lib/models/LocalStorageKeys.dart | 2 + pubspec.lock | 79 ++++++++---------- 15 files changed, 119 insertions(+), 96 deletions(-) create mode 100644 assets/placeholder.png create mode 100644 lib/components/Shared/SpotubePageRoute.dart diff --git a/assets/placeholder.png b/assets/placeholder.png new file mode 100644 index 0000000000000000000000000000000000000000..6f6d451f2c07a7141944461ac691b96c065f61be GIT binary patch literal 8886 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 C02ti> literal 0 HcmV?d00001 diff --git a/lib/components/Album/AlbumCard.dart b/lib/components/Album/AlbumCard.dart index e5ea9423..bdc4d864 100644 --- a/lib/components/Album/AlbumCard.dart +++ b/lib/components/Album/AlbumCard.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Album/AlbumView.dart'; import 'package:spotube/components/Shared/PlaybuttonCard.dart'; +import 'package:spotube/components/Shared/SpotubePageRoute.dart'; import 'package:spotube/helpers/artist-to-string.dart'; import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/helpers/simple-track-to-track.dart'; @@ -27,10 +28,8 @@ class AlbumCard extends ConsumerWidget { description: "Album • ${artistsToString(album.artists ?? [])}", onTap: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) { - return AlbumView(album); - }, + Navigator.of(context).push(SpotubePageRoute( + child: AlbumView(album), )); }, onPlaybuttonPressed: () async { diff --git a/lib/components/Artist/ArtistCard.dart b/lib/components/Artist/ArtistCard.dart index 0f5099e8..6f92cb59 100644 --- a/lib/components/Artist/ArtistCard.dart +++ b/lib/components/Artist/ArtistCard.dart @@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Artist/ArtistProfile.dart'; +import 'package:spotube/components/Shared/SpotubePageRoute.dart'; class ArtistCard extends StatelessWidget { final Artist artist; @@ -9,12 +10,15 @@ class ArtistCard extends StatelessWidget { @override Widget build(BuildContext context) { + final backgroundImage = CachedNetworkImageProvider((artist + .images?.isNotEmpty ?? + false) + ? artist.images!.first.url! + : "https://avatars.dicebear.com/api/open-peeps/${artist.id}.png?b=%231ed760&r=50&flip=1&translateX=3&translateY=-6"); return InkWell( onTap: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) { - return ArtistProfile(artist.id!); - }, + Navigator.of(context).push(SpotubePageRoute( + child: ArtistProfile(artist.id!), )); }, borderRadius: BorderRadius.circular(10), @@ -38,11 +42,7 @@ class ArtistCard extends StatelessWidget { CircleAvatar( maxRadius: 80, minRadius: 20, - backgroundImage: CachedNetworkImageProvider((artist - .images?.isNotEmpty ?? - false) - ? artist.images!.first.url! - : "https://avatars.dicebear.com/api/open-peeps/${artist.id}.png?b=%231ed760&r=50&flip=1&translateX=3&translateY=-6"), + backgroundImage: backgroundImage, ), Text( artist.name!, diff --git a/lib/components/Artist/ArtistProfile.dart b/lib/components/Artist/ArtistProfile.dart index a947c37b..8b2b0cdd 100644 --- a/lib/components/Artist/ArtistProfile.dart +++ b/lib/components/Artist/ArtistProfile.dart @@ -7,6 +7,7 @@ import 'package:spotube/components/Album/AlbumCard.dart'; import 'package:spotube/components/Artist/ArtistAlbumView.dart'; import 'package:spotube/components/Artist/ArtistCard.dart'; import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; +import 'package:spotube/components/Shared/SpotubePageRoute.dart'; import 'package:spotube/components/Shared/TracksTableView.dart'; import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/helpers/readable-number.dart'; @@ -215,8 +216,8 @@ class ArtistProfile extends ConsumerWidget { TextButton( child: const Text("See All"), onPressed: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) => ArtistAlbumView( + Navigator.of(context).push(SpotubePageRoute( + child: ArtistAlbumView( artistId, snapshot.data?.name ?? "KRTX", ), diff --git a/lib/components/Category/CategoryCard.dart b/lib/components/Category/CategoryCard.dart index 19811f70..99745883 100644 --- a/lib/components/Category/CategoryCard.dart +++ b/lib/components/Category/CategoryCard.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Playlist/PlaylistCard.dart'; import 'package:spotube/components/Playlist/PlaylistGenreView.dart'; +import 'package:spotube/components/Shared/SpotubePageRoute.dart'; import 'package:spotube/provider/SpotifyDI.dart'; class CategoryCard extends StatelessWidget { @@ -30,14 +31,12 @@ class CategoryCard extends StatelessWidget { TextButton( onPressed: () { Navigator.of(context).push( - MaterialPageRoute( - builder: (context) { - return PlaylistGenreView( - category.id!, - category.name!, - playlists: playlists, - ); - }, + SpotubePageRoute( + child: PlaylistGenreView( + category.id!, + category.name!, + playlists: playlists, + ), ), ); }, diff --git a/lib/components/Home.dart b/lib/components/Home.dart index 200433f3..2d6cfa97 100644 --- a/lib/components/Home.dart +++ b/lib/components/Home.dart @@ -16,6 +16,7 @@ import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; import 'package:spotube/components/Player/Player.dart'; import 'package:spotube/components/Settings.dart'; import 'package:spotube/components/Library/UserLibrary.dart'; +import 'package:spotube/components/Shared/SpotubePageRoute.dart'; import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/helpers/oauth-login.dart'; import 'package:spotube/models/LocalStorageKeys.dart'; @@ -228,10 +229,8 @@ class _HomeState extends ConsumerState { IconButton( icon: const Icon(Icons.settings_outlined), onPressed: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) { - return const Settings(); - }, + Navigator.of(context).push(SpotubePageRoute( + child: const Settings(), )); }), ], diff --git a/lib/components/Lyrics.dart b/lib/components/Lyrics.dart index 8d42e8e0..71db1357 100644 --- a/lib/components/Lyrics.dart +++ b/lib/components/Lyrics.dart @@ -3,6 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Settings.dart'; +import 'package:spotube/components/Shared/SpotubePageRoute.dart'; import 'package:spotube/helpers/artist-to-string.dart'; import 'package:spotube/helpers/getLyrics.dart'; import 'package:spotube/provider/Playback.dart'; @@ -68,10 +69,8 @@ class Lyrics extends HookConsumerWidget { ), ElevatedButton( onPressed: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) { - return const Settings(); - }, + Navigator.of(context).push(SpotubePageRoute( + child: const Settings(), )); }, child: const Text("Add Access Token")) diff --git a/lib/components/Player/Player.dart b/lib/components/Player/Player.dart index 41cbe480..96c70f4f 100644 --- a/lib/components/Player/Player.dart +++ b/lib/components/Player/Player.dart @@ -4,12 +4,14 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:just_audio/just_audio.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Shared/DownloadTrackButton.dart'; import 'package:spotube/components/Player/PlayerControls.dart'; import 'package:spotube/helpers/artists-to-clickable-artists.dart'; import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/helpers/search-youtube.dart'; +import 'package:spotube/models/LocalStorageKeys.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:flutter/material.dart'; import 'package:spotube/provider/SpotifyDI.dart'; @@ -20,14 +22,18 @@ class Player extends HookConsumerWidget { @override Widget build(BuildContext context, ref) { - var _isPlaying = useState(false); - var _shuffled = useState(false); - var _volume = useState(0.0); - var _duration = useState(null); - var _currentTrackId = useState(null); + final _isPlaying = useState(false); + final _shuffled = useState(false); + final _volume = useState(0.0); + final _duration = useState(null); + final _currentTrackId = useState(null); - AudioPlayer player = useMemoized(() => AudioPlayer(), []); - YoutubeExplode youtube = useMemoized(() => YoutubeExplode(), []); + final AudioPlayer player = useMemoized(() => AudioPlayer(), []); + final YoutubeExplode youtube = useMemoized(() => YoutubeExplode(), []); + final Future future = + useMemoized(SharedPreferences.getInstance); + final AsyncSnapshot localStorage = + useFuture(future, initialData: null); var _movePlaylistPositionBy = useCallback((int pos) { Playback playback = ref.read(playbackProvider); @@ -53,8 +59,6 @@ class Player extends HookConsumerWidget { }, [_duration]); useEffect(() { - _volume.value = player.volume; - var playingStreamListener = player.playingStream.listen((playing) async { _isPlaying.value = playing; }); @@ -97,6 +101,13 @@ class Player extends HookConsumerWidget { }; }, []); + useEffect(() { + if (localStorage.hasData) { + _volume.value = localStorage.data?.getDouble(LocalStorageKeys.volume) ?? + player.volume; + } + }, [localStorage.data]); + var _playTrack = useCallback((Track currentTrack, Playback playback) async { try { if (currentTrack.id != _currentTrackId.value) { @@ -285,6 +296,10 @@ class Player extends HookConsumerWidget { try { await player.setVolume(value).then((_) { _volume.value = value; + localStorage.data?.setDouble( + LocalStorageKeys.volume, + value, + ); }); } catch (e, stack) { print("[VolumeSlider.onChange()] $e"); diff --git a/lib/components/Playlist/PlaylistCard.dart b/lib/components/Playlist/PlaylistCard.dart index 862ee9fc..2da322ee 100644 --- a/lib/components/Playlist/PlaylistCard.dart +++ b/lib/components/Playlist/PlaylistCard.dart @@ -3,6 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Playlist/PlaylistView.dart'; import 'package:spotube/components/Shared/PlaybuttonCard.dart'; +import 'package:spotube/components/Shared/SpotubePageRoute.dart'; import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/SpotifyDI.dart'; @@ -20,10 +21,8 @@ class PlaylistCard extends ConsumerWidget { imageUrl: playlist.images![0].url!, isPlaying: isPlaylistPlaying, onTap: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) { - return PlaylistView(playlist); - }, + Navigator.of(context).push(SpotubePageRoute( + child: PlaylistView(playlist), )); }, onPlaybuttonPressed: () async { diff --git a/lib/components/Shared/PlaybuttonCard.dart b/lib/components/Shared/PlaybuttonCard.dart index 42b350e0..d0561b2b 100644 --- a/lib/components/Shared/PlaybuttonCard.dart +++ b/lib/components/Shared/PlaybuttonCard.dart @@ -46,11 +46,8 @@ class PlaybuttonCard extends StatelessWidget { borderRadius: BorderRadius.circular(8), child: CachedNetworkImage( imageUrl: imageUrl, - progressIndicatorBuilder: (context, url, progress) { - return CircularProgressIndicator.adaptive( - value: progress.progress, - ); - }, + placeholder: (context, url) => + Image.asset("assets/placeholder.png"), ), ), Positioned.directional( diff --git a/lib/components/Shared/SpotubePageRoute.dart b/lib/components/Shared/SpotubePageRoute.dart new file mode 100644 index 00000000..0cc47129 --- /dev/null +++ b/lib/components/Shared/SpotubePageRoute.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +class SpotubePageRoute extends PageRouteBuilder { + final Widget child; + SpotubePageRoute({required this.child}) + : super( + pageBuilder: (context, animation, secondaryAnimation) => child, + ); + + @override + Widget buildTransitions(BuildContext context, Animation animation, + Animation secondaryAnimation, Widget child) { + return FadeTransition( + opacity: animation, + child: child, + ); + } +} diff --git a/lib/components/Shared/TracksTableView.dart b/lib/components/Shared/TracksTableView.dart index 9ae45a14..b3a6dffb 100644 --- a/lib/components/Shared/TracksTableView.dart +++ b/lib/components/Shared/TracksTableView.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Album/AlbumView.dart'; import 'package:spotube/components/Shared/LinkText.dart'; +import 'package:spotube/components/Shared/SpotubePageRoute.dart'; import 'package:spotube/helpers/artists-to-clickable-artists.dart'; import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/helpers/zero-pad-num-str.dart'; @@ -83,8 +84,8 @@ class TracksTableView extends ConsumerWidget { Expanded( child: LinkText( track.value.album!.name!, - MaterialPageRoute( - builder: (context) => AlbumView(track.value.album!), + SpotubePageRoute( + child: AlbumView(track.value.album!), ), overflow: TextOverflow.ellipsis, ), diff --git a/lib/helpers/artists-to-clickable-artists.dart b/lib/helpers/artists-to-clickable-artists.dart index a4b11fa5..0cb5a7f6 100644 --- a/lib/helpers/artists-to-clickable-artists.dart +++ b/lib/helpers/artists-to-clickable-artists.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Artist/ArtistProfile.dart'; import 'package:spotube/components/Shared/LinkText.dart'; +import 'package:spotube/components/Shared/SpotubePageRoute.dart'; Widget artistsToClickableArtists( List artists, { @@ -19,8 +20,8 @@ Widget artistsToClickableArtists( (artist.key != artists.length - 1) ? "${artist.value.name}, " : artist.value.name!, - MaterialPageRoute( - builder: (context) => ArtistProfile(artist.value.id!), + SpotubePageRoute( + child: ArtistProfile(artist.value.id!), ), overflow: TextOverflow.ellipsis, ), diff --git a/lib/models/LocalStorageKeys.dart b/lib/models/LocalStorageKeys.dart index 70b5936a..1af5088c 100644 --- a/lib/models/LocalStorageKeys.dart +++ b/lib/models/LocalStorageKeys.dart @@ -10,4 +10,6 @@ abstract class LocalStorageKeys { static String nextTrackHotKey = "next_track_hot_key"; static String prevTrackHotKey = "prev_track_hot_key"; static String playPauseHotKey = "play_pause_hot_key"; + + static String volume = "volume"; } diff --git a/pubspec.lock b/pubspec.lock index 491d288a..0ad07331 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -14,7 +14,7 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.1.8" + version: "3.2.1" args: dependency: transitive description: @@ -180,7 +180,7 @@ packages: name: flutter_blurhash url: "https://pub.dartlang.org" source: hosted - version: "0.6.0" + version: "0.6.4" flutter_cache_manager: dependency: transitive description: @@ -225,7 +225,7 @@ packages: name: freezed_annotation url: "https://pub.dartlang.org" source: hosted - version: "0.14.3" + version: "1.1.0" hooks_riverpod: dependency: "direct main" description: @@ -267,7 +267,7 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "3.1.1" + version: "3.1.3" infinite_scroll_pagination: dependency: "direct main" description: @@ -275,13 +275,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.0" - injector: - dependency: transitive - description: - name: injector - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" js: dependency: transitive description: @@ -302,7 +295,7 @@ packages: name: just_audio url: "https://pub.dartlang.org" source: hosted - version: "0.9.18" + version: "0.9.20" just_audio_libwinmedia: dependency: "direct main" description: @@ -316,14 +309,14 @@ packages: name: just_audio_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.1.0" just_audio_web: dependency: transitive description: name: just_audio_web url: "https://pub.dartlang.org" source: hosted - version: "0.4.2" + version: "0.4.4" libwinmedia: dependency: transitive description: @@ -365,7 +358,7 @@ packages: name: msix url: "https://pub.dartlang.org" source: hosted - version: "2.8.1" + version: "2.8.18" oauth2: dependency: transitive description: @@ -400,7 +393,7 @@ packages: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.0.9" path_provider_android: dependency: transitive description: @@ -421,28 +414,28 @@ packages: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.5" path_provider_macos: dependency: transitive description: name: path_provider_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.4" + version: "2.0.5" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.3" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.4" + version: "2.0.5" pedantic: dependency: transitive description: @@ -470,7 +463,7 @@ packages: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.1.2" process: dependency: transitive description: @@ -498,35 +491,35 @@ packages: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.13" shared_preferences_android: dependency: transitive description: name: shared_preferences_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.9" + version: "2.0.11" shared_preferences_ios: dependency: transitive description: name: shared_preferences_ios url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.1.0" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.3" shared_preferences_platform_interface: dependency: transitive description: @@ -540,14 +533,14 @@ packages: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.3" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.1.0" sky_engine: dependency: transitive description: flutter @@ -580,14 +573,14 @@ packages: name: sqflite url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" sqflite_common: dependency: transitive description: name: sqflite_common url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.2.0" stack_trace: dependency: transitive description: @@ -650,63 +643,63 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.17" + version: "6.0.20" url_launcher_android: dependency: transitive description: name: url_launcher_android url: "https://pub.dartlang.org" source: hosted - version: "6.0.13" + version: "6.0.15" url_launcher_ios: dependency: transitive description: name: url_launcher_ios url: "https://pub.dartlang.org" source: hosted - version: "6.0.13" + version: "6.0.15" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "3.0.0" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "3.0.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.4" + version: "2.0.5" url_launcher_web: dependency: transitive description: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.8" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "3.0.0" uuid: dependency: transitive description: name: uuid url: "https://pub.dartlang.org" source: hosted - version: "3.0.5" + version: "3.0.6" vector_math: dependency: transitive description: @@ -720,14 +713,14 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.3.3" + version: "2.4.1" xdg_directories: dependency: transitive description: name: xdg_directories url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "0.2.0+1" xml: dependency: transitive description: @@ -748,7 +741,7 @@ packages: name: youtube_explode_dart url: "https://pub.dartlang.org" source: hosted - version: "1.10.8" + version: "1.10.9+1" sdks: dart: ">=2.15.1 <3.0.0" - flutter: ">=2.5.0" + flutter: ">=2.10.0"