Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve playlist add #405

Merged
merged 1 commit into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions lib/src/common/audio_page_body.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,12 @@ class _AudioPageBodyState extends State<AudioPageBody> {
final liked = libraryModel.liked;
final removeLikedAudio = libraryModel.removeLikedAudio;
final addLikedAudio = libraryModel.addLikedAudio;
final void Function(String, Audio) removeAudioFromPlaylist =
libraryModel.removeAudioFromPlaylist;
final List<String> Function() getTopFivePlaylistNames =
libraryModel.getTopFivePlaylistNames;
final void Function(String, Audio) addAudioToPlaylist =
libraryModel.addAudioToPlaylist;
final void Function(String, Set<Audio>) addPlaylist =
libraryModel.addPlaylist;
final removeAudioFromPlaylist = libraryModel.removeAudioFromPlaylist;
final playlistNames = libraryModel.getPlaylistNames;
final addAudioToPlaylist = libraryModel.addAudioToPlaylist;
final addPlaylist = libraryModel.addPlaylist;
final getPlaylistById = libraryModel.getPlaylistById;
final removePlaylist = libraryModel.removePlaylist;

final sortedAudios = widget.audios?.toList() ?? [];

Expand Down Expand Up @@ -253,10 +251,13 @@ class _AudioPageBodyState extends State<AudioPageBody> {
widget.audioPageType != AudioPageType.playlist
? null
: removeAudioFromPlaylist,
topFivePlaylistNames: getTopFivePlaylistNames(),
playlistIds: playlistNames(),
addAudioToPlaylist: addAudioToPlaylist,
addPlaylist: addPlaylist,
insertIntoQueue: () => insertIntoQueue(audio),
removePlaylist: removePlaylist,
getPlaylistById: getPlaylistById,
onTextTap: widget.onTextTap,
);

return AudioTile(
Expand Down
84 changes: 55 additions & 29 deletions lib/src/common/like_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import 'package:yaru_widgets/yaru_widgets.dart';

import '../../build_context_x.dart';
import '../../data.dart';
import '../../library.dart';
import '../l10n/l10n.dart';
import '../library/add_to_playlist_dialog.dart';
import '../library/playlist_dialog.dart';
import 'icons.dart';
import 'stream_provider_share_button.dart';
Expand All @@ -18,10 +20,13 @@ class LikeButton extends StatelessWidget {
required this.removeLikedAudio,
required this.addLikedAudio,
this.onRemoveFromPlaylist,
required this.topFivePlaylistNames,
required this.playlistIds,
required this.addAudioToPlaylist,
required this.addPlaylist,
this.insertIntoQueue,
required this.getPlaylistById,
required this.removePlaylist,
this.onTextTap,
});

final String playlistId;
Expand All @@ -31,10 +36,14 @@ class LikeButton extends StatelessWidget {
final void Function(Audio, [bool]) removeLikedAudio;
final void Function(Audio, [bool]) addLikedAudio;
final void Function(String, Audio)? onRemoveFromPlaylist;
final List<String>? topFivePlaylistNames;
final List<String>? playlistIds;
final void Function(String, Audio) addAudioToPlaylist;
final void Function(String, Set<Audio>) addPlaylist;
final void Function()? insertIntoQueue;
final Set<Audio>? Function(String id) getPlaylistById;
final void Function(String) removePlaylist;
final void Function({required AudioType audioType, required String text})?
onTextTap;

@override
Widget build(BuildContext context) {
Expand All @@ -53,8 +62,7 @@ class LikeButton extends StatelessWidget {

return _Button(
insertIntoQueue: insertIntoQueue,
artist: audio.artist ?? '',
title: audio.title ?? '',
audio: audio,
playlistId: playlistId,
onRemoveFromPlaylist: onRemoveFromPlaylist == null
? null
Expand All @@ -70,9 +78,12 @@ class LikeButton extends StatelessWidget {
},
);
},
onAddToPlaylist: (playlistId) => addAudioToPlaylist(playlistId, audio),
topFivePlaylistIds: topFivePlaylistNames,
addAudioToPlaylist: addAudioToPlaylist,
playlistIds: playlistIds ?? [],
icon: heartButton,
removePlaylist: removePlaylist,
getPlaylistById: getPlaylistById,
onTextTap: onTextTap,
);
}
}
Expand All @@ -81,24 +92,29 @@ class _Button extends StatelessWidget {
const _Button({
this.onCreateNewPlaylist,
this.onRemoveFromPlaylist,
this.onAddToPlaylist,
required this.addAudioToPlaylist,
this.playlistId,
this.topFivePlaylistIds,
required this.playlistIds,
required this.icon,
required this.artist,
required this.title,
required this.audio,
this.insertIntoQueue,
required this.removePlaylist,
required this.getPlaylistById,
this.onTextTap,
});

final void Function()? insertIntoQueue;
final void Function()? onCreateNewPlaylist;
final void Function(String playlistId)? onRemoveFromPlaylist;
final void Function(String playlistId)? onAddToPlaylist;
final void Function(String, Audio) addAudioToPlaylist;
final void Function(String) removePlaylist;
final String? playlistId;
final List<String>? topFivePlaylistIds;
final List<String> playlistIds;
final Widget icon;
final String artist;
final String title;
final Audio audio;
final Set<Audio>? Function(String id) getPlaylistById;
final void Function({required AudioType audioType, required String text})?
onTextTap;

@override
Widget build(BuildContext context) {
Expand All @@ -112,34 +128,44 @@ class _Button extends StatelessWidget {
),
itemBuilder: (context) {
return [
PopupMenuItem(
onTap: onCreateNewPlaylist,
child: Text(context.l10n.createNewPlaylist),
),
PopupMenuItem(
onTap: insertIntoQueue,
child: Text(context.l10n.insertIntoQueue),
),
PopupMenuItem(
onTap: onCreateNewPlaylist,
child: Text(context.l10n.createNewPlaylist),
),
if (onRemoveFromPlaylist != null)
PopupMenuItem(
onTap: onRemoveFromPlaylist == null || playlistId == null
? null
: () => onRemoveFromPlaylist!(playlistId!),
child: Text('Remove from $playlistId'),
),
if (topFivePlaylistIds != null)
for (final playlist in topFivePlaylistIds!)
PopupMenuItem(
onTap: onAddToPlaylist == null
? null
: () => onAddToPlaylist!(playlist),
child: Text(
'${context.l10n.addTo} $playlist',
),
),
PopupMenuItem(
onTap: () => showDialog(
context: context,
builder: (context) {
return AddToPlaylistDialog(
audio: audio,
playlistIds: playlistIds,
addAudioToPlaylist: addAudioToPlaylist,
removePlaylist: removePlaylist,
getPlaylistById: getPlaylistById,
onTextTap: onTextTap,
);
},
),
child: Text(
'${context.l10n.addToPlaylist} ...',
),
),
PopupMenuItem(
padding: EdgeInsets.zero,
child: StreamProviderRow(text: '$artist - $title'),
child: StreamProviderRow(
text: '${audio.artist ?? ''} - ${audio.title ?? ''}',
),
),
];
},
Expand Down
5 changes: 4 additions & 1 deletion lib/src/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,8 @@
"moreOptions": "Mehr Optionen",
"noRadioServerFound": "Es wurde kein Radio-Server gefunden",
"connectedTo": "Verbunden mit",
"tryReconnect": "Versuche Neuverbindung"
"tryReconnect": "Versuche Neuverbindung",
"addedTo": "Hinzugefügt zu",
"addToPlaylist": "Zu Wiedergabeliste hinzufügen",
"open": "Öffnen"
}
5 changes: 4 additions & 1 deletion lib/src/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,8 @@
"moreOptions": "More options",
"noRadioServerFound": "No radio server found",
"connectedTo": "Connected to",
"tryReconnect": "Try reconnect"
"tryReconnect": "Try reconnect",
"addedTo": "Added to",
"addToPlaylist": "Add to playlist",
"open": "Open"
}
115 changes: 115 additions & 0 deletions lib/src/library/add_to_playlist_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import 'package:flutter/material.dart';
import 'package:yaru_widgets/yaru_widgets.dart';

