mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
feat: playlist create support for generated playlist
This commit is contained in:
parent
51e427e83c
commit
91c72f9ec9
@ -98,7 +98,7 @@ class UserPlaylists extends HookConsumerWidget {
|
||||
Row(
|
||||
children: [
|
||||
const SizedBox(width: 10),
|
||||
const PlaylistCreateDialog(),
|
||||
const PlaylistCreateDialogButton(),
|
||||
const SizedBox(width: 10),
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(SpotubeIcons.magic),
|
||||
|
@ -10,13 +10,16 @@ import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/provider/spotify_provider.dart';
|
||||
|
||||
class PlaylistCreateDialog extends HookConsumerWidget {
|
||||
const PlaylistCreateDialog({Key? key}) : super(key: key);
|
||||
/// Track ids to add to the playlist
|
||||
final List<String> trackIds;
|
||||
const PlaylistCreateDialog({
|
||||
Key? key,
|
||||
this.trackIds = const [],
|
||||
}) : super(key: key);
|
||||
|
||||
showPlaylistDialog(BuildContext context, SpotifyApi spotify) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return HookBuilder(builder: (context) {
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final spotify = ref.watch(spotifyProvider);
|
||||
final playlistName = useTextEditingController();
|
||||
final description = useTextEditingController();
|
||||
final public = useState(false);
|
||||
@ -24,22 +27,28 @@ class PlaylistCreateDialog extends HookConsumerWidget {
|
||||
final client = useQueryClient();
|
||||
final navigator = Navigator.of(context);
|
||||
|
||||
onCreate() async {
|
||||
Future<void> onCreate() async {
|
||||
if (playlistName.text.isEmpty) return;
|
||||
final me = await spotify.me.get();
|
||||
await spotify.playlists.createPlaylist(
|
||||
final playlist = await spotify.playlists.createPlaylist(
|
||||
me.id!,
|
||||
playlistName.text,
|
||||
collaborative: collaborative.value,
|
||||
public: public.value,
|
||||
description: description.text,
|
||||
);
|
||||
if (trackIds.isNotEmpty) {
|
||||
await spotify.playlists.addTracks(
|
||||
trackIds.map((id) => "spotify:track:$id").toList(),
|
||||
playlist.id!,
|
||||
);
|
||||
}
|
||||
await client
|
||||
.getQuery(
|
||||
"current-user-playlists",
|
||||
)
|
||||
?.refresh();
|
||||
navigator.pop();
|
||||
navigator.pop(playlist);
|
||||
}
|
||||
|
||||
return AlertDialog(
|
||||
@ -94,8 +103,16 @@ class PlaylistCreateDialog extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
class PlaylistCreateDialogButton extends HookConsumerWidget {
|
||||
const PlaylistCreateDialogButton({Key? key}) : super(key: key);
|
||||
|
||||
showPlaylistDialog(BuildContext context, SpotifyApi spotify) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => const PlaylistCreateDialog(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -217,5 +217,9 @@
|
||||
"min": "Min",
|
||||
"max": "Max",
|
||||
"target": "Target",
|
||||
"moderate": "Moderate"
|
||||
"moderate": "Moderate",
|
||||
"deselect_all": "Deselect All",
|
||||
"select_all": "Select All",
|
||||
"generating_playlist": "Generating your custom playlist...",
|
||||
"selected_count_tracks": "Selected {count} tracks"
|
||||
}
|
@ -454,7 +454,11 @@ class PlaylistGeneratorPage extends HookConsumerWidget {
|
||||
FilledButton.icon(
|
||||
icon: const Icon(SpotubeIcons.magic),
|
||||
label: Text(context.l10n.generate_playlist),
|
||||
onPressed: () {
|
||||
onPressed: artists.value.isEmpty &&
|
||||
tracks.value.isEmpty &&
|
||||
genres.value.isEmpty
|
||||
? null
|
||||
: () {
|
||||
final PlaylistGenerateResultRouteState routeState = (
|
||||
seeds: (
|
||||
artists: artists.value.map((a) => a.id!).toList(),
|
||||
|
@ -1,9 +1,12 @@
|
||||
import 'package:fl_query_hooks/fl_query_hooks.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/collections/spotube_icons.dart';
|
||||
import 'package:spotube/components/library/playlist_generate/simple_track_tile.dart';
|
||||
import 'package:spotube/components/playlist/playlist_create_dialog.dart';
|
||||
import 'package:spotube/components/shared/page_window_title_bar.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
||||
@ -27,6 +30,7 @@ class PlaylistGenerateResultPage extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final router = GoRouter.of(context);
|
||||
final playlistNotifier = ref.watch(ProxyPlaylistNotifier.notifier);
|
||||
final (:seeds, :parameters, :limit, :market) = state;
|
||||
|
||||
@ -62,13 +66,13 @@ class PlaylistGenerateResultPage extends HookConsumerWidget {
|
||||
child: Scaffold(
|
||||
appBar: const PageWindowTitleBar(leading: BackButton()),
|
||||
body: generatedPlaylist.isLoading
|
||||
? const Center(
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
Text("Generating your custom playlist..."),
|
||||
const CircularProgressIndicator(),
|
||||
Text(context.l10n.generating_playlist),
|
||||
],
|
||||
),
|
||||
)
|
||||
@ -128,8 +132,23 @@ class PlaylistGenerateResultPage extends HookConsumerWidget {
|
||||
FilledButton.tonalIcon(
|
||||
icon: const Icon(SpotubeIcons.addFilled),
|
||||
label: Text(context.l10n.create_a_playlist),
|
||||
onPressed:
|
||||
selectedTracks.value.isEmpty ? null : () {},
|
||||
onPressed: selectedTracks.value.isEmpty
|
||||
? null
|
||||
: () async {
|
||||
final playlist = await showDialog<Playlist>(
|
||||
context: context,
|
||||
builder: (context) => PlaylistCreateDialog(
|
||||
trackIds: selectedTracks.value,
|
||||
),
|
||||
);
|
||||
|
||||
if (playlist != null) {
|
||||
router.go(
|
||||
'/playlist/${playlist.id}',
|
||||
extra: playlist,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
FilledButton.tonalIcon(
|
||||
icon: const Icon(SpotubeIcons.playlistAdd),
|
||||
@ -141,9 +160,15 @@ class PlaylistGenerateResultPage extends HookConsumerWidget {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
if (generatedPlaylist.data != null)
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: ElevatedButton.icon(
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
context.l10n.selected_count_tracks(
|
||||
selectedTracks.value.length,
|
||||
),
|
||||
),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
if (isAllTrackSelected) {
|
||||
selectedTracks.value = [];
|
||||
@ -156,9 +181,12 @@ class PlaylistGenerateResultPage extends HookConsumerWidget {
|
||||
},
|
||||
icon: const Icon(SpotubeIcons.selectionCheck),
|
||||
label: Text(
|
||||
isAllTrackSelected ? "Deselect all" : "Select all",
|
||||
isAllTrackSelected
|
||||
? context.l10n.deselect_all
|
||||
: context.l10n.select_all,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Card(
|
||||
|
Loading…
Reference in New Issue
Block a user