feat: add generated to playlist(s)

This commit is contained in:
Kingkor Roy Tirtho 2023-06-11 18:56:39 +06:00
parent 3724bd5a10
commit c91d8c8efa
4 changed files with 88 additions and 34 deletions

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.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';
class ConfirmDownloadDialog extends StatelessWidget { class ConfirmDownloadDialog extends StatelessWidget {
const ConfirmDownloadDialog({Key? key}) : super(key: key); const ConfirmDownloadDialog({Key? key}) : super(key: key);
@ -11,10 +12,10 @@ class ConfirmDownloadDialog extends StatelessWidget {
title: Padding( title: Padding(
padding: const EdgeInsets.all(15), padding: const EdgeInsets.all(15),
child: Row( child: Row(
children: const [ children: [
Text("Are you sure?"), Text(context.l10n.are_you_sure),
SizedBox(width: 10), const SizedBox(width: 10),
UniversalImage( const UniversalImage(
path: path:
"https://c.tenor.com/kHcmsxlKHEAAAAAM/rock-one-eyebrow-raised-rock-staring.gif", "https://c.tenor.com/kHcmsxlKHEAAAAAM/rock-one-eyebrow-raised-rock-staring.gif",
height: 40, height: 40,
@ -29,39 +30,37 @@ class ConfirmDownloadDialog extends StatelessWidget {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: const [ children: [
Text( Text(
"If you download all Tracks at bulk you're clearly pirating Music & causing damage to the creative society of Music. I hope you are aware of this. Always, try respecting & supporting Artist's hard work", context.l10n.download_warning,
textAlign: TextAlign.justify, textAlign: TextAlign.justify,
), ),
SizedBox(height: 10), const SizedBox(height: 10),
Text( Text(
"BTW, your IP can get blocked on YouTube due excessive download requests than usual. IP block means you can't use YouTube (even if you're logged in) for at least 2-3 months from that IP device. And Spotube doesn't hold any responsibility if this ever happens", context.l10n.download_ip_ban_warning,
style: TextStyle( style: const TextStyle(
color: Colors.red, color: Colors.red,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
textAlign: TextAlign.justify, textAlign: TextAlign.justify,
), ),
SizedBox(height: 10), const SizedBox(height: 10),
Text( Text(
"By clicking 'accept' you agree to following terms:", context.l10n.by_clicking_accept_terms,
), ),
SizedBox(height: 10), const SizedBox(height: 10),
BulletPoint("I know I'm pirating Music. I'm bad"), BulletPoint(context.l10n.download_agreement_1),
SizedBox(height: 10), const SizedBox(height: 10),
BulletPoint( BulletPoint(context.l10n.download_agreement_2),
"I'll support the Artist wherever I can and I'm only doing this because I don't have money to buy their art"), const SizedBox(height: 10),
SizedBox(height: 10), BulletPoint(context.l10n.download_agreement_3),
BulletPoint(
"I'm completely aware that my IP can get blocked on YouTube & I don't hold Spotube or his owners/contributors responsible for any accidents caused by my current action"),
], ],
), ),
), ),
), ),
actions: [ actions: [
OutlinedButton( OutlinedButton(
child: const Text("Decline"), child: Text(context.l10n.decline),
onPressed: () { onPressed: () {
Navigator.pop(context, false); Navigator.pop(context, false);
}, },
@ -72,7 +71,7 @@ class ConfirmDownloadDialog extends StatelessWidget {
backgroundColor: Colors.red, backgroundColor: Colors.red,
), ),
onPressed: () => Navigator.of(context).pop(true), onPressed: () => Navigator.of(context).pop(true),
child: const Text("Accept"), child: Text(context.l10n.accept),
), ),
], ],
); );

View File

@ -3,8 +3,11 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/provider/spotify_provider.dart'; import 'package:spotube/provider/spotify_provider.dart';
import 'package:spotube/services/queries/queries.dart'; import 'package:spotube/services/queries/queries.dart';
import 'package:spotube/utils/type_conversion_utils.dart';
class PlaylistAddTrackDialog extends HookConsumerWidget { class PlaylistAddTrackDialog extends HookConsumerWidget {
final List<Track> tracks; final List<Track> tracks;
@ -39,21 +42,21 @@ class PlaylistAddTrackDialog extends HookConsumerWidget {
.toList(), .toList(),
playlistId), playlistId),
), ),
).then((_) => Navigator.pop(context)); ).then((_) => Navigator.pop(context, true));
} }
return AlertDialog( return AlertDialog(
title: const Text("Add to Playlist"), title: Text(context.l10n.add_to_playlist),
actions: [ actions: [
OutlinedButton( OutlinedButton(
child: const Text("Cancel"), child: Text(context.l10n.cancel),
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context, false);
}, },
), ),
FilledButton( FilledButton(
onPressed: onAdd, onPressed: onAdd,
child: const Text("Add"), child: Text(context.l10n.add),
), ),
], ],
content: SizedBox( content: SizedBox(
@ -67,7 +70,19 @@ class PlaylistAddTrackDialog extends HookConsumerWidget {
itemBuilder: (context, index) { itemBuilder: (context, index) {
final playlist = filteredPlaylists.elementAt(index); final playlist = filteredPlaylists.elementAt(index);
return CheckboxListTile( return CheckboxListTile(
title: Text(playlist.name!), secondary: CircleAvatar(
backgroundImage: UniversalImage.imageProvider(
TypeConversionUtils.image_X_UrlString(
playlist.images,
placeholder: ImagePlaceholder.collection,
),
),
),
contentPadding: EdgeInsets.zero,
title: Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(playlist.name!),
),
value: playlistsCheck.value[playlist.id] ?? false, value: playlistsCheck.value[playlist.id] ?? false,
onChanged: (val) { onChanged: (val) {
playlistsCheck.value = { playlistsCheck.value = {

View File

@ -220,6 +220,15 @@
"moderate": "Moderate", "moderate": "Moderate",
"deselect_all": "Deselect All", "deselect_all": "Deselect All",
"select_all": "Select All", "select_all": "Select All",
"are_you_sure": "Are you sure?",
"generating_playlist": "Generating your custom playlist...", "generating_playlist": "Generating your custom playlist...",
"selected_count_tracks": "Selected {count} tracks" "selected_count_tracks": "Selected {count} tracks",
"download_warning": "If you download all Tracks at bulk you're clearly pirating Music & causing damage to the creative society of Music. I hope you are aware of this. Always, try respecting & supporting Artist's hard work",
"download_ip_ban_warning": "BTW, your IP can get blocked on YouTube due excessive download requests than usual. IP block means you can't use YouTube (even if you're logged in) for at least 2-3 months from that IP device. And Spotube doesn't hold any responsibility if this ever happens",
"by_clicking_accept_terms": "By clicking 'accept' you agree to following terms:",
"download_agreement_1": "I know I'm pirating Music. I'm bad",
"download_agreement_2": "I'll support the Artist wherever I can and I'm only doing this because I don't have money to buy their art",
"download_agreement_3": "I'm completely aware that my IP can get blocked on YouTube & I don't hold Spotube or his owners/contributors responsible for any accidents caused by my current action",
"decline": "Decline",
"accept": "Accept"
} }

View File

@ -7,6 +7,7 @@ import 'package:spotify/spotify.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/library/playlist_generate/simple_track_tile.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/playlist/playlist_create_dialog.dart';
import 'package:spotube/components/shared/dialogs/playlist_add_track_dialog.dart';
import 'package:spotube/components/shared/page_window_title_bar.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
@ -31,6 +32,7 @@ class PlaylistGenerateResultPage extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final router = GoRouter.of(context); final router = GoRouter.of(context);
final scaffoldMessenger = ScaffoldMessenger.of(context);
final playlistNotifier = ref.watch(ProxyPlaylistNotifier.notifier); final playlistNotifier = ref.watch(ProxyPlaylistNotifier.notifier);
final (:seeds, :parameters, :limit, :market) = state; final (:seeds, :parameters, :limit, :market) = state;
@ -118,12 +120,13 @@ class PlaylistGenerateResultPage extends HookConsumerWidget {
), ),
); );
if (context.mounted) { if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar( scaffoldMessenger.showSnackBar(
SnackBar( SnackBar(
content: Text( content: Text(
context.l10n.add_count_to_queue( context.l10n.add_count_to_queue(
selectedTracks.value.length, selectedTracks.value.length,
)), ),
),
), ),
); );
} }
@ -153,8 +156,36 @@ class PlaylistGenerateResultPage extends HookConsumerWidget {
FilledButton.tonalIcon( FilledButton.tonalIcon(
icon: const Icon(SpotubeIcons.playlistAdd), icon: const Icon(SpotubeIcons.playlistAdd),
label: Text(context.l10n.add_to_playlist), label: Text(context.l10n.add_to_playlist),
onPressed: onPressed: selectedTracks.value.isEmpty
selectedTracks.value.isEmpty ? null : () {}, ? null
: () async {
final hasAdded = await showDialog<bool>(
context: context,
builder: (context) =>
PlaylistAddTrackDialog(
tracks: selectedTracks.value
.map(
(e) => generatedPlaylist.data!
.firstWhere(
(element) => element.id == e,
),
)
.toList(),
),
);
if (context.mounted && hasAdded == true) {
scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
context.l10n.add_count_to_playlist(
selectedTracks.value.length,
),
),
),
);
}
},
) )
], ],
), ),