import '../../common.dart';
import '../../data.dart';
import '../../globals.dart';
import '../../l10n.dart';
import '../../library.dart';
import '../../theme.dart';
import '../common/side_bar_fall_back_image.dart';

class AddToPlaylistDialog extends StatelessWidget {
const AddToPlaylistDialog({
super.key,
required this.audio,
required this.playlistIds,
required this.addAudioToPlaylist,
required this.getPlaylistById,
required this.removePlaylist,
this.onTextTap,
});

final Audio audio;
final List<String> playlistIds;
final void Function(String, Audio) addAudioToPlaylist;
final Set<Audio>? Function(String id) getPlaylistById;
final void Function(String) removePlaylist;
final void Function({required AudioType audioType, required String text})?
onTextTap;

@override
Widget build(BuildContext context) {
return SimpleDialog(
title: yaruStyled
? YaruDialogTitleBar(
title: Text(context.l10n.addToPlaylist),
)
: Text(context.l10n.addToPlaylist),
titlePadding: yaruStyled
? EdgeInsets.zero
: const EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 0.0),
children: playlistIds
.map(
(e) => ListTile(
onTap: () {
addAudioToPlaylist(e, audio);
Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: _AddToPlaylistSnackBar(
id: e,
getPlaylistById: getPlaylistById,
unPinPlaylist: removePlaylist,
onTextTap: onTextTap,
),
),
);
},
leading: SideBarFallBackImage(
color: getAlphabetColor(e),
child: Icon(Iconz().starFilled),
),
title: Text(e),
),
)
.toList(),
);
}
}

