From d05ec0099d9a9b09b3a30fef0fca896f4bb7a444 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Fri, 11 Feb 2022 10:44:16 +0600 Subject: [PATCH] flutter provider replaced with flutter_riverpod --- lib/components/Album/AlbumCard.dart | 10 +- lib/components/Album/AlbumView.dart | 10 +- lib/components/Artist/ArtistAlbumView.dart | 15 +- lib/components/Artist/ArtistProfile.dart | 10 +- lib/components/Category/CategoryCard.dart | 11 +- lib/components/Home.dart | 103 ++++----- lib/components/Library/UserArtists.dart | 16 +- lib/components/Library/UserPlaylists.dart | 10 +- lib/components/Login.dart | 187 ++++++++------- lib/components/Lyrics.dart | 12 +- lib/components/Player/Player.dart | 20 +- lib/components/Player/PlayerControls.dart | 8 +- lib/components/Playlist/PlaylistCard.dart | 14 +- .../Playlist/PlaylistGenreView.dart | 71 +++--- lib/components/Playlist/PlaylistView.dart | 125 +++++----- lib/components/Search/Search.dart | 12 +- lib/components/Settings.dart | 11 +- lib/components/Shared/TracksTableView.dart | 8 +- lib/helpers/oauth-login.dart | 6 +- lib/main.dart | 215 +++++++----------- lib/provider/Auth.dart | 3 + lib/provider/Playback.dart | 3 +- lib/provider/SpotifyDI.dart | 42 +++- lib/provider/UserPreferences.dart | 3 + pubspec.lock | 29 ++- pubspec.yaml | 2 +- 26 files changed, 472 insertions(+), 484 deletions(-) diff --git a/lib/components/Album/AlbumCard.dart b/lib/components/Album/AlbumCard.dart index eed381de..e5ea9423 100644 --- a/lib/components/Album/AlbumCard.dart +++ b/lib/components/Album/AlbumCard.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; +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'; @@ -9,13 +9,13 @@ import 'package:spotube/helpers/simple-track-to-track.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/SpotifyDI.dart'; -class AlbumCard extends StatelessWidget { +class AlbumCard extends ConsumerWidget { final Album album; const AlbumCard(this.album, {Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - Playback playback = context.watch(); + Widget build(BuildContext context, ref) { + Playback playback = ref.watch(playbackProvider); bool isPlaylistPlaying = playback.currentPlaylist != null && playback.currentPlaylist!.id == album.id; @@ -34,7 +34,7 @@ class AlbumCard extends StatelessWidget { )); }, onPlaybuttonPressed: () async { - SpotifyApi spotify = context.read().spotifyApi; + SpotifyApi spotify = ref.read(spotifyProvider); if (isPlaylistPlaying) return; List tracks = (await spotify.albums.getTracks(album.id!).all()) .map((track) => simpleTrackToTrack(track, album)) diff --git a/lib/components/Album/AlbumView.dart b/lib/components/Album/AlbumView.dart index 88f74b7e..80b1b937 100644 --- a/lib/components/Album/AlbumView.dart +++ b/lib/components/Album/AlbumView.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; import 'package:spotube/components/Shared/TracksTableView.dart'; @@ -8,7 +8,7 @@ import 'package:spotube/helpers/simple-track-to-track.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/SpotifyDI.dart'; -class AlbumView extends StatelessWidget { +class AlbumView extends ConsumerWidget { final AlbumSimple album; const AlbumView(this.album, {Key? key}) : super(key: key); @@ -31,11 +31,11 @@ class AlbumView extends StatelessWidget { } @override - Widget build(BuildContext context) { - Playback playback = context.watch(); + Widget build(BuildContext context, ref) { + Playback playback = ref.watch(playbackProvider); var isPlaylistPlaying = playback.currentPlaylist?.id == album.id; - SpotifyApi spotify = context.watch().spotifyApi; + SpotifyApi spotify = ref.watch(spotifyProvider); return Scaffold( body: FutureBuilder>( future: spotify.albums.getTracks(album.id!).all(), diff --git a/lib/components/Artist/ArtistAlbumView.dart b/lib/components/Artist/ArtistAlbumView.dart index 9f0906fd..fb3c150b 100644 --- a/lib/components/Artist/ArtistAlbumView.dart +++ b/lib/components/Artist/ArtistAlbumView.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart' hide Page; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; -import 'package:provider/provider.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Album/AlbumCard.dart'; import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; import 'package:spotube/provider/SpotifyDI.dart'; -class ArtistAlbumView extends StatefulWidget { +class ArtistAlbumView extends ConsumerStatefulWidget { final String artistId; final String artistName; const ArtistAlbumView( @@ -16,10 +16,10 @@ class ArtistAlbumView extends StatefulWidget { }) : super(key: key); @override - State createState() => _ArtistAlbumViewState(); + ConsumerState createState() => _ArtistAlbumViewState(); } -class _ArtistAlbumViewState extends State { +class _ArtistAlbumViewState extends ConsumerState { final PagingController _pagingController = PagingController(firstPageKey: 0); @@ -39,10 +39,9 @@ class _ArtistAlbumViewState extends State { _fetchPage(int pageKey) async { try { - SpotifyDI data = context.read(); - Page albums = await data.spotifyApi.artists - .albums(widget.artistId) - .getPage(8, pageKey); + SpotifyApi spotifyApi = ref.watch(spotifyProvider); + Page albums = + await spotifyApi.artists.albums(widget.artistId).getPage(8, pageKey); var items = albums.items!.toList(); diff --git a/lib/components/Artist/ArtistProfile.dart b/lib/components/Artist/ArtistProfile.dart index 5eb839c2..ce5ea13f 100644 --- a/lib/components/Artist/ArtistProfile.dart +++ b/lib/components/Artist/ArtistProfile.dart @@ -1,7 +1,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Album/AlbumCard.dart'; import 'package:spotube/components/Artist/ArtistAlbumView.dart'; @@ -14,7 +14,7 @@ import 'package:spotube/helpers/zero-pad-num-str.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/SpotifyDI.dart'; -class ArtistProfile extends StatefulWidget { +class ArtistProfile extends ConsumerStatefulWidget { final String artistId; const ArtistProfile(this.artistId, {Key? key}) : super(key: key); @@ -22,10 +22,10 @@ class ArtistProfile extends StatefulWidget { _ArtistProfileState createState() => _ArtistProfileState(); } -class _ArtistProfileState extends State { +class _ArtistProfileState extends ConsumerState { @override Widget build(BuildContext context) { - SpotifyApi spotify = context.watch().spotifyApi; + SpotifyApi spotify = ref.watch(spotifyProvider); return Scaffold( appBar: const PageWindowTitleBar( leading: BackButton(), @@ -134,7 +134,7 @@ class _ArtistProfileState extends State { return const Center( child: CircularProgressIndicator.adaptive()); } - Playback playback = context.watch(); + Playback playback = ref.watch(playbackProvider); var isPlaylistPlaying = playback.currentPlaylist?.id == snapshot.data?.id; playPlaylist(List tracks, {Track? currentTrack}) { diff --git a/lib/components/Category/CategoryCard.dart b/lib/components/Category/CategoryCard.dart index 1788fffc..06cb0d7b 100644 --- a/lib/components/Category/CategoryCard.dart +++ b/lib/components/Category/CategoryCard.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart' hide Page; -import 'package:provider/provider.dart'; +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'; @@ -51,14 +51,15 @@ class _CategoryCardState extends State { ], ), ), - Consumer( - builder: (context, data, child) { + Consumer( + builder: (context, ref, child) { + SpotifyApi spotifyApi = ref.watch(spotifyProvider); return FutureBuilder>( future: widget.playlists == null ? (widget.category.id != "user-featured-playlists" - ? data.spotifyApi.playlists + ? spotifyApi.playlists .getByCategoryId(widget.category.id!) - : data.spotifyApi.playlists.featured) + : spotifyApi.playlists.featured) .getPage(4, 0) .then((value) => value.items ?? []) : Future.value(widget.playlists), diff --git a/lib/components/Home.dart b/lib/components/Home.dart index 1a4be44d..200433f3 100644 --- a/lib/components/Home.dart +++ b/lib/components/Home.dart @@ -3,8 +3,8 @@ import 'dart:io'; import 'package:bitsdojo_window/bitsdojo_window.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart' hide Page; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; -import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:oauth2/oauth2.dart' show AuthorizationException; import 'package:spotify/spotify.dart' hide Image, Player, Search; @@ -33,14 +33,14 @@ List spotifyScopes = [ "playlist-read-collaborative" ]; -class Home extends StatefulWidget { +class Home extends ConsumerStatefulWidget { const Home({Key? key}) : super(key: key); @override _HomeState createState() => _HomeState(); } -class _HomeState extends State { +class _HomeState extends ConsumerState { final PagingController _pagingController = PagingController(firstPageKey: 0); @@ -63,7 +63,7 @@ class _HomeState extends State { DateTime? expiration = expirationStr != null ? DateTime.parse(expirationStr) : null; try { - Auth authProvider = context.read(); + Auth auth = ref.read(authProvider); if (clientId != null && clientSecret != null) { SpotifyApi spotifyApi = SpotifyApi( @@ -78,7 +78,7 @@ class _HomeState extends State { ); SpotifyApiCredentials credentials = await spotifyApi.getCredentials(); if (credentials.accessToken?.isNotEmpty ?? false) { - authProvider.setAuthState( + auth.setAuthState( clientId: clientId, clientSecret: clientSecret, accessToken: @@ -91,8 +91,8 @@ class _HomeState extends State { } _pagingController.addPageRequestListener((pageKey) async { try { - SpotifyDI data = context.read(); - Page categories = await data.spotifyApi.categories + SpotifyApi spotifyApi = ref.read(spotifyProvider); + Page categories = await spotifyApi.categories .list(country: "US") .getPage(15, pageKey); @@ -113,10 +113,10 @@ class _HomeState extends State { _pagingController.error = e; } }); - } on AuthorizationException catch (e) { + } on AuthorizationException catch (_) { if (clientId != null && clientSecret != null) { oauthLogin( - context, + ref.read(authProvider), clientId: clientId, clientSecret: clientSecret, ); @@ -136,8 +136,9 @@ class _HomeState extends State { @override Widget build(BuildContext context) { - Auth authProvider = Provider.of(context); - if (!authProvider.isLoggedIn) { + Auth auth = ref.watch(authProvider); + SpotifyApi spotify = ref.watch(spotifyProvider); + if (!auth.isLoggedIn) { return const Login(); } @@ -199,49 +200,45 @@ class _HomeState extends State { style: Theme.of(context).textTheme.headline4), ]), ), - trailing: - Consumer(builder: (context, data, widget) { - return FutureBuilder( - future: data.spotifyApi.me.get(), - builder: (context, snapshot) { - var avatarImg = imageToUrlString(snapshot.data?.images, - index: (snapshot.data?.images?.length ?? 1) - 1); - return Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - CircleAvatar( - backgroundImage: - CachedNetworkImageProvider(avatarImg), + trailing: FutureBuilder( + future: spotify.me.get(), + builder: (context, snapshot) { + var avatarImg = imageToUrlString(snapshot.data?.images, + index: (snapshot.data?.images?.length ?? 1) - 1); + return Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + CircleAvatar( + backgroundImage: + CachedNetworkImageProvider(avatarImg), + ), + const SizedBox(width: 10), + Text( + snapshot.data?.displayName ?? "User's name", + style: const TextStyle( + fontWeight: FontWeight.bold, ), - const SizedBox(width: 10), - Text( - snapshot.data?.displayName ?? "User's name", - style: const TextStyle( - fontWeight: FontWeight.bold, - ), - ), - ], - ), - IconButton( - icon: const Icon(Icons.settings_outlined), - onPressed: () { - Navigator.of(context) - .push(MaterialPageRoute( - builder: (context) { - return const Settings(); - }, - )); - }), - ], - ), - ); - }, - ); - }), + ), + ], + ), + IconButton( + icon: const Icon(Icons.settings_outlined), + onPressed: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) { + return const Settings(); + }, + )); + }), + ], + ), + ); + }, + ), ), // contents of the spotify if (_selectedIndex == 0) diff --git a/lib/components/Library/UserArtists.dart b/lib/components/Library/UserArtists.dart index 60291c33..17fae18e 100644 --- a/lib/components/Library/UserArtists.dart +++ b/lib/components/Library/UserArtists.dart @@ -1,18 +1,18 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; -import 'package:provider/provider.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Artist/ArtistCard.dart'; import 'package:spotube/provider/SpotifyDI.dart'; -class UserArtists extends StatefulWidget { +class UserArtists extends ConsumerStatefulWidget { const UserArtists({Key? key}) : super(key: key); @override - State createState() => _UserArtistsState(); + ConsumerState createState() => _UserArtistsState(); } -class _UserArtistsState extends State { +class _UserArtistsState extends ConsumerState { final PagingController _pagingController = PagingController(firstPageKey: ""); @@ -22,8 +22,8 @@ class _UserArtistsState extends State { WidgetsBinding.instance?.addPostFrameCallback((timestamp) { _pagingController.addPageRequestListener((pageKey) async { try { - SpotifyDI data = context.read(); - CursorPage artists = await data.spotifyApi.me + SpotifyApi spotifyApi = ref.read(spotifyProvider); + CursorPage artists = await spotifyApi.me .following(FollowingType.artist) .getPage(15, pageKey); @@ -51,10 +51,10 @@ class _UserArtistsState extends State { @override Widget build(BuildContext context) { - SpotifyDI data = context.watch(); + SpotifyApi spotifyApi = ref.watch(spotifyProvider); return FutureBuilder>( - future: data.spotifyApi.me.following(FollowingType.artist).first(), + future: spotifyApi.me.following(FollowingType.artist).first(), builder: (context, snapshot) { if (!snapshot.hasData) { return const Center(child: CircularProgressIndicator.adaptive()); diff --git a/lib/components/Library/UserPlaylists.dart b/lib/components/Library/UserPlaylists.dart index dbe37fbe..ce6076c0 100644 --- a/lib/components/Library/UserPlaylists.dart +++ b/lib/components/Library/UserPlaylists.dart @@ -1,18 +1,18 @@ import 'package:flutter/material.dart' hide Image; -import 'package:provider/provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Playlist/PlaylistCard.dart'; import 'package:spotube/provider/SpotifyDI.dart'; -class UserPlaylists extends StatelessWidget { +class UserPlaylists extends ConsumerWidget { const UserPlaylists({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - SpotifyDI data = context.watch(); + Widget build(BuildContext context, ref) { + SpotifyApi spotifyApi = ref.watch(spotifyProvider); return FutureBuilder>( - future: data.spotifyApi.playlists.me.all(), + future: spotifyApi.playlists.me.all(), builder: (context, snapshot) { if (!snapshot.hasData) { return const Center(child: CircularProgressIndicator.adaptive()); diff --git a/lib/components/Login.dart b/lib/components/Login.dart index e7bb4427..3c144baa 100644 --- a/lib/components/Login.dart +++ b/lib/components/Login.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:spotube/components/Shared/Hyperlink.dart'; import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; @@ -8,14 +8,14 @@ import 'package:spotube/models/LocalStorageKeys.dart'; import 'package:spotube/provider/Auth.dart'; import 'package:spotube/provider/UserPreferences.dart'; -class Login extends StatefulWidget { +class Login extends ConsumerStatefulWidget { const Login({Key? key}) : super(key: key); @override _LoginState createState() => _LoginState(); } -class _LoginState extends State { +class _LoginState extends ConsumerState { String clientId = ""; String clientSecret = ""; String accessToken = ""; @@ -28,7 +28,8 @@ class _LoginState extends State { _fieldError = true; }); } - await oauthLogin(context, clientId: clientId, clientSecret: clientSecret); + await oauthLogin(ref.read(authProvider), + clientId: clientId, clientSecret: clientSecret); } catch (e) { print("[Login.handleLogin] $e"); } @@ -36,99 +37,95 @@ class _LoginState extends State { @override Widget build(BuildContext context) { - return Consumer( - builder: (context, authState, child) { - return Scaffold( - appBar: const PageWindowTitleBar(), - body: SingleChildScrollView( - child: Center( - child: Column( - children: [ - Image.asset( - "assets/spotube-logo.png", - width: 400, - height: 400, - ), - Text("Add your spotify credentials to get started", - style: Theme.of(context).textTheme.headline4), - const Text( - "Don't worry, any of your credentials won't be collected or shared with anyone"), - const Hyperlink("How to get these client-id & client-secret?", - "https://github.com/KRTirtho/spotube#configuration"), - const SizedBox( - height: 10, - ), - Container( - constraints: const BoxConstraints( - maxWidth: 400, - ), - child: Column( - children: [ - TextField( - decoration: const InputDecoration( - hintText: "Spotify Client ID", - label: Text("ClientID"), - ), - onChanged: (value) { - setState(() { - clientId = value; - }); - }, - ), - const SizedBox(height: 10), - TextField( - decoration: const InputDecoration( - hintText: "Spotify Client Secret", - label: Text("Client Secret"), - ), - onChanged: (value) { - setState(() { - clientSecret = value; - }); - }, - ), - const SizedBox(height: 10), - const Divider(color: Colors.grey), - const SizedBox(height: 10), - TextField( - decoration: const InputDecoration( - label: Text("Genius Access Token (optional)"), - ), - onChanged: (value) { - setState(() { - accessToken = value; - }); - }, - ), - const SizedBox( - height: 10, - ), - ElevatedButton( - onPressed: () async { - await handleLogin(authState); - UserPreferences preferences = - context.read(); - SharedPreferences localStorage = - await SharedPreferences.getInstance(); - preferences.setGeniusAccessToken(accessToken); - await localStorage.setString( - LocalStorageKeys.geniusAccessToken, - accessToken); - setState(() { - accessToken = ""; - }); - }, - child: const Text("Submit"), - ) - ], - ), - ), - ], + Auth authState = ref.watch(authProvider); + return Scaffold( + appBar: const PageWindowTitleBar(), + body: SingleChildScrollView( + child: Center( + child: Column( + children: [ + Image.asset( + "assets/spotube-logo.png", + width: 400, + height: 400, ), - ), + Text("Add your spotify credentials to get started", + style: Theme.of(context).textTheme.headline4), + const Text( + "Don't worry, any of your credentials won't be collected or shared with anyone"), + const Hyperlink("How to get these client-id & client-secret?", + "https://github.com/KRTirtho/spotube#configuration"), + const SizedBox( + height: 10, + ), + Container( + constraints: const BoxConstraints( + maxWidth: 400, + ), + child: Column( + children: [ + TextField( + decoration: const InputDecoration( + hintText: "Spotify Client ID", + label: Text("ClientID"), + ), + onChanged: (value) { + setState(() { + clientId = value; + }); + }, + ), + const SizedBox(height: 10), + TextField( + decoration: const InputDecoration( + hintText: "Spotify Client Secret", + label: Text("Client Secret"), + ), + onChanged: (value) { + setState(() { + clientSecret = value; + }); + }, + ), + const SizedBox(height: 10), + const Divider(color: Colors.grey), + const SizedBox(height: 10), + TextField( + decoration: const InputDecoration( + label: Text("Genius Access Token (optional)"), + ), + onChanged: (value) { + setState(() { + accessToken = value; + }); + }, + ), + const SizedBox( + height: 10, + ), + ElevatedButton( + onPressed: () async { + await handleLogin(authState); + UserPreferences preferences = + ref.read(userPreferencesProvider); + SharedPreferences localStorage = + await SharedPreferences.getInstance(); + preferences.setGeniusAccessToken(accessToken); + await localStorage.setString( + LocalStorageKeys.geniusAccessToken, accessToken); + setState(() { + accessToken = ""; + }); + }, + child: const Text("Submit"), + ) + ], + ), + ), + ], ), - ); - }, + ), + ), ); } } diff --git a/lib/components/Lyrics.dart b/lib/components/Lyrics.dart index dcc5b19a..cd09c82b 100644 --- a/lib/components/Lyrics.dart +++ b/lib/components/Lyrics.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Settings.dart'; import 'package:spotube/helpers/artist-to-string.dart'; @@ -7,20 +7,20 @@ import 'package:spotube/helpers/getLyrics.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/UserPreferences.dart'; -class Lyrics extends StatefulWidget { +class Lyrics extends ConsumerStatefulWidget { const Lyrics({Key? key}) : super(key: key); @override - State createState() => _LyricsState(); + ConsumerState createState() => _LyricsState(); } -class _LyricsState extends State { +class _LyricsState extends ConsumerState { Map _lyrics = {}; @override Widget build(BuildContext context) { - Playback playback = context.watch(); - UserPreferences userPreferences = context.watch(); + Playback playback = ref.watch(playbackProvider); + UserPreferences userPreferences = ref.watch(userPreferencesProvider); bool hasToken = (userPreferences.geniusAccessToken != null || (userPreferences.geniusAccessToken?.isNotEmpty ?? false)); diff --git a/lib/components/Player/Player.dart b/lib/components/Player/Player.dart index dd689c6f..33430389 100644 --- a/lib/components/Player/Player.dart +++ b/lib/components/Player/Player.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:just_audio/just_audio.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Shared/DownloadTrackButton.dart'; @@ -10,18 +11,17 @@ import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/helpers/search-youtube.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; import 'package:spotube/provider/SpotifyDI.dart'; import 'package:youtube_explode_dart/youtube_explode_dart.dart'; -class Player extends StatefulWidget { +class Player extends ConsumerStatefulWidget { const Player({Key? key}) : super(key: key); @override _PlayerState createState() => _PlayerState(); } -class _PlayerState extends State with WidgetsBindingObserver { +class _PlayerState extends ConsumerState with WidgetsBindingObserver { late AudioPlayer player; bool _isPlaying = false; bool _shuffled = false; @@ -111,7 +111,7 @@ class _PlayerState extends State with WidgetsBindingObserver { } void _movePlaylistPositionBy(int pos) { - Playback playback = context.read(); + Playback playback = ref.read(playbackProvider); if (playback.currentTrack != null && playback.currentPlaylist != null) { int index = playback.currentPlaylist!.trackIds .indexOf(playback.currentTrack!.id!) + @@ -198,8 +198,9 @@ class _PlayerState extends State with WidgetsBindingObserver { Widget build(BuildContext context) { return Container( color: Theme.of(context).backgroundColor, - child: Consumer( - builder: (context, playback, widget) { + child: Consumer( + builder: (context, ref, widget) { + Playback playback = ref.watch(playbackProvider); if (playback.currentPlaylist != null && playback.currentTrack != null) { _playTrack(playback.currentTrack!, playback); @@ -348,10 +349,11 @@ class _PlayerState extends State with WidgetsBindingObserver { DownloadTrackButton( track: playback.currentTrack, ), - Consumer(builder: (context, data, widget) { + Consumer(builder: (context, ref, widget) { + SpotifyApi spotifyApi = ref.watch(spotifyProvider); return FutureBuilder( future: playback.currentTrack?.id != null - ? data.spotifyApi.tracks.me + ? spotifyApi.tracks.me .containsOne(playback.currentTrack!.id!) : Future.value(false), initialData: false, @@ -367,7 +369,7 @@ class _PlayerState extends State with WidgetsBindingObserver { onPressed: () { if (!isLiked && playback.currentTrack?.id != null) { - data.spotifyApi.tracks.me + spotifyApi.tracks.me .saveOne( playback.currentTrack!.id!) .then((value) => setState(() {})); diff --git a/lib/components/Player/PlayerControls.dart b/lib/components/Player/PlayerControls.dart index adcefee9..38dc849e 100644 --- a/lib/components/Player/PlayerControls.dart +++ b/lib/components/Player/PlayerControls.dart @@ -1,13 +1,13 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:hotkey_manager/hotkey_manager.dart'; import 'package:spotube/helpers/zero-pad-num-str.dart'; import 'package:spotube/models/GlobalKeyActions.dart'; import 'package:spotube/provider/UserPreferences.dart'; -import 'package:provider/provider.dart'; -class PlayerControls extends StatefulWidget { +class PlayerControls extends ConsumerStatefulWidget { final Stream positionStream; final bool isPlaying; final Duration duration; @@ -38,7 +38,7 @@ class PlayerControls extends StatefulWidget { _PlayerControlsState createState() => _PlayerControlsState(); } -class _PlayerControlsState extends State { +class _PlayerControlsState extends ConsumerState { StreamSubscription? _timePositionListener; late List _hotKeys = []; @@ -88,7 +88,7 @@ class _PlayerControlsState extends State { @override Widget build(BuildContext context) { - UserPreferences preferences = context.watch(); + UserPreferences preferences = ref.watch(userPreferencesProvider); _configureHotKeys(preferences); return Container( diff --git a/lib/components/Playlist/PlaylistCard.dart b/lib/components/Playlist/PlaylistCard.dart index c79052dc..9995b0fd 100644 --- a/lib/components/Playlist/PlaylistCard.dart +++ b/lib/components/Playlist/PlaylistCard.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Playlist/PlaylistView.dart'; import 'package:spotube/components/Shared/PlaybuttonCard.dart'; @@ -7,17 +7,17 @@ import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/SpotifyDI.dart'; -class PlaylistCard extends StatefulWidget { +class PlaylistCard extends ConsumerStatefulWidget { final PlaylistSimple playlist; const PlaylistCard(this.playlist, {Key? key}) : super(key: key); @override _PlaylistCardState createState() => _PlaylistCardState(); } -class _PlaylistCardState extends State { +class _PlaylistCardState extends ConsumerState { @override Widget build(BuildContext context) { - Playback playback = context.watch(); + Playback playback = ref.watch(playbackProvider); bool isPlaylistPlaying = playback.currentPlaylist != null && playback.currentPlaylist!.id == widget.playlist.id; return PlaybuttonCard( @@ -33,13 +33,13 @@ class _PlaylistCardState extends State { }, onPlaybuttonPressed: () async { if (isPlaylistPlaying) return; - SpotifyDI data = context.read(); + SpotifyApi spotifyApi = ref.read(spotifyProvider); List tracks = (widget.playlist.id != "user-liked-tracks" - ? await data.spotifyApi.playlists + ? await spotifyApi.playlists .getTracksByPlaylistId(widget.playlist.id!) .all() - : await data.spotifyApi.tracks.me.saved + : await spotifyApi.tracks.me.saved .all() .then((tracks) => tracks.map((e) => e.track!))) .toList(); diff --git a/lib/components/Playlist/PlaylistGenreView.dart b/lib/components/Playlist/PlaylistGenreView.dart index 44597c60..4497ae7b 100644 --- a/lib/components/Playlist/PlaylistGenreView.dart +++ b/lib/components/Playlist/PlaylistGenreView.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; import 'package:spotube/components/Playlist/PlaylistCard.dart'; @@ -33,39 +33,42 @@ class _PlaylistGenreViewState extends State { style: Theme.of(context).textTheme.headline4, textAlign: TextAlign.center, ), - Consumer( - builder: (context, data, child) => Expanded( - child: SingleChildScrollView( - child: FutureBuilder>( - future: widget.playlists == null - ? (widget.genreId != "user-featured-playlists" - ? data.spotifyApi.playlists - .getByCategoryId(widget.genreId) - .all() - : data.spotifyApi.playlists.featured.all()) - : Future.value(widget.playlists), - builder: (context, snapshot) { - if (snapshot.hasError) { - return const Center(child: Text("Error occurred")); - } - if (!snapshot.hasData) { - return const CircularProgressIndicator.adaptive(); - } - return Center( - child: Wrap( - children: snapshot.data! - .map( - (playlist) => Padding( - padding: const EdgeInsets.all(8.0), - child: PlaylistCard(playlist), - ), - ) - .toList(), - ), - ); - }), - ), - ), + Consumer( + builder: (context, ref, child) { + SpotifyApi spotifyApi = ref.watch(spotifyProvider); + return Expanded( + child: SingleChildScrollView( + child: FutureBuilder>( + future: widget.playlists == null + ? (widget.genreId != "user-featured-playlists" + ? spotifyApi.playlists + .getByCategoryId(widget.genreId) + .all() + : spotifyApi.playlists.featured.all()) + : Future.value(widget.playlists), + builder: (context, snapshot) { + if (snapshot.hasError) { + return const Center(child: Text("Error occurred")); + } + if (!snapshot.hasData) { + return const CircularProgressIndicator.adaptive(); + } + return Center( + child: Wrap( + children: snapshot.data! + .map( + (playlist) => Padding( + padding: const EdgeInsets.all(8.0), + child: PlaylistCard(playlist), + ), + ) + .toList(), + ), + ); + }), + ), + ); + }, ) ], ), diff --git a/lib/components/Playlist/PlaylistView.dart b/lib/components/Playlist/PlaylistView.dart index 524a251f..5f9ef5a6 100644 --- a/lib/components/Playlist/PlaylistView.dart +++ b/lib/components/Playlist/PlaylistView.dart @@ -1,20 +1,20 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; import 'package:spotube/components/Shared/TracksTableView.dart'; import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/provider/SpotifyDI.dart'; -class PlaylistView extends StatefulWidget { +class PlaylistView extends ConsumerStatefulWidget { final PlaylistSimple playlist; const PlaylistView(this.playlist, {Key? key}) : super(key: key); @override _PlaylistViewState createState() => _PlaylistViewState(); } -class _PlaylistViewState extends State { +class _PlaylistViewState extends ConsumerState { playPlaylist(Playback playback, List tracks, {Track? currentTrack}) { currentTrack ??= tracks.first; var isPlaylistPlaying = playback.currentPlaylist?.id != null && @@ -36,71 +36,70 @@ class _PlaylistViewState extends State { @override Widget build(BuildContext context) { - Playback playback = context.watch(); + Playback playback = ref.watch(playbackProvider); + SpotifyApi spotifyApi = ref.watch(spotifyProvider); var isPlaylistPlaying = playback.currentPlaylist?.id != null && playback.currentPlaylist?.id == widget.playlist.id; - return Consumer(builder: (_, data, __) { - return Scaffold( - body: FutureBuilder>( - future: widget.playlist.id != "user-liked-tracks" - ? data.spotifyApi.playlists - .getTracksByPlaylistId(widget.playlist.id) - .all() - : data.spotifyApi.tracks.me.saved - .all() - .then((tracks) => tracks.map((e) => e.track!)), - builder: (context, snapshot) { - List tracks = snapshot.data?.toList() ?? []; - return Column( - children: [ - PageWindowTitleBar( - leading: Row( - children: [ - // nav back - const BackButton(), - // heart playlist - IconButton( - icon: const Icon(Icons.favorite_outline_rounded), - onPressed: () {}, + return Scaffold( + body: FutureBuilder>( + future: widget.playlist.id != "user-liked-tracks" + ? spotifyApi.playlists + .getTracksByPlaylistId(widget.playlist.id) + .all() + : spotifyApi.tracks.me.saved + .all() + .then((tracks) => tracks.map((e) => e.track!)), + builder: (context, snapshot) { + List tracks = snapshot.data?.toList() ?? []; + return Column( + children: [ + PageWindowTitleBar( + leading: Row( + children: [ + // nav back + const BackButton(), + // heart playlist + IconButton( + icon: const Icon(Icons.favorite_outline_rounded), + onPressed: () {}, + ), + // play playlist + IconButton( + icon: Icon( + isPlaylistPlaying + ? Icons.stop_rounded + : Icons.play_arrow_rounded, ), - // play playlist - IconButton( - icon: Icon( - isPlaylistPlaying - ? Icons.stop_rounded - : Icons.play_arrow_rounded, - ), - onPressed: snapshot.hasData - ? () => playPlaylist(playback, tracks) - : null, - ) - ], - ), + onPressed: snapshot.hasData + ? () => playPlaylist(playback, tracks) + : null, + ) + ], ), - Center( - child: Text(widget.playlist.name!, - style: Theme.of(context).textTheme.headline4), - ), - snapshot.hasError - ? const Center(child: Text("Error occurred")) - : !snapshot.hasData - ? const Expanded( - child: Center( - child: CircularProgressIndicator.adaptive()), - ) - : TracksTableView( + ), + Center( + child: Text(widget.playlist.name!, + style: Theme.of(context).textTheme.headline4), + ), + snapshot.hasError + ? const Center(child: Text("Error occurred")) + : !snapshot.hasData + ? const Expanded( + child: Center( + child: CircularProgressIndicator.adaptive()), + ) + : TracksTableView( + tracks, + onTrackPlayButtonPressed: (currentTrack) => + playPlaylist( + playback, tracks, - onTrackPlayButtonPressed: (currentTrack) => - playPlaylist( - playback, - tracks, - currentTrack: currentTrack, - ), + currentTrack: currentTrack, ), - ], - ); - }), - ); - }); + ), + ], + ); + }), + ); } } diff --git a/lib/components/Search/Search.dart b/lib/components/Search/Search.dart index 10649e1b..e13dd643 100644 --- a/lib/components/Search/Search.dart +++ b/lib/components/Search/Search.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart' hide Page; -import 'package:provider/provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Album/AlbumCard.dart'; import 'package:spotube/components/Artist/ArtistCard.dart'; @@ -11,14 +11,14 @@ import 'package:spotube/helpers/zero-pad-num-str.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/SpotifyDI.dart'; -class Search extends StatefulWidget { +class Search extends ConsumerStatefulWidget { const Search({Key? key}) : super(key: key); @override - State createState() => _SearchState(); + ConsumerState createState() => _SearchState(); } -class _SearchState extends State { +class _SearchState extends ConsumerState { late TextEditingController _controller; String searchTerm = ""; @@ -31,7 +31,7 @@ class _SearchState extends State { @override Widget build(BuildContext context) { - SpotifyApi spotify = context.watch().spotifyApi; + SpotifyApi spotify = ref.watch(spotifyProvider); return Expanded( child: Column( @@ -80,7 +80,7 @@ class _SearchState extends State { } else if (!snapshot.hasData && searchTerm.isEmpty) { return Container(); } - Playback playback = context.watch(); + Playback playback = ref.watch(playbackProvider); List albums = []; List artists = []; List tracks = []; diff --git a/lib/components/Settings.dart b/lib/components/Settings.dart index 705e2059..057dfe4d 100644 --- a/lib/components/Settings.dart +++ b/lib/components/Settings.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:hotkey_manager/hotkey_manager.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:spotube/components/Settings/SettingsHotkeyTile.dart'; import 'package:spotube/components/Shared/Hyperlink.dart'; @@ -10,14 +9,14 @@ import 'package:spotube/models/LocalStorageKeys.dart'; import 'package:spotube/provider/Auth.dart'; import 'package:spotube/provider/UserPreferences.dart'; -class Settings extends StatefulWidget { +class Settings extends ConsumerStatefulWidget { const Settings({Key? key}) : super(key: key); @override _SettingsState createState() => _SettingsState(); } -class _SettingsState extends State { +class _SettingsState extends ConsumerState { TextEditingController? _textEditingController; String? _geniusAccessToken; @@ -40,7 +39,7 @@ class _SettingsState extends State { @override Widget build(BuildContext context) { - UserPreferences preferences = context.watch(); + UserPreferences preferences = ref.watch(userPreferencesProvider); return Scaffold( appBar: PageWindowTitleBar( @@ -151,7 +150,7 @@ class _SettingsState extends State { ), const SizedBox(height: 10), Builder(builder: (context) { - var auth = context.read(); + Auth auth = ref.watch(authProvider); return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/components/Shared/TracksTableView.dart b/lib/components/Shared/TracksTableView.dart index 6cacc577..9ae45a14 100644 --- a/lib/components/Shared/TracksTableView.dart +++ b/lib/components/Shared/TracksTableView.dart @@ -1,6 +1,6 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; +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'; @@ -9,7 +9,7 @@ import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/helpers/zero-pad-num-str.dart'; import 'package:spotube/provider/Playback.dart'; -class TracksTableView extends StatelessWidget { +class TracksTableView extends ConsumerWidget { final void Function(Track currentTrack)? onTrackPlayButtonPressed; final List tracks; const TracksTableView(this.tracks, {Key? key, this.onTrackPlayButtonPressed}) @@ -97,8 +97,8 @@ class TracksTableView extends StatelessWidget { } @override - Widget build(BuildContext context) { - Playback playback = context.watch(); + Widget build(context, ref) { + Playback playback = ref.watch(playbackProvider); TextStyle tableHeadStyle = const TextStyle(fontWeight: FontWeight.bold, fontSize: 16); return Expanded( diff --git a/lib/helpers/oauth-login.dart b/lib/helpers/oauth-login.dart index e9bdbeb7..4ff3fb2d 100644 --- a/lib/helpers/oauth-login.dart +++ b/lib/helpers/oauth-login.dart @@ -1,5 +1,3 @@ -import 'package:flutter/cupertino.dart'; -import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/Home.dart'; @@ -9,7 +7,7 @@ import 'package:spotube/provider/Auth.dart'; const redirectUri = "http://localhost:4304/auth/spotify/callback"; -Future oauthLogin(BuildContext context, +Future oauthLogin(Auth auth, {required String clientId, required String clientSecret}) async { try { String? accessToken; @@ -50,7 +48,7 @@ Future oauthLogin(BuildContext context, clientSecret, ); - Provider.of(context, listen: false).setAuthState( + auth.setAuthState( clientId: clientId, clientSecret: clientSecret, accessToken: accessToken, diff --git a/lib/main.dart b/lib/main.dart index f1bb3faa..575bc93e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,20 +1,15 @@ import 'package:bitsdojo_window/bitsdojo_window.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:hotkey_manager/hotkey_manager.dart'; -import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:spotify/spotify.dart'; import 'package:spotube/components/Home.dart'; import 'package:spotube/models/LocalStorageKeys.dart'; -import 'package:spotube/provider/Auth.dart'; -import 'package:spotube/provider/Playback.dart'; -import 'package:spotube/provider/SpotifyDI.dart'; -import 'package:spotube/provider/UserPreferences.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await hotKeyManager.unregisterAll(); - runApp(MyApp()); + runApp(const ProviderScope(child: MyApp())); doWhenWindowReady(() { appWindow.minSize = const Size(900, 700); appWindow.size = const Size(900, 700); @@ -25,6 +20,8 @@ void main() async { } class MyApp extends StatefulWidget { + const MyApp({Key? key}) : super(key: key); + static _MyAppState? of(BuildContext context) => context.findAncestorStateOfType<_MyAppState>(); @override @@ -72,139 +69,95 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { - return MultiProvider( - providers: [ - ChangeNotifierProvider(create: (context) => Auth()), - ChangeNotifierProvider(create: (context) { - Auth authState = Provider.of(context, listen: false); - return SpotifyDI( - SpotifyApi( - SpotifyApiCredentials( - authState.clientId, - authState.clientSecret, - accessToken: authState.accessToken, - refreshToken: authState.refreshToken, - expiration: authState.expiration, - scopes: spotifyScopes, - ), - onCredentialsRefreshed: (credentials) async { - SharedPreferences localStorage = - await SharedPreferences.getInstance(); - localStorage.setString( - LocalStorageKeys.refreshToken, - credentials.refreshToken!, - ); - localStorage.setString( - LocalStorageKeys.accessToken, - credentials.accessToken!, - ); - localStorage.setString( - LocalStorageKeys.clientId, credentials.clientId!); - localStorage.setString( - LocalStorageKeys.clientSecret, - credentials.clientSecret!, - ); - }, - ), - ); - }), - ChangeNotifierProvider(create: (context) => Playback()), - ChangeNotifierProvider( - create: (context) { - return UserPreferences(); - }, + return MaterialApp( + debugShowCheckedModeBanner: false, + title: 'Spotube', + theme: ThemeData( + primaryColor: Colors.green, + primarySwatch: Colors.green, + buttonTheme: const ButtonThemeData( + buttonColor: Colors.green, ), - ], - child: MaterialApp( - debugShowCheckedModeBanner: false, - title: 'Spotube', - theme: ThemeData( - primaryColor: Colors.green, - primarySwatch: Colors.green, - buttonTheme: const ButtonThemeData( - buttonColor: Colors.green, - ), - shadowColor: Colors.grey[300], - backgroundColor: Colors.white, - textTheme: TextTheme( - bodyText1: TextStyle(color: Colors.grey[850]), - headline1: TextStyle(color: Colors.grey[850]), - headline2: TextStyle(color: Colors.grey[850]), - headline3: TextStyle(color: Colors.grey[850]), - headline4: TextStyle(color: Colors.grey[850]), - headline5: TextStyle(color: Colors.grey[850]), - headline6: TextStyle(color: Colors.grey[850]), - ), - listTileTheme: ListTileThemeData( - iconColor: Colors.grey[850], - horizontalTitleGap: 0, - ), - inputDecorationTheme: InputDecorationTheme( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.green[400]!, - width: 2.0, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.grey[800]!, - ), + shadowColor: Colors.grey[300], + backgroundColor: Colors.white, + textTheme: TextTheme( + bodyText1: TextStyle(color: Colors.grey[850]), + headline1: TextStyle(color: Colors.grey[850]), + headline2: TextStyle(color: Colors.grey[850]), + headline3: TextStyle(color: Colors.grey[850]), + headline4: TextStyle(color: Colors.grey[850]), + headline5: TextStyle(color: Colors.grey[850]), + headline6: TextStyle(color: Colors.grey[850]), + ), + listTileTheme: ListTileThemeData( + iconColor: Colors.grey[850], + horizontalTitleGap: 0, + ), + inputDecorationTheme: InputDecorationTheme( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.green[400]!, + width: 2.0, ), ), - navigationRailTheme: NavigationRailThemeData( - backgroundColor: Colors.blueGrey[50], - unselectedIconTheme: - IconThemeData(color: Colors.grey[850], opacity: 1), - unselectedLabelTextStyle: TextStyle( - color: Colors.grey[850], + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.grey[800]!, ), ), - cardTheme: CardTheme( - shape: - RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), - color: Colors.white, - ), ), - darkTheme: ThemeData( - brightness: Brightness.dark, - primaryColor: Colors.green, - primarySwatch: Colors.green, - backgroundColor: Colors.blueGrey[900], - scaffoldBackgroundColor: Colors.blueGrey[900], - dialogBackgroundColor: Colors.blueGrey[800], - shadowColor: Colors.black26, - buttonTheme: const ButtonThemeData( - buttonColor: Colors.green, + navigationRailTheme: NavigationRailThemeData( + backgroundColor: Colors.blueGrey[50], + unselectedIconTheme: + IconThemeData(color: Colors.grey[850], opacity: 1), + unselectedLabelTextStyle: TextStyle( + color: Colors.grey[850], ), - inputDecorationTheme: InputDecorationTheme( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.green[400]!, - width: 2.0, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Colors.grey[800]!, - ), - ), - ), - navigationRailTheme: NavigationRailThemeData( - backgroundColor: Colors.blueGrey[800], - unselectedIconTheme: const IconThemeData(opacity: 1), - ), - cardTheme: CardTheme( - shape: - RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), - color: Colors.blueGrey[900], - elevation: 20, - ), - canvasColor: Colors.blueGrey[900], ), - themeMode: _themeMode, - home: const Home(), + cardTheme: CardTheme( + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + color: Colors.white, + ), ), + darkTheme: ThemeData( + brightness: Brightness.dark, + primaryColor: Colors.green, + primarySwatch: Colors.green, + backgroundColor: Colors.blueGrey[900], + scaffoldBackgroundColor: Colors.blueGrey[900], + dialogBackgroundColor: Colors.blueGrey[800], + shadowColor: Colors.black26, + buttonTheme: const ButtonThemeData( + buttonColor: Colors.green, + ), + inputDecorationTheme: InputDecorationTheme( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.green[400]!, + width: 2.0, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.grey[800]!, + ), + ), + ), + navigationRailTheme: NavigationRailThemeData( + backgroundColor: Colors.blueGrey[800], + unselectedIconTheme: const IconThemeData(opacity: 1), + ), + cardTheme: CardTheme( + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + color: Colors.blueGrey[900], + elevation: 20, + ), + canvasColor: Colors.blueGrey[900], + ), + themeMode: _themeMode, + home: const Home(), ); } } diff --git a/lib/provider/Auth.dart b/lib/provider/Auth.dart index 5249b891..d5e69dc2 100644 --- a/lib/provider/Auth.dart +++ b/lib/provider/Auth.dart @@ -1,4 +1,5 @@ import 'package:flutter/cupertino.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; class Auth with ChangeNotifier { String? _clientId; @@ -52,3 +53,5 @@ class Auth with ChangeNotifier { notifyListeners(); } } + +var authProvider = ChangeNotifierProvider((ref) => Auth()); diff --git a/lib/provider/Playback.dart b/lib/provider/Playback.dart index fb20d153..b8978555 100644 --- a/lib/provider/Playback.dart +++ b/lib/provider/Playback.dart @@ -1,4 +1,5 @@ import 'package:flutter/cupertino.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; class CurrentPlaylist { @@ -77,4 +78,4 @@ class Playback extends ChangeNotifier { } } -var x = Playback(); +var playbackProvider = ChangeNotifierProvider((_) => Playback()); diff --git a/lib/provider/SpotifyDI.dart b/lib/provider/SpotifyDI.dart index f8723440..acfe96e2 100644 --- a/lib/provider/SpotifyDI.dart +++ b/lib/provider/SpotifyDI.dart @@ -1,10 +1,36 @@ -import 'package:flutter/cupertino.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:spotify/spotify.dart'; +import 'package:spotube/components/Home.dart'; +import 'package:spotube/models/LocalStorageKeys.dart'; +import 'package:spotube/provider/Auth.dart'; -class SpotifyDI extends ChangeNotifier { - SpotifyApi _spotifyApi; - - SpotifyDI(this._spotifyApi); - - SpotifyApi get spotifyApi => _spotifyApi; -} +var spotifyProvider = Provider((ref) { + Auth authState = ref.watch(authProvider); + return SpotifyApi( + SpotifyApiCredentials( + authState.clientId, + authState.clientSecret, + accessToken: authState.accessToken, + refreshToken: authState.refreshToken, + expiration: authState.expiration, + scopes: spotifyScopes, + ), + onCredentialsRefreshed: (credentials) async { + SharedPreferences localStorage = await SharedPreferences.getInstance(); + localStorage.setString( + LocalStorageKeys.refreshToken, + credentials.refreshToken!, + ); + localStorage.setString( + LocalStorageKeys.accessToken, + credentials.accessToken!, + ); + localStorage.setString(LocalStorageKeys.clientId, credentials.clientId!); + localStorage.setString( + LocalStorageKeys.clientSecret, + credentials.clientSecret!, + ); + }, + ); +}); diff --git a/lib/provider/UserPreferences.dart b/lib/provider/UserPreferences.dart index 2fc6543c..7e881377 100644 --- a/lib/provider/UserPreferences.dart +++ b/lib/provider/UserPreferences.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:hotkey_manager/hotkey_manager.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:spotube/models/LocalStorageKeys.dart'; @@ -110,3 +111,5 @@ class UserPreferences extends ChangeNotifier { notifyListeners(); } } + +var userPreferencesProvider = ChangeNotifierProvider((_) => UserPreferences()); diff --git a/pubspec.lock b/pubspec.lock index 77b0ed0c..dcccce79 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -195,6 +195,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + flutter_riverpod: + dependency: "direct main" + description: + name: flutter_riverpod + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" flutter_test: dependency: "direct dev" description: flutter @@ -338,13 +345,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.8.1" - nested: - dependency: transitive - description: - name: nested - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" oauth2: dependency: transitive description: @@ -457,13 +457,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.4" - provider: - dependency: "direct main" + riverpod: + dependency: transitive description: - name: provider + name: riverpod url: "https://pub.dartlang.org" source: hosted - version: "6.0.1" + version: "1.0.3" rxdart: dependency: transitive description: @@ -574,6 +574,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.10.0" + state_notifier: + dependency: transitive + description: + name: state_notifier + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.2+1" stream_channel: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 49b1828a..819d2389 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -37,7 +37,6 @@ dependencies: cached_network_image: ^3.2.0 html: ^0.15.0 http: ^0.13.4 - provider: ^6.0.1 shared_preferences: ^2.0.11 spotify: ^0.6.0 url_launcher: ^6.0.17 @@ -50,6 +49,7 @@ dependencies: path: ^1.8.0 path_provider: ^2.0.8 collection: ^1.15.0 + flutter_riverpod: ^1.0.3 dev_dependencies: flutter_test: