mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-05-09 00:34:36 +00:00
feat: use provider in add track dialog
This commit is contained in:
parent
82802fef2c
commit
d2a9ff6652
@ -1,4 +1,3 @@
|
|||||||
import 'package:fl_query_hooks/fl_query_hooks.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
@ -8,8 +7,7 @@ import 'package:spotify/spotify.dart';
|
|||||||
import 'package:spotube/components/playlist/playlist_create_dialog.dart';
|
import 'package:spotube/components/playlist/playlist_create_dialog.dart';
|
||||||
import 'package:spotube/components/shared/image/universal_image.dart';
|
import 'package:spotube/components/shared/image/universal_image.dart';
|
||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/provider/spotify_provider.dart';
|
import 'package:spotube/provider/spotify/spotify.dart';
|
||||||
import 'package:spotube/services/queries/queries.dart';
|
|
||||||
import 'package:spotube/utils/type_conversion_utils.dart';
|
import 'package:spotube/utils/type_conversion_utils.dart';
|
||||||
|
|
||||||
class PlaylistAddTrackDialog extends HookConsumerWidget {
|
class PlaylistAddTrackDialog extends HookConsumerWidget {
|
||||||
@ -25,27 +23,34 @@ class PlaylistAddTrackDialog extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final ThemeData(:textTheme) = Theme.of(context);
|
final ThemeData(:textTheme) = Theme.of(context);
|
||||||
final spotify = ref.watch(spotifyProvider);
|
final userPlaylists = ref.watch(favoritePlaylistsProvider);
|
||||||
final userPlaylists = useQueries.playlist.ofMineAll(ref);
|
final favoritePlaylistsNotifier =
|
||||||
|
ref.watch(favoritePlaylistsProvider.notifier);
|
||||||
|
|
||||||
final me = useQueries.user.me(ref);
|
final me = ref.watch(meProvider);
|
||||||
|
|
||||||
final filteredPlaylists = useMemoized(
|
final filteredPlaylists = useMemoized(
|
||||||
() =>
|
() =>
|
||||||
userPlaylists.data
|
userPlaylists.asData?.value.items
|
||||||
?.where(
|
.where(
|
||||||
(playlist) =>
|
(playlist) =>
|
||||||
playlist.owner?.id != null &&
|
playlist.owner?.id != null &&
|
||||||
playlist.owner!.id == me.data?.id &&
|
playlist.owner!.id == me.asData?.value.id &&
|
||||||
playlist.id != openFromPlaylist,
|
playlist.id != openFromPlaylist,
|
||||||
)
|
)
|
||||||
.toList() ??
|
.toList() ??
|
||||||
[],
|
[],
|
||||||
[userPlaylists.data, me.data?.id, openFromPlaylist],
|
[userPlaylists.asData?.value, me.asData?.value.id, openFromPlaylist],
|
||||||
);
|
);
|
||||||
|
|
||||||
final playlistsCheck = useState(<String, bool>{});
|
final playlistsCheck = useState(<String, bool>{});
|
||||||
final queryClient = useQueryClient();
|
|
||||||
|
useEffect(() {
|
||||||
|
if (userPlaylists.asData?.value != null) {
|
||||||
|
favoritePlaylistsNotifier.fetchAll();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, [userPlaylists.asData?.value]);
|
||||||
|
|
||||||
Future<void> onAdd() async {
|
Future<void> onAdd() async {
|
||||||
final selectedPlaylists = playlistsCheck.value.entries
|
final selectedPlaylists = playlistsCheck.value.entries
|
||||||
@ -54,21 +59,12 @@ class PlaylistAddTrackDialog extends HookConsumerWidget {
|
|||||||
|
|
||||||
await Future.wait(
|
await Future.wait(
|
||||||
selectedPlaylists.map(
|
selectedPlaylists.map(
|
||||||
(playlistId) => spotify.playlists.addTracks(
|
(playlistId) => favoritePlaylistsNotifier.addTracks(
|
||||||
tracks
|
playlistId,
|
||||||
.map(
|
tracks.map((e) => e.id!).toList(),
|
||||||
(track) => track.uri!,
|
),
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
playlistId),
|
|
||||||
),
|
),
|
||||||
).then((_) => Navigator.pop(context, true));
|
).then((_) => Navigator.pop(context, true));
|
||||||
|
|
||||||
await queryClient.refreshQueries(
|
|
||||||
selectedPlaylists
|
|
||||||
.map((playlistId) => "playlist-tracks/$playlistId")
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
|
|||||||
@ -72,6 +72,19 @@ class FavoritePlaylistsNotifier
|
|||||||
|
|
||||||
ref.invalidate(isFavoritePlaylistProvider(playlist.id!));
|
ref.invalidate(isFavoritePlaylistProvider(playlist.id!));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> addTracks(String playlistId, List<String> trackIds) async {
|
||||||
|
if (state.value == null) return;
|
||||||
|
|
||||||
|
final spotify = ref.read(spotifyProvider);
|
||||||
|
|
||||||
|
await spotify.playlists.addTracks(
|
||||||
|
trackIds.map((id) => 'spotify:track:$id').toList(),
|
||||||
|
playlistId,
|
||||||
|
);
|
||||||
|
|
||||||
|
ref.invalidate(playlistTracksProvider(playlistId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final favoritePlaylistsProvider =
|
final favoritePlaylistsProvider =
|
||||||
@ -79,13 +92,6 @@ final favoritePlaylistsProvider =
|
|||||||
() => FavoritePlaylistsNotifier(),
|
() => FavoritePlaylistsNotifier(),
|
||||||
);
|
);
|
||||||
|
|
||||||
final allFavoritePlaylistsProvider = FutureProvider<List<PlaylistSimple>>(
|
|
||||||
(ref) async {
|
|
||||||
final spotify = ref.watch(spotifyProvider);
|
|
||||||
return (await spotify.playlists.me.all()).toList();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
final isFavoritePlaylistProvider = FutureProvider.family<bool, String>(
|
final isFavoritePlaylistProvider = FutureProvider.family<bool, String>(
|
||||||
(ref, id) async {
|
(ref, id) async {
|
||||||
final spotify = ref.watch(spotifyProvider);
|
final spotify = ref.watch(spotifyProvider);
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class PlaylistNotifier extends FamilyAsyncNotifier<Playlist, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> create(PlaylistInput input, [ValueChanged? onError]) async {
|
Future<void> create(PlaylistInput input, [ValueChanged? onError]) async {
|
||||||
if (state is AsyncData || state is AsyncLoading) return;
|
if (state is AsyncLoading) return;
|
||||||
state = const AsyncLoading();
|
state = const AsyncLoading();
|
||||||
|
|
||||||
final spotify = ref.read(spotifyProvider);
|
final spotify = ref.read(spotifyProvider);
|
||||||
@ -51,19 +51,6 @@ class PlaylistNotifier extends FamilyAsyncNotifier<Playlist, String> {
|
|||||||
ref.invalidate(favoritePlaylistsProvider);
|
ref.invalidate(favoritePlaylistsProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addTracks(List<String> trackIds) async {
|
|
||||||
if (state.value == null) return;
|
|
||||||
|
|
||||||
final spotify = ref.read(spotifyProvider);
|
|
||||||
|
|
||||||
await spotify.playlists.addTracks(
|
|
||||||
trackIds.map((id) => 'spotify:track:$id').toList(),
|
|
||||||
state.value!.id!,
|
|
||||||
);
|
|
||||||
|
|
||||||
ref.invalidate(playlistTracksProvider(state.value!.id!));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> modify(PlaylistInput input, [ValueChanged? onError]) async {
|
Future<void> modify(PlaylistInput input, [ValueChanged? onError]) async {
|
||||||
if (state.value == null) return;
|
if (state.value == null) return;
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,30 @@ abstract class PaginatedAsyncNotifier<K, T extends BasePaginatedState<K, int>>
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<K>> fetchAll() async {
|
||||||
|
if (state.value == null) return [];
|
||||||
|
if (!state.value!.hasMore) return state.value!.items;
|
||||||
|
|
||||||
|
bool hasMore = true;
|
||||||
|
while (hasMore) {
|
||||||
|
await update((state) async {
|
||||||
|
final items = await fetch(
|
||||||
|
state.offset + state.limit,
|
||||||
|
state.limit,
|
||||||
|
);
|
||||||
|
|
||||||
|
hasMore = items.length == state.limit;
|
||||||
|
return state.copyWith(
|
||||||
|
items: [...state.items, ...items],
|
||||||
|
offset: state.offset + state.limit,
|
||||||
|
hasMore: hasMore,
|
||||||
|
) as T;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.value!.items;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class CursorPaginatedAsyncNotifier<K,
|
abstract class CursorPaginatedAsyncNotifier<K,
|
||||||
@ -49,6 +73,27 @@ abstract class CursorPaginatedAsyncNotifier<K,
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<K>> fetchAll() async {
|
||||||
|
if (state.value == null) return [];
|
||||||
|
if (!state.value!.hasMore) return state.value!.items;
|
||||||
|
|
||||||
|
bool hasMore = true;
|
||||||
|
while (hasMore) {
|
||||||
|
await update((state) async {
|
||||||
|
final items = await fetch(state.offset, state.limit);
|
||||||
|
|
||||||
|
hasMore = items.$1.length == state.limit;
|
||||||
|
return state.copyWith(
|
||||||
|
items: [...state.items, ...items.$1],
|
||||||
|
offset: items.$2,
|
||||||
|
hasMore: hasMore,
|
||||||
|
) as T;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.value!.items;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class FamilyPaginatedAsyncNotifier<
|
abstract class FamilyPaginatedAsyncNotifier<
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user