class _AddToPlaylistSnackBar extends StatelessWidget {
const _AddToPlaylistSnackBar({
required this.getPlaylistById,
required this.unPinPlaylist,
required this.id,
this.onTextTap,
});

final Set<Audio>? Function(String id) getPlaylistById;
final void Function(String p1) unPinPlaylist;
final String id;
final void Function({required AudioType audioType, required String text})?
onTextTap;

@override
Widget build(BuildContext context) {
final playlist = getPlaylistById(id);
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${context.l10n.addedTo} $id',
),
if (playlist != null)
ImportantButton(
onPressed: () {
ScaffoldMessenger.of(context).clearSnackBars();
navigatorKey.currentState?.push(
MaterialPageRoute(
builder: (context) {
return PlaylistPage(
playlist: MapEntry(id, playlist),
unPinPlaylist: unPinPlaylist,
onTextTap: onTextTap,
);
},
),
);
},
child: Text(context.l10n.open),
),
],
);
}
}
5 changes: 3 additions & 2 deletions lib/src/library/library_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class LibraryModel extends SafeChangeNotifier {
int get playlistsLength => playlists.length;
List<Audio> getPlaylistAt(int index) =>
playlists.entries.elementAt(index).value.toList();
Set<Audio>? getPlaylistById(String id) => _service.playlists[id];

bool isPlaylistSaved(String? name) => playlists.containsKey(name);

Expand All @@ -162,8 +163,8 @@ class LibraryModel extends SafeChangeNotifier {
void removeAudioFromPlaylist(String playlist, Audio audio) =>
_service.removeAudioFromPlaylist(playlist, audio);

List<String> getTopFivePlaylistNames() =>
playlists.entries.take(5).map((e) => e.key).toList();
List<String> getPlaylistNames() =>
playlists.entries.map((e) => e.key).toList();

// Podcasts

Expand Down
11 changes: 7 additions & 4 deletions lib/src/player/queue_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,13 @@ class _QueueDialogState extends State<QueueDialog> {
top: 15,
),
child: OutlinedButton(
onPressed: () => widget.addPlaylist(
'${context.l10n.queue} ${DateTime.now()}',
Set.from(queue),
),
onPressed: () {
widget.addPlaylist(
'${context.l10n.queue} ${DateTime.now()}',
Set.from(queue),
);
Navigator.of(context).pop();
},
child: Text(context.l10n.createNewPlaylist),
),
),
Expand Down