feat(queue): add track(s) for playing next (#460)

This commit is contained in:
Kingkor Roy Tirtho 2023-04-28 11:30:27 +06:00
parent 441b43bef6
commit cac8ea6388
4 changed files with 83 additions and 9 deletions

View File

@ -75,4 +75,5 @@ abstract class SpotubeIcons {
static const hoverOn = Icons.back_hand_rounded;
static const hoverOff = Icons.back_hand_outlined;
static const dragHandle = Icons.drag_indicator;
static const lightning = Icons.flash_on_rounded;
}

View File

@ -310,27 +310,46 @@ class TrackTile extends HookConsumerWidget {
tooltip: "More options",
itemBuilder: (context) {
return [
if (!playlistQueueNotifier.isTrackOnQueue(track.value))
if (!playlistQueueNotifier.isTrackOnQueue(track.value)) ...[
PopupMenuItem(
padding: EdgeInsets.zero,
onTap: () {
playlistQueueNotifier.add([track.value]);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text("Added ${track.value.name} to queue"),
content: Text(
"Added ${track.value.name} to queue",
),
),
);
},
child: const ListTile(
leading: Icon(SpotubeIcons.queueAdd),
title: Text("Add to queue"),
title: Text("Add to Queue"),
),
),
)
else
PopupMenuItem(
padding: EdgeInsets.zero,
onTap: () {
playlistQueueNotifier.playNext([track.value]);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text("${track.value.name} will play next"),
),
);
},
child: const ListTile(
leading: Icon(SpotubeIcons.lightning),
title: Text("Play next"),
),
),
] else
PopupMenuItem(
padding: EdgeInsets.zero,
onTap: playlist?.activeTrack.id == track.value.id
? null
: () {
playlistQueueNotifier.remove([track.value]);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
@ -339,6 +358,7 @@ class TrackTile extends HookConsumerWidget {
),
);
},
enabled: playlist?.activeTrack.id != track.value.id,
child: const ListTile(
leading: Icon(SpotubeIcons.queueRemove),
title: Text("Remove from queue"),

View File

@ -41,6 +41,7 @@ class TracksTableView extends HookConsumerWidget {
@override
Widget build(context, ref) {
final playlist = ref.watch(PlaylistQueueNotifier.provider);
final playlistNotifier = ref.watch(PlaylistQueueNotifier.notifier);
final downloader = ref.watch(downloaderProvider);
TextStyle tableHeadStyle =
const TextStyle(fontWeight: FontWeight.bold, fontSize: 16);
@ -162,6 +163,32 @@ class TracksTableView extends HookConsumerWidget {
],
),
),
PopupMenuItem(
enabled: selectedTracks.isNotEmpty,
value: "add-to-queue",
child: Row(
children: [
const Icon(SpotubeIcons.queueAdd),
const SizedBox(width: 5),
Text(
"Add (${selectedTracks.length}) to Queue",
),
],
),
),
PopupMenuItem(
enabled: selectedTracks.isNotEmpty,
value: "play-next",
child: Row(
children: [
const Icon(SpotubeIcons.lightning),
const SizedBox(width: 5),
Text(
"Play (${selectedTracks.length}) Next",
),
],
),
),
];
},
onSelected: (action) async {
@ -194,6 +221,20 @@ class TracksTableView extends HookConsumerWidget {
);
break;
}
case "play-next":
{
playlistNotifier.playNext(selectedTracks.toList());
selected.value = [];
showCheck.value = false;
break;
}
case "add-to-queue":
{
playlistNotifier.add(selectedTracks.toList());
selected.value = [];
showCheck.value = false;
break;
}
default:
}
},

View File

@ -266,6 +266,18 @@ class PlaylistQueueNotifier extends PersistedStateNotifier<PlaylistQueue?> {
}
}
void playNext(List<Track> tracks) {
if (!isLoaded) {
loadAndPlay(tracks);
} else {
final stateTracks = state!.tracks.toList();
stateTracks.insertAll(state!.active + 1, tracks);
state = state?.copyWith(tracks: Set.from(stateTracks));
}
}
void remove(List<Track> tracks) {
if (!isLoaded) return;
final trackIds = tracks.map((e) => e.id!).toSet();