mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
fix: re-enable add to queue and play next support, favorite button query exceptions
This commit is contained in:
parent
bf59570251
commit
e529c79c4f
@ -11,7 +11,6 @@ import 'package:spotube/services/mutations/mutations.dart';
|
||||
import 'package:spotube/services/queries/queries.dart';
|
||||
|
||||
import 'package:spotube/utils/type_conversion_utils.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class HeartButton extends HookConsumerWidget {
|
||||
final bool isLiked;
|
||||
@ -60,8 +59,11 @@ class HeartButton extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
Tuple3<bool, Mutation<bool, dynamic, bool>, Query<User, dynamic>>
|
||||
useTrackToggleLike(Track track, WidgetRef ref) {
|
||||
({
|
||||
bool isLiked,
|
||||
Mutation<bool, dynamic, bool> toggleTrackLike,
|
||||
Query<User?, dynamic> me,
|
||||
}) useTrackToggleLike(Track track, WidgetRef ref) {
|
||||
final me = useQueries.user.me(ref);
|
||||
|
||||
final savedTracks =
|
||||
@ -101,7 +103,7 @@ Tuple3<bool, Mutation<bool, dynamic, bool>, Query<User, dynamic>>
|
||||
},
|
||||
);
|
||||
|
||||
return Tuple3(isLiked, toggleTrackLike, me);
|
||||
return (isLiked: isLiked, toggleTrackLike: toggleTrackLike, me: me);
|
||||
}
|
||||
|
||||
class TrackHeartButton extends HookConsumerWidget {
|
||||
@ -116,18 +118,18 @@ class TrackHeartButton extends HookConsumerWidget {
|
||||
final savedTracks =
|
||||
useQueries.playlist.tracksOfQuery(ref, "user-liked-tracks");
|
||||
final toggler = useTrackToggleLike(track, ref);
|
||||
if (toggler.item3.isLoading || !toggler.item3.hasData) {
|
||||
if (toggler.me.isLoading || !toggler.me.hasData) {
|
||||
return const CircularProgressIndicator();
|
||||
}
|
||||
|
||||
return HeartButton(
|
||||
tooltip: toggler.item1
|
||||
tooltip: toggler.isLiked
|
||||
? context.l10n.remove_from_favorites
|
||||
: context.l10n.save_as_favorite,
|
||||
isLiked: toggler.item1,
|
||||
isLiked: toggler.isLiked,
|
||||
onPressed: savedTracks.hasData
|
||||
? () {
|
||||
toggler.item2.mutate(toggler.item1);
|
||||
toggler.toggleTrackLike.mutate(toggler.isLiked);
|
||||
}
|
||||
: null,
|
||||
);
|
||||
|
@ -316,16 +316,18 @@ class TrackTile extends HookConsumerWidget {
|
||||
if (!playlist.containsTrack(track.value)) ...[
|
||||
PopupMenuItem(
|
||||
padding: EdgeInsets.zero,
|
||||
onTap: () {
|
||||
playback.addTrack(track.value);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
context.l10n
|
||||
.added_track_to_queue(track.value.name!),
|
||||
onTap: () async {
|
||||
await playback.addTrack(track.value);
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
context.l10n
|
||||
.added_track_to_queue(track.value.name!),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
}
|
||||
},
|
||||
child: ListTile(
|
||||
leading: const Icon(SpotubeIcons.queueAdd),
|
||||
@ -373,21 +375,21 @@ class TrackTile extends HookConsumerWidget {
|
||||
title: Text(context.l10n.remove_from_queue),
|
||||
),
|
||||
),
|
||||
if (toggler.item3.hasData)
|
||||
if (toggler.me.hasData)
|
||||
PopupMenuItem(
|
||||
padding: EdgeInsets.zero,
|
||||
onTap: () {
|
||||
toggler.item2.mutate(toggler.item1);
|
||||
toggler.toggleTrackLike.mutate(toggler.isLiked);
|
||||
},
|
||||
child: ListTile(
|
||||
leading: toggler.item1
|
||||
leading: toggler.isLiked
|
||||
? const Icon(
|
||||
SpotubeIcons.heartFilled,
|
||||
color: Colors.pink,
|
||||
)
|
||||
: const Icon(SpotubeIcons.heart),
|
||||
title: Text(
|
||||
toggler.item1
|
||||
toggler.isLiked
|
||||
? context.l10n.remove_from_favorites
|
||||
: context.l10n.save_as_favorite,
|
||||
),
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/models/current_playlist.dart';
|
||||
@ -56,21 +57,22 @@ class BlackListNotifier
|
||||
}
|
||||
|
||||
bool contains(TrackSimple track) {
|
||||
return filter([track]).isNotEmpty;
|
||||
final containsTrack =
|
||||
state.contains(BlacklistedElement.track(track.id!, track.name!));
|
||||
|
||||
final containsTrackArtists = track.artists?.any(
|
||||
(artist) => state.contains(
|
||||
BlacklistedElement.artist(artist.id!, artist.name!),
|
||||
),
|
||||
) ??
|
||||
false;
|
||||
|
||||
return containsTrack || containsTrackArtists;
|
||||
}
|
||||
|
||||
/// Filters the non blacklisted tracks from the given [tracks]
|
||||
Iterable<TrackSimple> filter(Iterable<TrackSimple> tracks) {
|
||||
return tracks.where(
|
||||
(track) {
|
||||
return !state
|
||||
.contains(BlacklistedElement.track(track.id!, track.name!)) &&
|
||||
!(track.artists ?? []).any(
|
||||
(artist) => state.contains(
|
||||
BlacklistedElement.artist(artist.id!, artist.name!),
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList();
|
||||
return tracks.whereNot(contains).toList();
|
||||
}
|
||||
|
||||
CurrentPlaylist filterPlaylist(CurrentPlaylist playlist) {
|
||||
|
@ -21,7 +21,7 @@ import 'package:spotube/utils/type_conversion_utils.dart';
|
||||
/// * [ ] Mixed Queue containing both [SpotubeTrack] and [LocalTrack]
|
||||
/// * [ ] Modification of the Queue
|
||||
/// * [x] Add track at the end
|
||||
/// * [ ] Add track at the beginning
|
||||
/// * [x] Add track at the beginning
|
||||
/// * [x] Remove track
|
||||
/// * [ ] Reorder track
|
||||
/// * [ ] Caching and loading of cache of tracks
|
||||
@ -277,7 +277,20 @@ class ProxyPlaylistNotifier extends StateNotifier<ProxyPlaylist>
|
||||
await audioPlayer.moveTrack(oldIndex, newIndex);
|
||||
}
|
||||
|
||||
Future<void> addTracksAtFirst(Iterable<Track> track) async {}
|
||||
Future<void> addTracksAtFirst(Iterable<Track> tracks) async {
|
||||
tracks = blacklist.filter(tracks).toList() as List<Track>;
|
||||
final destIndex = state.active != null ? state.active! + 1 : 0;
|
||||
final newTracks = state.tracks.toList()..insertAll(destIndex, tracks);
|
||||
state = state.copyWith(tracks: newTracks.toSet());
|
||||
|
||||
tracks.forEachIndexed((index, track) async {
|
||||
audioPlayer.addTrackAt(
|
||||
makeAppropriateSource(track),
|
||||
destIndex + index,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> populateSibling() async {}
|
||||
Future<void> swapSibling(PipedSearchItem video) async {}
|
||||
|
||||
|
@ -216,6 +216,16 @@ class SpotubeAudioPlayer extends AudioPlayerInterface
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> addTrackAt(String url, int index) async {
|
||||
final urlType = _resolveUrlType(url);
|
||||
// if (mkSupportedPlatform && urlType is mk.Media) {
|
||||
await _mkPlayer.insert(index, urlType as mk.Media);
|
||||
// } else {
|
||||
// await (_justAudio!.audioSource as ja.ConcatenatingAudioSource)
|
||||
// .insert(index, urlType as ja.AudioSource);
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> removeTrack(int index) async {
|
||||
// if (mkSupportedPlatform) {
|
||||
await _mkPlayer.remove(index);
|
||||
|
@ -243,6 +243,25 @@ class MkPlayerWithState extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> insert(int index, Media media) {
|
||||
if (_playlist == null ||
|
||||
index < 0 ||
|
||||
index > _playlist!.medias.length - 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final newMedias = _playlist!.medias.toList()..insert(index, media);
|
||||
|
||||
playlist = _playlist!.copyWith(
|
||||
medias: newMedias,
|
||||
index: newMedias.indexOf(_playlist!.medias[_playlist!.index]),
|
||||
);
|
||||
|
||||
if (shuffled && _tempMedias != null) {
|
||||
_tempMedias!.insert(index, media);
|
||||
}
|
||||
}
|
||||
|
||||
/// Doesn't work when active media is the one to be removed
|
||||
@override
|
||||
FutureOr<void> remove(int index) async {
|
||||
|
@ -2,15 +2,17 @@ import 'package:fl_query/fl_query.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/hooks/use_spotify_query.dart';
|
||||
import 'package:spotube/provider/authentication_provider.dart';
|
||||
import 'package:spotube/utils/type_conversion_utils.dart';
|
||||
|
||||
class UserQueries {
|
||||
const UserQueries();
|
||||
Query<User, dynamic> me(WidgetRef ref) {
|
||||
Query<User?, dynamic> me(WidgetRef ref) {
|
||||
return useSpotifyQuery<User, dynamic>(
|
||||
"current-user",
|
||||
(spotify) async {
|
||||
final me = await spotify.me.get();
|
||||
if (ref.read(AuthenticationNotifier.provider) == null) return null;
|
||||
if (me.images == null || me.images?.isEmpty == true) {
|
||||
me.images = [
|
||||
Image()
|
||||
|
@ -1815,7 +1815,7 @@ packages:
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
tuple:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: tuple
|
||||
sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa"
|
||||
|
@ -88,7 +88,6 @@ dependencies:
|
||||
spotify: ^0.11.0
|
||||
system_theme: ^2.1.0
|
||||
titlebar_buttons: ^1.0.0
|
||||
tuple: ^2.0.1
|
||||
url_launcher: ^6.1.7
|
||||
uuid: ^3.0.7
|
||||
version: ^3.0.2
|
||||
|
Loading…
Reference in New Issue
Block a user