diff --git a/lib/collections/routes.dart b/lib/collections/routes.dart index ebd1e3b2..7f4efd56 100644 --- a/lib/collections/routes.dart +++ b/lib/collections/routes.dart @@ -1,6 +1,8 @@ import 'package:flutter/widgets.dart'; import 'package:go_router/go_router.dart'; import 'package:spotify/spotify.dart' hide Search; +import 'package:spotube/utils/platform.dart'; +import 'package:spotube/components/shared/spotube_page_route.dart'; import 'package:spotube/pages/album/album.dart'; import 'package:spotube/pages/artist/artist.dart'; import 'package:spotube/pages/genre/genres.dart'; @@ -12,9 +14,7 @@ import 'package:spotube/pages/player/player.dart'; import 'package:spotube/pages/playlist/playlist.dart'; import 'package:spotube/pages/root/root_app.dart'; import 'package:spotube/pages/search/search.dart'; -import 'package:spotube/components/shared/spotube_page_route.dart'; import 'package:spotube/pages/settings/settings.dart'; -import 'package:spotube/utils/platform.dart'; import 'package:spotube/pages/mobile_login/mobile_login.dart'; final rootNavigatorKey = GlobalKey(); diff --git a/lib/components/artist/artist_album_list.dart b/lib/components/artist/artist_album_list.dart index 564c3405..91fe2206 100644 --- a/lib/components/artist/artist_album_list.dart +++ b/lib/components/artist/artist_album_list.dart @@ -9,7 +9,7 @@ import 'package:spotube/components/shared/shimmers/shimmer_playbutton_card.dart' import 'package:spotube/components/shared/waypoint.dart'; import 'package:spotube/models/logger.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; class ArtistAlbumList extends HookConsumerWidget { final String artistId; @@ -24,7 +24,7 @@ class ArtistAlbumList extends HookConsumerWidget { Widget build(BuildContext context, ref) { final scrollController = useScrollController(); final albumsQuery = useInfiniteQuery( - job: artistAlbumsQueryJob(artistId), + job: Queries.artist.albumsOf(artistId), externalData: ref.watch(spotifyProvider), ); diff --git a/lib/components/genre/category_card.dart b/lib/components/genre/category_card.dart index 6add9e05..a0fe3268 100644 --- a/lib/components/genre/category_card.dart +++ b/lib/components/genre/category_card.dart @@ -10,7 +10,7 @@ import 'package:spotube/components/shared/waypoint.dart'; import 'package:spotube/components/playlist/playlist_card.dart'; import 'package:spotube/models/logger.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; class CategoryCard extends HookConsumerWidget { final Category category; @@ -28,7 +28,7 @@ class CategoryCard extends HookConsumerWidget { final scrollController = useScrollController(); final spotify = ref.watch(spotifyProvider); final playlistQuery = useInfiniteQuery( - job: categoryPlaylistsQueryJob(category.id!), + job: Queries.category.playlistsOf(category.id!), externalData: spotify, ); final hasNextPage = playlistQuery.pages.isEmpty diff --git a/lib/components/library/user_albums.dart b/lib/components/library/user_albums.dart index 6c9e0bd1..8d1d570c 100644 --- a/lib/components/library/user_albums.dart +++ b/lib/components/library/user_albums.dart @@ -7,7 +7,8 @@ import 'package:spotube/components/shared/shimmers/shimmer_playbutton_card.dart' import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart'; import 'package:spotube/provider/auth_provider.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; + import 'package:spotube/utils/type_conversion_utils.dart'; class UserAlbums extends HookConsumerWidget { @@ -20,7 +21,7 @@ class UserAlbums extends HookConsumerWidget { return const AnonymousFallback(); } final albumsQuery = useQuery( - job: currentUserAlbumsQueryJob, + job: Queries.album.ofMine, externalData: ref.watch(spotifyProvider), ); diff --git a/lib/components/library/user_artists.dart b/lib/components/library/user_artists.dart index d9e19483..b78cd5f2 100644 --- a/lib/components/library/user_artists.dart +++ b/lib/components/library/user_artists.dart @@ -9,7 +9,7 @@ import 'package:spotube/components/shared/waypoint.dart'; import 'package:spotube/components/artist/artist_card.dart'; import 'package:spotube/provider/auth_provider.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; class UserArtists extends HookConsumerWidget { const UserArtists({Key? key}) : super(key: key); @@ -21,7 +21,7 @@ class UserArtists extends HookConsumerWidget { return const AnonymousFallback(); } final artistQuery = useInfiniteQuery( - job: currentUserFollowingArtistsQueryJob, + job: Queries.artist.followedByMe, externalData: ref.watch(spotifyProvider), ); diff --git a/lib/components/library/user_playlists.dart b/lib/components/library/user_playlists.dart index 3de47a0b..de53d502 100644 --- a/lib/components/library/user_playlists.dart +++ b/lib/components/library/user_playlists.dart @@ -9,7 +9,7 @@ import 'package:spotube/components/playlist/playlist_card.dart'; import 'package:spotube/components/playlist/playlist_create_dialog.dart'; import 'package:spotube/provider/auth_provider.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; class UserPlaylists extends HookConsumerWidget { const UserPlaylists({Key? key}) : super(key: key); @@ -22,7 +22,7 @@ class UserPlaylists extends HookConsumerWidget { } final playlistsQuery = useQuery( - job: currentUserPlaylistsQueryJob, + job: Queries.playlist.ofMine, externalData: ref.watch(spotifyProvider), ); Image image = Image(); diff --git a/lib/components/playlist/playlist_create_dialog.dart b/lib/components/playlist/playlist_create_dialog.dart index db391751..1e112519 100644 --- a/lib/components/playlist/playlist_create_dialog.dart +++ b/lib/components/playlist/playlist_create_dialog.dart @@ -5,7 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:platform_ui/platform_ui.dart'; import 'package:spotube/components/root/sidebar.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; class PlaylistCreateDialog extends HookConsumerWidget { const PlaylistCreateDialog({Key? key}) : super(key: key); @@ -44,7 +44,7 @@ class PlaylistCreateDialog extends HookConsumerWidget { ) .then((_) { QueryBowl.of(context).refetchQueries([ - currentUserPlaylistsQueryJob.queryKey, + Queries.playlist.ofMine.queryKey, ]); Navigator.pop(context); }); diff --git a/lib/components/root/bottom_player.dart b/lib/components/root/bottom_player.dart index a739b8b5..87b3f027 100644 --- a/lib/components/root/bottom_player.dart +++ b/lib/components/root/bottom_player.dart @@ -3,7 +3,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:macos_ui/macos_ui.dart'; -import 'package:fluent_ui/fluent_ui.dart' as FluentUI; +import 'package:fluent_ui/fluent_ui.dart' as fluent_ui; import 'package:platform_ui/platform_ui.dart'; import 'package:spotube/components/player/player_actions.dart'; import 'package:spotube/components/player/player_overlay.dart'; @@ -17,10 +17,10 @@ import 'package:flutter/material.dart'; import 'package:spotube/provider/user_preferences_provider.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; -class Player extends HookConsumerWidget { - Player({Key? key}) : super(key: key); +class BottomPlayer extends HookConsumerWidget { + BottomPlayer({Key? key}) : super(key: key); - final logger = getLogger(Player); + final logger = getLogger(BottomPlayer); @override Widget build(BuildContext context, ref) { Playback playback = ref.watch(playbackProvider); @@ -59,7 +59,7 @@ class Player extends HookConsumerWidget { ? Colors.grey[800] : Colors.blueGrey[50], linux: Theme.of(context).backgroundColor, - windows: FluentUI.FluentTheme.maybeOf(context)?.micaBackgroundColor, + windows: fluent_ui.FluentTheme.maybeOf(context)?.micaBackgroundColor, ), ); diff --git a/lib/components/root/sidebar.dart b/lib/components/root/sidebar.dart index 91bbff0e..81614340 100644 --- a/lib/components/root/sidebar.dart +++ b/lib/components/root/sidebar.dart @@ -12,11 +12,12 @@ import 'package:spotube/hooks/use_breakpoints.dart'; import 'package:spotube/provider/auth_provider.dart'; import 'package:spotube/provider/downloader_provider.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; + import 'package:spotube/provider/user_preferences_provider.dart'; +import 'package:spotube/services/queries/queries.dart'; import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; -import 'package:fluent_ui/fluent_ui.dart' as FluentUI; +import 'package:fluent_ui/fluent_ui.dart' as fluent_ui; final sidebarExtendedStateProvider = StateProvider((ref) => null); @@ -153,8 +154,8 @@ class Sidebar extends HookConsumerWidget { ], ), windowsFooterItems: [ - FluentUI.PaneItemAction( - icon: const FluentUI.Icon(FluentUI.FluentIcons.settings), + fluent_ui.PaneItemAction( + icon: const fluent_ui.Icon(fluent_ui.FluentIcons.settings), onTap: () => goToSettings(context), ), ], @@ -180,7 +181,7 @@ class SidebarFooter extends HookConsumerWidget { child: HookBuilder( builder: (context) { final me = useQuery( - job: currentUserQueryJob, + job: Queries.user.me, externalData: ref.watch(spotifyProvider), ); final data = me.data; diff --git a/lib/components/shared/dialogs/playlist_add_track_dialog.dart b/lib/components/shared/dialogs/playlist_add_track_dialog.dart index 633dea19..584a7b0e 100644 --- a/lib/components/shared/dialogs/playlist_add_track_dialog.dart +++ b/lib/components/shared/dialogs/playlist_add_track_dialog.dart @@ -5,7 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:platform_ui/platform_ui.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; class PlaylistAddTrackDialog extends HookConsumerWidget { final List tracks; @@ -18,11 +18,11 @@ class PlaylistAddTrackDialog extends HookConsumerWidget { Widget build(BuildContext context, ref) { final spotify = ref.watch(spotifyProvider); final userPlaylists = useQuery( - job: currentUserPlaylistsQueryJob, + job: Queries.playlist.ofMine, externalData: spotify, ); final me = useQuery( - job: currentUserQueryJob, + job: Queries.user.me, externalData: spotify, ); final filteredPlaylists = userPlaylists.data?.where( diff --git a/lib/components/shared/heart_button.dart b/lib/components/shared/heart_button.dart index 8ec9b137..bee9cc60 100644 --- a/lib/components/shared/heart_button.dart +++ b/lib/components/shared/heart_button.dart @@ -8,7 +8,9 @@ import 'package:spotify/spotify.dart'; import 'package:spotube/hooks/use_palette_color.dart'; import 'package:spotube/provider/auth_provider.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/mutations/mutations.dart'; +import 'package:spotube/services/queries/queries.dart'; + import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:tuple/tuple.dart'; @@ -49,11 +51,11 @@ class HeartButton extends ConsumerWidget { Tuple3>, Query> useTrackToggleLike(Track track, WidgetRef ref) { - final me = useQuery( - job: currentUserQueryJob, externalData: ref.watch(spotifyProvider)); + final me = + useQuery(job: Queries.user.me, externalData: ref.watch(spotifyProvider)); final savedTracks = useQuery( - job: playlistTracksQueryJob("user-liked-tracks"), + job: Queries.playlist.tracksOf("user-liked-tracks"), externalData: ref.watch(spotifyProvider), ); @@ -63,7 +65,7 @@ Tuple3>, Query> final mounted = useIsMounted(); final toggleTrackLike = useMutation>( - job: toggleFavoriteTrackMutationJob(track.id!), + job: Mutations.track.toggleFavorite(track.id!), onMutate: (variable) { savedTracks.setQueryData( (oldData) { @@ -117,7 +119,7 @@ class TrackHeartButton extends HookConsumerWidget { @override Widget build(BuildContext context, ref) { final savedTracks = useQuery( - job: playlistTracksQueryJob("user-liked-tracks"), + job: Queries.playlist.tracksOf("user-liked-tracks"), externalData: ref.watch(spotifyProvider), ); final toggler = useTrackToggleLike(track, ref); @@ -150,22 +152,23 @@ class PlaylistHeartButton extends HookConsumerWidget { @override Widget build(BuildContext context, ref) { final me = useQuery( - job: currentUserQueryJob, + job: Queries.user.me, externalData: ref.watch(spotifyProvider), ); - final job = playlistIsFollowedQueryJob("${playlist.id}:${me.data?.id}"); + final job = + Queries.playlist.doesUserFollow("${playlist.id}:${me.data?.id}"); final isLikedQuery = useQuery( job: job, externalData: ref.watch(spotifyProvider), ); final togglePlaylistLike = useMutation>( - job: toggleFavoritePlaylistMutationJob(playlist.id!), + job: Mutations.playlist.toggleFavorite(playlist.id!), onData: (payload, variables, queryContext) { isLikedQuery.refetch(); QueryBowl.of(context) - .getQuery(currentUserPlaylistsQueryJob.queryKey) + .getQuery(Queries.playlist.ofMine.queryKey) ?.refetch(); }, ); @@ -182,8 +185,9 @@ class PlaylistHeartButton extends HookConsumerWidget { titleImage, ).dominantColor; - if (me.isLoading || !me.hasData) + if (me.isLoading || !me.hasData) { return const PlatformCircularProgressIndicator(); + } return HeartButton( isLiked: isLikedQuery.data ?? false, @@ -217,28 +221,29 @@ class AlbumHeartButton extends HookConsumerWidget { Widget build(BuildContext context, ref) { final spotify = ref.watch(spotifyProvider); final me = useQuery( - job: currentUserQueryJob, + job: Queries.user.me, externalData: spotify, ); final albumIsSaved = useQuery( - job: albumIsSavedForCurrentUserQueryJob(album.id!), + job: Queries.album.isSavedForMe(album.id!), externalData: spotify, ); final isLiked = albumIsSaved.data ?? false; final toggleAlbumLike = useMutation>( - job: toggleFavoriteAlbumMutationJob(album.id!), + job: Mutations.album.toggleFavorite(album.id!), onData: (payload, variables, queryContext) { albumIsSaved.refetch(); QueryBowl.of(context) - .getQuery(currentUserAlbumsQueryJob.queryKey) + .getQuery(Queries.album.ofMine.queryKey) ?.refetch(); }, ); - if (me.isLoading || !me.hasData) + if (me.isLoading || !me.hasData) { return const PlatformCircularProgressIndicator(); + } return HeartButton( isLiked: isLiked, diff --git a/lib/components/shared/track_table/track_tile.dart b/lib/components/shared/track_table/track_tile.dart index 4dc8d3a2..01c357fe 100644 --- a/lib/components/shared/track_table/track_tile.dart +++ b/lib/components/shared/track_table/track_tile.dart @@ -16,7 +16,9 @@ import 'package:spotube/models/logger.dart'; import 'package:spotube/provider/auth_provider.dart'; import 'package:spotube/provider/playback_provider.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/mutations/mutations.dart'; +import 'package:spotube/services/queries/queries.dart'; + import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:tuple/tuple.dart'; @@ -63,12 +65,12 @@ class TrackTile extends HookConsumerWidget { final spotify = ref.watch(spotifyProvider); final removingTrack = useState(null); final removeTrack = useMutation>( - job: removeTrackFromPlaylistMutationJob(playlistId ?? ""), + job: Mutations.playlist.removeTrackOf(playlistId ?? ""), onData: (payload, variables, ctx) { if (playlistId == null || !payload) return; QueryBowl.of(context) .getQuery( - playlistTracksQueryJob(playlistId!).queryKey, + Queries.playlist.tracksOf(playlistId!).queryKey, ) ?.refetch(); }, diff --git a/lib/pages/album/album.dart b/lib/pages/album/album.dart index 09ab6402..f85a4e05 100644 --- a/lib/pages/album/album.dart +++ b/lib/pages/album/album.dart @@ -8,12 +8,12 @@ import 'package:spotube/components/shared/heart_button.dart'; import 'package:spotube/components/shared/track_table/track_collection_view.dart'; import 'package:spotube/components/shared/track_table/tracks_table_view.dart'; import 'package:spotube/hooks/use_breakpoints.dart'; +import 'package:spotube/services/queries/queries.dart'; import 'package:spotube/utils/service_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/models/current_playlist.dart'; import 'package:spotube/provider/playback_provider.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; class AlbumPage extends HookConsumerWidget { final AlbumSimple album; @@ -56,7 +56,7 @@ class AlbumPage extends HookConsumerWidget { final SpotifyApi spotify = ref.watch(spotifyProvider); final tracksSnapshot = useQuery( - job: albumTracksQueryJob(album.id!), + job: Queries.album.tracksOf(album.id!), externalData: spotify, ); diff --git a/lib/pages/artist/artist.dart b/lib/pages/artist/artist.dart index df7e1357..c70893a5 100644 --- a/lib/pages/artist/artist.dart +++ b/lib/pages/artist/artist.dart @@ -18,7 +18,8 @@ import 'package:spotube/models/current_playlist.dart'; import 'package:spotube/models/logger.dart'; import 'package:spotube/provider/playback_provider.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; + import 'package:spotube/utils/primitive_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; @@ -60,7 +61,7 @@ class ArtistPage extends HookConsumerWidget { body: HookBuilder( builder: (context) { final artistsQuery = useQuery( - job: artistProfileQueryJob(artistId), + job: Queries.artist.get(artistId), externalData: spotify, ); @@ -130,8 +131,7 @@ class ArtistPage extends HookConsumerWidget { HookBuilder( builder: (context) { final isFollowingQuery = useQuery( - job: currentUserFollowsArtistQueryJob( - artistId), + job: Queries.artist.doIFollow(artistId), externalData: spotify, ); @@ -165,8 +165,8 @@ class ArtistPage extends HookConsumerWidget { ); } finally { QueryBowl.of(context).refetchQueries([ - currentUserFollowsArtistQueryJob( - artistId) + Queries.artist + .doIFollow(artistId) .queryKey, ]); } @@ -211,7 +211,7 @@ class ArtistPage extends HookConsumerWidget { HookBuilder( builder: (context) { final topTracksQuery = useQuery( - job: artistTopTracksQueryJob(artistId), + job: Queries.artist.topTracksOf(artistId), externalData: spotify, ); @@ -311,7 +311,7 @@ class ArtistPage extends HookConsumerWidget { HookBuilder( builder: (context) { final relatedArtists = useQuery( - job: artistRelatedArtistsQueryJob(artistId), + job: Queries.artist.relatedArtistsOf(artistId), externalData: spotify, ); diff --git a/lib/pages/genre/genres.dart b/lib/pages/genre/genres.dart index 857b7cc4..7657de1e 100644 --- a/lib/pages/genre/genres.dart +++ b/lib/pages/genre/genres.dart @@ -9,8 +9,9 @@ import 'package:spotube/components/shared/shimmers/shimmer_categories.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart'; import 'package:spotube/components/shared/waypoint.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; + import 'package:spotube/provider/user_preferences_provider.dart'; +import 'package:spotube/services/queries/queries.dart'; import 'package:spotube/utils/platform.dart'; class GenrePage extends HookConsumerWidget { @@ -24,7 +25,7 @@ class GenrePage extends HookConsumerWidget { userPreferencesProvider.select((s) => s.recommendationMarket), ); final categoriesQuery = useInfiniteQuery( - job: categoriesQueryJob, + job: Queries.category.list, externalData: { "spotify": spotify, "recommendationMarket": recommendationMarket, diff --git a/lib/pages/lyrics/genius_lyrics.dart b/lib/pages/lyrics/genius_lyrics.dart index bef6f91c..04465bce 100644 --- a/lib/pages/lyrics/genius_lyrics.dart +++ b/lib/pages/lyrics/genius_lyrics.dart @@ -7,8 +7,9 @@ import 'package:spotify/spotify.dart'; import 'package:spotube/components/shared/shimmers/shimmer_lyrics.dart'; import 'package:spotube/hooks/use_breakpoints.dart'; import 'package:spotube/provider/playback_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; + import 'package:spotube/provider/user_preferences_provider.dart'; +import 'package:spotube/services/queries/queries.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:tuple/tuple.dart'; @@ -23,7 +24,7 @@ class GeniusLyrics extends HookConsumerWidget { Widget build(BuildContext context, ref) { Playback playback = ref.watch(playbackProvider); final geniusLyricsQuery = useQuery( - job: geniusLyricsQueryJob, + job: Queries.lyrics.static, externalData: Tuple2( playback.track, ref.watch(userPreferencesProvider).geniusAccessToken, diff --git a/lib/pages/lyrics/synced_lyrics.dart b/lib/pages/lyrics/synced_lyrics.dart index 80c6023c..1cc114aa 100644 --- a/lib/pages/lyrics/synced_lyrics.dart +++ b/lib/pages/lyrics/synced_lyrics.dart @@ -13,7 +13,8 @@ import 'package:spotube/hooks/use_breakpoints.dart'; import 'package:spotube/hooks/use_synced_lyrics.dart'; import 'package:spotube/provider/playback_provider.dart'; import 'package:scroll_to_index/scroll_to_index.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; + import 'package:spotube/utils/type_conversion_utils.dart'; final lyricDelayState = StateProvider( @@ -33,7 +34,7 @@ class SyncedLyrics extends HookConsumerWidget { Widget build(BuildContext context, ref) { Playback playback = ref.watch(playbackProvider); final timedLyricsQuery = useQuery( - job: rentanadviserLyricsQueryJob, + job: Queries.lyrics.synced, externalData: playback.track, ); final lyricDelay = ref.watch(lyricDelayState); diff --git a/lib/pages/playlist/playlist.dart b/lib/pages/playlist/playlist.dart index 812b9681..3cafe3a5 100644 --- a/lib/pages/playlist/playlist.dart +++ b/lib/pages/playlist/playlist.dart @@ -12,7 +12,8 @@ import 'package:spotube/provider/playback_provider.dart'; import 'package:flutter/material.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; + import 'package:spotube/utils/service_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; @@ -61,10 +62,9 @@ class PlaylistView extends HookConsumerWidget { final breakpoint = useBreakpoints(); - final meSnapshot = - useQuery(job: currentUserQueryJob, externalData: spotify); + final meSnapshot = useQuery(job: Queries.user.me, externalData: spotify); final tracksSnapshot = useQuery( - job: playlistTracksQueryJob(playlist.id!), + job: Queries.playlist.tracksOf(playlist.id!), externalData: spotify, ); diff --git a/lib/pages/root/root_app.dart b/lib/pages/root/root_app.dart index 918d302a..0973e4ef 100644 --- a/lib/pages/root/root_app.dart +++ b/lib/pages/root/root_app.dart @@ -75,7 +75,7 @@ class RootApp extends HookConsumerWidget { bottomNavigationBar: Column( mainAxisSize: MainAxisSize.min, children: [ - Player(), + BottomPlayer(), SpotubeNavigationBar( selectedIndex: index.value, onSelectedIndexChanged: (selectedIndex) { diff --git a/lib/pages/search/search.dart b/lib/pages/search/search.dart index 35b80da0..4d3fb4f2 100644 --- a/lib/pages/search/search.dart +++ b/lib/pages/search/search.dart @@ -18,7 +18,8 @@ import 'package:spotube/models/current_playlist.dart'; import 'package:spotube/provider/auth_provider.dart'; import 'package:spotube/provider/playback_provider.dart'; import 'package:spotube/provider/spotify_provider.dart'; -import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/services/queries/queries.dart'; + import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/primitive_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; @@ -47,16 +48,16 @@ class SearchPage extends HookConsumerWidget { ); final searchTrack = useInfiniteQuery( - job: searchQueryJob(SearchType.track.key), + job: Queries.search.get(SearchType.track.key), externalData: getVariables()); final searchAlbum = useInfiniteQuery( - job: searchQueryJob(SearchType.album.key), + job: Queries.search.get(SearchType.album.key), externalData: getVariables()); final searchPlaylist = useInfiniteQuery( - job: searchQueryJob(SearchType.playlist.key), + job: Queries.search.get(SearchType.playlist.key), externalData: getVariables()); final searchArtist = useInfiniteQuery( - job: searchQueryJob(SearchType.artist.key), + job: Queries.search.get(SearchType.artist.key), externalData: getVariables()); void onSearch() { diff --git a/lib/provider/SpotifyRequests.dart b/lib/provider/SpotifyRequests.dart deleted file mode 100644 index 6162980a..00000000 --- a/lib/provider/SpotifyRequests.dart +++ /dev/null @@ -1,291 +0,0 @@ -import 'package:fl_query/fl_query.dart'; -import 'package:spotube/models/lyrics.dart'; -import 'package:spotube/models/spotube_track.dart'; -import 'package:spotify/spotify.dart'; -import 'package:collection/collection.dart'; -import 'package:spotube/utils/service_utils.dart'; -import 'package:spotube/utils/type_conversion_utils.dart'; -import 'package:tuple/tuple.dart'; - -final categoriesQueryJob = - InfiniteQueryJob, Map, int>( - queryKey: "categories-query", - initialParam: 0, - getNextPageParam: (lastPage, lastParam) => lastPage.nextOffset, - getPreviousPageParam: (lastPage, lastParam) => lastPage.nextOffset - 16, - refetchOnExternalDataChange: true, - task: (queryKey, pageParam, data) async { - final SpotifyApi spotify = data["spotify"] as SpotifyApi; - final String recommendationMarket = data["recommendationMarket"]; - final categories = await spotify.categories - .list(country: recommendationMarket) - .getPage(15, pageParam); - - return categories; - }, -); - -final categoryPlaylistsQueryJob = - InfiniteQueryJob.withVariableKey, SpotifyApi, int>( - preQueryKey: "category-playlists", - initialParam: 0, - getNextPageParam: (lastPage, lastParam) => lastPage.nextOffset, - getPreviousPageParam: (lastPage, lastParam) => lastPage.nextOffset - 6, - task: (queryKey, pageKey, spotify) { - final id = getVariable(queryKey); - return (id != "user-featured-playlists" - ? spotify.playlists.getByCategoryId(id) - : spotify.playlists.featured) - .getPage(5, pageKey); - }, -); - -final currentUserPlaylistsQueryJob = - QueryJob, SpotifyApi>( - queryKey: "current-user-playlists", - task: (_, spotify) { - return spotify.playlists.me.all(); - }, -); - -final currentUserAlbumsQueryJob = QueryJob, SpotifyApi>( - queryKey: "current-user-albums", - task: (_, spotify) { - return spotify.me.savedAlbums().all(); - }, -); - -final currentUserFollowingArtistsQueryJob = - InfiniteQueryJob, SpotifyApi, String>( - queryKey: "user-following-artists", - initialParam: "", - getNextPageParam: (lastPage, lastParam) => lastPage.after, - getPreviousPageParam: (lastPage, lastParam) => - lastPage.metadata.previous ?? "", - task: (queryKey, pageKey, spotify) { - return spotify.me.following(FollowingType.artist).getPage(15, pageKey); - }, -); - -final artistProfileQueryJob = QueryJob.withVariableKey( - preQueryKey: "artist-profile", - task: (queryKey, externalData) => - externalData.artists.get(getVariable(queryKey)), -); - -final artistTopTracksQueryJob = - QueryJob.withVariableKey, SpotifyApi>( - preQueryKey: "artist-top-track-query", - task: (queryKey, spotify) { - return spotify.artists.getTopTracks(getVariable(queryKey), "US"); - }, -); - -final artistAlbumsQueryJob = - InfiniteQueryJob.withVariableKey, SpotifyApi, int>( - preQueryKey: "artist-albums", - initialParam: 0, - getNextPageParam: (lastPage, lastParam) => lastPage.nextOffset, - getPreviousPageParam: (lastPage, lastParam) => lastPage.nextOffset - 6, - task: (queryKey, pageKey, spotify) { - final id = getVariable(queryKey); - return spotify.artists.albums(id).getPage(5, pageKey); - }, -); - -final artistRelatedArtistsQueryJob = - QueryJob.withVariableKey, SpotifyApi>( - preQueryKey: "artist-related-artist-query", - task: (queryKey, spotify) { - return spotify.artists.getRelatedArtists(getVariable(queryKey)); - }, -); - -final currentUserFollowsArtistQueryJob = - QueryJob.withVariableKey( - preQueryKey: "user-follows-artists-query", - task: (artistId, spotify) async { - final result = await spotify.me.isFollowing( - FollowingType.artist, - [getVariable(artistId)], - ); - return result.first; - }, -); - -final playlistTracksQueryJob = - QueryJob.withVariableKey, SpotifyApi>( - preQueryKey: "playlist-tracks", - task: (queryKey, spotify) { - final id = getVariable(queryKey); - return id != "user-liked-tracks" - ? spotify.playlists.getTracksByPlaylistId(id).all().then( - (value) => value.toList(), - ) - : spotify.tracks.me.saved.all().then( - (tracks) => tracks.map((e) => e.track!).toList(), - ); - }, -); - -final albumTracksQueryJob = - QueryJob.withVariableKey, SpotifyApi>( - preQueryKey: "album-tracks", - task: (queryKey, spotify) { - final id = getVariable(queryKey); - return spotify.albums.getTracks(id).all().then((value) => value.toList()); - }, -); - -final currentUserQueryJob = QueryJob( - queryKey: "current-user", - refetchOnExternalDataChange: true, - task: (_, spotify) async { - final me = await spotify.me.get(); - if (me.images == null || me.images?.isEmpty == true) { - me.images = [ - Image() - ..height = 50 - ..width = 50 - ..url = TypeConversionUtils.image_X_UrlString( - me.images, - placeholder: ImagePlaceholder.artist, - ), - ]; - } - return me; - }, -); - -final playlistIsFollowedQueryJob = QueryJob.withVariableKey( - preQueryKey: "playlist-is-followed", - task: (queryKey, spotify) { - final idMap = getVariable(queryKey).split(":"); - - return spotify.playlists.followedBy(idMap.first, [idMap.last]).then( - (value) => value.first, - ); - }, -); - -final albumIsSavedForCurrentUserQueryJob = - QueryJob.withVariableKey(task: (queryKey, spotify) { - return spotify.me - .isSavedAlbums([getVariable(queryKey)]).then((value) => value.first); -}); - -final searchQueryJob = InfiniteQueryJob.withVariableKey, - Tuple2, int>( - preQueryKey: "search-query", - initialParam: 0, - enabled: false, - getNextPageParam: (lastPage, lastParam) => - (lastPage.first.items?.length ?? 0) < 10 ? null : lastParam + 10, - getPreviousPageParam: (lastPage, lastParam) => lastParam - 10, - task: (queryKey, pageParam, variables) { - final queryString = variables.item1; - final spotify = variables.item2; - if (queryString.isEmpty) return []; - final searchType = getVariable(queryKey); - return spotify.search.get( - queryString, - types: [SearchType(searchType)], - ).getPage(10, pageParam); - }, -); - -final geniusLyricsQueryJob = QueryJob>( - queryKey: "genius-lyrics-query", - task: (_, externalData) async { - final currentTrack = externalData.item1; - final geniusAccessToken = externalData.item2; - if (currentTrack == null) { - return "“Give this player a track to play”\n- S'Challa"; - } - final lyrics = await ServiceUtils.getLyrics( - currentTrack.name!, - currentTrack.artists?.map((s) => s.name).whereNotNull().toList() ?? [], - apiKey: geniusAccessToken, - optimizeQuery: true, - ); - - if (lyrics == null) throw Exception("Unable find lyrics"); - return lyrics; - }, -); - -final rentanadviserLyricsQueryJob = QueryJob( - queryKey: "synced-lyrics", - task: (_, currentTrack) async { - if (currentTrack == null) throw "No track currently"; - - final timedLyrics = await ServiceUtils.getTimedLyrics(currentTrack); - if (timedLyrics == null) throw Exception("Unable to find lyrics"); - - return timedLyrics; - }, -); - -final toggleFavoriteTrackMutationJob = - MutationJob.withVariableKey>( - preMutationKey: "toggle-track-like", - task: (queryKey, externalData) async { - final trackId = getVariable(queryKey); - final spotify = externalData.item1; - final isLiked = externalData.item2; - - if (isLiked) { - await spotify.tracks.me.removeOne(trackId); - } else { - await spotify.tracks.me.saveOne(trackId); - } - return !isLiked; - }, -); - -final toggleFavoritePlaylistMutationJob = - MutationJob.withVariableKey>( - preMutationKey: "toggle-playlist-like", - task: (queryKey, externalData) async { - final playlistId = getVariable(queryKey); - final spotify = externalData.item1; - final isLiked = externalData.item2; - - if (isLiked) { - await spotify.playlists.unfollowPlaylist(playlistId); - } else { - await spotify.playlists.followPlaylist(playlistId); - } - return !isLiked; - }, -); - -final toggleFavoriteAlbumMutationJob = - MutationJob.withVariableKey>( - preMutationKey: "toggle-album-like", - task: (queryKey, externalData) async { - final albumId = getVariable(queryKey); - final spotify = externalData.item1; - final isLiked = externalData.item2; - - if (isLiked) { - await spotify.me.removeAlbums([albumId]); - } else { - await spotify.me.saveAlbums([albumId]); - } - return !isLiked; - }, -); - -final removeTrackFromPlaylistMutationJob = - MutationJob.withVariableKey>( - preMutationKey: "remove-track-from-playlist", - task: (queryKey, externalData) async { - final spotify = externalData.item1; - final playlistId = getVariable(queryKey); - final trackId = externalData.item2; - - await spotify.playlists.removeTracks([trackId], playlistId); - return true; - }, -); diff --git a/lib/services/mutations/album.dart b/lib/services/mutations/album.dart new file mode 100644 index 00000000..c93a1aa3 --- /dev/null +++ b/lib/services/mutations/album.dart @@ -0,0 +1,22 @@ +import 'package:fl_query/fl_query.dart'; +import 'package:spotify/spotify.dart'; +import 'package:tuple/tuple.dart'; + +class AlbumMutations { + final toggleFavorite = + MutationJob.withVariableKey>( + preMutationKey: "toggle-album-like", + task: (queryKey, externalData) async { + final albumId = getVariable(queryKey); + final spotify = externalData.item1; + final isLiked = externalData.item2; + + if (isLiked) { + await spotify.me.removeAlbums([albumId]); + } else { + await spotify.me.saveAlbums([albumId]); + } + return !isLiked; + }, + ); +} diff --git a/lib/services/mutations/mutations.dart b/lib/services/mutations/mutations.dart new file mode 100644 index 00000000..b61f1209 --- /dev/null +++ b/lib/services/mutations/mutations.dart @@ -0,0 +1,9 @@ +import 'package:spotube/services/mutations/album.dart'; +import 'package:spotube/services/mutations/playlist.dart'; +import 'package:spotube/services/mutations/track.dart'; + +abstract class Mutations { + static final playlist = PlaylistMutations(); + static final album = AlbumMutations(); + static final track = TrackMutations(); +} diff --git a/lib/services/mutations/playlist.dart b/lib/services/mutations/playlist.dart new file mode 100644 index 00000000..b5c3ba39 --- /dev/null +++ b/lib/services/mutations/playlist.dart @@ -0,0 +1,35 @@ +import 'package:fl_query/fl_query.dart'; +import 'package:spotify/spotify.dart'; +import 'package:tuple/tuple.dart'; + +class PlaylistMutations { + final toggleFavorite = + MutationJob.withVariableKey>( + preMutationKey: "toggle-playlist-like", + task: (queryKey, externalData) async { + final playlistId = getVariable(queryKey); + final spotify = externalData.item1; + final isLiked = externalData.item2; + + if (isLiked) { + await spotify.playlists.unfollowPlaylist(playlistId); + } else { + await spotify.playlists.followPlaylist(playlistId); + } + return !isLiked; + }, + ); + + final removeTrackOf = + MutationJob.withVariableKey>( + preMutationKey: "remove-track-from-playlist", + task: (queryKey, externalData) async { + final spotify = externalData.item1; + final playlistId = getVariable(queryKey); + final trackId = externalData.item2; + + await spotify.playlists.removeTracks([trackId], playlistId); + return true; + }, + ); +} diff --git a/lib/services/mutations/track.dart b/lib/services/mutations/track.dart new file mode 100644 index 00000000..5cbc59b3 --- /dev/null +++ b/lib/services/mutations/track.dart @@ -0,0 +1,22 @@ +import 'package:fl_query/fl_query.dart'; +import 'package:spotify/spotify.dart'; +import 'package:tuple/tuple.dart'; + +class TrackMutations { + final toggleFavorite = + MutationJob.withVariableKey>( + preMutationKey: "toggle-track-like", + task: (queryKey, externalData) async { + final trackId = getVariable(queryKey); + final spotify = externalData.item1; + final isLiked = externalData.item2; + + if (isLiked) { + await spotify.tracks.me.removeOne(trackId); + } else { + await spotify.tracks.me.saveOne(trackId); + } + return !isLiked; + }, + ); +} diff --git a/lib/services/queries/album.dart b/lib/services/queries/album.dart new file mode 100644 index 00000000..b6dae35f --- /dev/null +++ b/lib/services/queries/album.dart @@ -0,0 +1,25 @@ +import 'package:fl_query/fl_query.dart'; +import 'package:spotify/spotify.dart'; + +class AlbumQueries { + final ofMine = QueryJob, SpotifyApi>( + queryKey: "current-user-albums", + task: (_, spotify) { + return spotify.me.savedAlbums().all(); + }, + ); + + final tracksOf = QueryJob.withVariableKey, SpotifyApi>( + preQueryKey: "album-tracks", + task: (queryKey, spotify) { + final id = getVariable(queryKey); + return spotify.albums.getTracks(id).all().then((value) => value.toList()); + }, + ); + + final isSavedForMe = + QueryJob.withVariableKey(task: (queryKey, spotify) { + return spotify.me + .isSavedAlbums([getVariable(queryKey)]).then((value) => value.first); + }); +} diff --git a/lib/services/queries/artist.dart b/lib/services/queries/artist.dart new file mode 100644 index 00000000..e0b9e7ec --- /dev/null +++ b/lib/services/queries/artist.dart @@ -0,0 +1,59 @@ +import 'package:fl_query/fl_query.dart'; +import 'package:spotify/spotify.dart'; + +class ArtistQueries { + final get = QueryJob.withVariableKey( + preQueryKey: "artist-profile", + task: (queryKey, externalData) => + externalData.artists.get(getVariable(queryKey)), + ); + + final followedByMe = InfiniteQueryJob, SpotifyApi, String>( + queryKey: "user-following-artists", + initialParam: "", + getNextPageParam: (lastPage, lastParam) => lastPage.after, + getPreviousPageParam: (lastPage, lastParam) => + lastPage.metadata.previous ?? "", + task: (queryKey, pageKey, spotify) { + return spotify.me.following(FollowingType.artist).getPage(15, pageKey); + }, + ); + + final doIFollow = QueryJob.withVariableKey( + preQueryKey: "user-follows-artists-query", + task: (artistId, spotify) async { + final result = await spotify.me.isFollowing( + FollowingType.artist, + [getVariable(artistId)], + ); + return result.first; + }, + ); + + final topTracksOf = QueryJob.withVariableKey, SpotifyApi>( + preQueryKey: "artist-top-track-query", + task: (queryKey, spotify) { + return spotify.artists.getTopTracks(getVariable(queryKey), "US"); + }, + ); + + final albumsOf = + InfiniteQueryJob.withVariableKey, SpotifyApi, int>( + preQueryKey: "artist-albums", + initialParam: 0, + getNextPageParam: (lastPage, lastParam) => lastPage.nextOffset, + getPreviousPageParam: (lastPage, lastParam) => lastPage.nextOffset - 6, + task: (queryKey, pageKey, spotify) { + final id = getVariable(queryKey); + return spotify.artists.albums(id).getPage(5, pageKey); + }, + ); + + final relatedArtistsOf = + QueryJob.withVariableKey, SpotifyApi>( + preQueryKey: "artist-related-artist-query", + task: (queryKey, spotify) { + return spotify.artists.getRelatedArtists(getVariable(queryKey)); + }, + ); +} diff --git a/lib/services/queries/category.dart b/lib/services/queries/category.dart new file mode 100644 index 00000000..772b0f93 --- /dev/null +++ b/lib/services/queries/category.dart @@ -0,0 +1,36 @@ +import 'package:fl_query/fl_query.dart'; +import 'package:spotify/spotify.dart'; + +class CategoryQueries { + final list = InfiniteQueryJob, Map, int>( + queryKey: "categories-query", + initialParam: 0, + getNextPageParam: (lastPage, lastParam) => lastPage.nextOffset, + getPreviousPageParam: (lastPage, lastParam) => lastPage.nextOffset - 16, + refetchOnExternalDataChange: true, + task: (queryKey, pageParam, data) async { + final SpotifyApi spotify = data["spotify"] as SpotifyApi; + final String recommendationMarket = data["recommendationMarket"]; + final categories = await spotify.categories + .list(country: recommendationMarket) + .getPage(15, pageParam); + + return categories; + }, + ); + + final playlistsOf = + InfiniteQueryJob.withVariableKey, SpotifyApi, int>( + preQueryKey: "category-playlists", + initialParam: 0, + getNextPageParam: (lastPage, lastParam) => lastPage.nextOffset, + getPreviousPageParam: (lastPage, lastParam) => lastPage.nextOffset - 6, + task: (queryKey, pageKey, spotify) { + final id = getVariable(queryKey); + return (id != "user-featured-playlists" + ? spotify.playlists.getByCategoryId(id) + : spotify.playlists.featured) + .getPage(5, pageKey); + }, + ); +} diff --git a/lib/services/queries/lyrics.dart b/lib/services/queries/lyrics.dart new file mode 100644 index 00000000..eb5f9712 --- /dev/null +++ b/lib/services/queries/lyrics.dart @@ -0,0 +1,41 @@ +import 'package:collection/collection.dart'; +import 'package:fl_query/fl_query.dart'; +import 'package:spotify/spotify.dart'; +import 'package:spotube/models/lyrics.dart'; +import 'package:spotube/models/spotube_track.dart'; +import 'package:spotube/utils/service_utils.dart'; +import 'package:tuple/tuple.dart'; + +class LyricsQueries { + final static = QueryJob>( + queryKey: "genius-lyrics-query", + task: (_, externalData) async { + final currentTrack = externalData.item1; + final geniusAccessToken = externalData.item2; + if (currentTrack == null) { + return "“Give this player a track to play”\n- S'Challa"; + } + final lyrics = await ServiceUtils.getLyrics( + currentTrack.name!, + currentTrack.artists?.map((s) => s.name).whereNotNull().toList() ?? [], + apiKey: geniusAccessToken, + optimizeQuery: true, + ); + + if (lyrics == null) throw Exception("Unable find lyrics"); + return lyrics; + }, + ); + + final synced = QueryJob( + queryKey: "synced-lyrics", + task: (_, currentTrack) async { + if (currentTrack == null) throw "No track currently"; + + final timedLyrics = await ServiceUtils.getTimedLyrics(currentTrack); + if (timedLyrics == null) throw Exception("Unable to find lyrics"); + + return timedLyrics; + }, + ); +} diff --git a/lib/services/queries/playlist.dart b/lib/services/queries/playlist.dart new file mode 100644 index 00000000..e263e705 --- /dev/null +++ b/lib/services/queries/playlist.dart @@ -0,0 +1,36 @@ +import 'package:fl_query/fl_query.dart'; +import 'package:spotify/spotify.dart'; + +class PlaylistQueries { + final doesUserFollow = QueryJob.withVariableKey( + preQueryKey: "playlist-is-followed", + task: (queryKey, spotify) { + final idMap = getVariable(queryKey).split(":"); + + return spotify.playlists.followedBy(idMap.first, [idMap.last]).then( + (value) => value.first, + ); + }, + ); + + final ofMine = QueryJob, SpotifyApi>( + queryKey: "current-user-playlists", + task: (_, spotify) { + return spotify.playlists.me.all(); + }, + ); + + final tracksOf = QueryJob.withVariableKey, SpotifyApi>( + preQueryKey: "playlist-tracks", + task: (queryKey, spotify) { + final id = getVariable(queryKey); + return id != "user-liked-tracks" + ? spotify.playlists.getTracksByPlaylistId(id).all().then( + (value) => value.toList(), + ) + : spotify.tracks.me.saved.all().then( + (tracks) => tracks.map((e) => e.track!).toList(), + ); + }, + ); +} diff --git a/lib/services/queries/queries.dart b/lib/services/queries/queries.dart new file mode 100644 index 00000000..25ae9c81 --- /dev/null +++ b/lib/services/queries/queries.dart @@ -0,0 +1,17 @@ +import 'package:spotube/services/queries/album.dart'; +import 'package:spotube/services/queries/artist.dart'; +import 'package:spotube/services/queries/category.dart'; +import 'package:spotube/services/queries/lyrics.dart'; +import 'package:spotube/services/queries/playlist.dart'; +import 'package:spotube/services/queries/search.dart'; +import 'package:spotube/services/queries/user.dart'; + +abstract class Queries { + static final album = AlbumQueries(); + static final artist = ArtistQueries(); + static final category = CategoryQueries(); + static final lyrics = LyricsQueries(); + static final playlist = PlaylistQueries(); + static final search = SearchQueries(); + static final user = UserQueries(); +} diff --git a/lib/services/queries/search.dart b/lib/services/queries/search.dart new file mode 100644 index 00000000..721349ca --- /dev/null +++ b/lib/services/queries/search.dart @@ -0,0 +1,25 @@ +import 'package:fl_query/fl_query.dart'; +import 'package:spotify/spotify.dart'; +import 'package:tuple/tuple.dart'; + +class SearchQueries { + final get = InfiniteQueryJob.withVariableKey, + Tuple2, int>( + preQueryKey: "search-query", + initialParam: 0, + enabled: false, + getNextPageParam: (lastPage, lastParam) => + (lastPage.first.items?.length ?? 0) < 10 ? null : lastParam + 10, + getPreviousPageParam: (lastPage, lastParam) => lastParam - 10, + task: (queryKey, pageParam, variables) { + final queryString = variables.item1; + final spotify = variables.item2; + if (queryString.isEmpty) return []; + final searchType = getVariable(queryKey); + return spotify.search.get( + queryString, + types: [SearchType(searchType)], + ).getPage(10, pageParam); + }, + ); +} diff --git a/lib/services/queries/user.dart b/lib/services/queries/user.dart new file mode 100644 index 00000000..29485598 --- /dev/null +++ b/lib/services/queries/user.dart @@ -0,0 +1,25 @@ +import 'package:fl_query/fl_query.dart'; +import 'package:spotify/spotify.dart'; +import 'package:spotube/utils/type_conversion_utils.dart'; + +class UserQueries { + final me = QueryJob( + queryKey: "current-user", + refetchOnExternalDataChange: true, + task: (_, spotify) async { + final me = await spotify.me.get(); + if (me.images == null || me.images?.isEmpty == true) { + me.images = [ + Image() + ..height = 50 + ..width = 50 + ..url = TypeConversionUtils.image_X_UrlString( + me.images, + placeholder: ImagePlaceholder.artist, + ), + ]; + } + return me; + }, + ); +}