mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
fix: collection currently playing state persist on restart
This commit is contained in:
parent
9251121ba0
commit
1c89e3efb0
@ -46,11 +46,9 @@ class AlbumCard extends HookConsumerWidget {
|
|||||||
useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying;
|
useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying;
|
||||||
final playlistNotifier = ref.watch(ProxyPlaylistNotifier.notifier);
|
final playlistNotifier = ref.watch(ProxyPlaylistNotifier.notifier);
|
||||||
final queryClient = useQueryClient();
|
final queryClient = useQueryClient();
|
||||||
final query = queryClient
|
|
||||||
.getQuery<List<TrackSimple>, dynamic>("album-tracks/${album.id}");
|
|
||||||
bool isPlaylistPlaying = useMemoized(
|
bool isPlaylistPlaying = useMemoized(
|
||||||
() => playlist.containsTracks(query?.data ?? album.tracks ?? []),
|
() => playlist.containsCollection(album.id!),
|
||||||
[playlistNotifier, query?.data, album.tracks],
|
[playlist, album.id],
|
||||||
);
|
);
|
||||||
final int marginH =
|
final int marginH =
|
||||||
useBreakpointValue(xs: 10, sm: 10, md: 15, lg: 20, xl: 20, xxl: 20);
|
useBreakpointValue(xs: 10, sm: 10, md: 15, lg: 20, xl: 20, xxl: 20);
|
||||||
@ -89,6 +87,7 @@ class AlbumCard extends HookConsumerWidget {
|
|||||||
[],
|
[],
|
||||||
autoPlay: true,
|
autoPlay: true,
|
||||||
);
|
);
|
||||||
|
playlistNotifier.addCollection(album.id!);
|
||||||
} finally {
|
} finally {
|
||||||
updating.value = false;
|
updating.value = false;
|
||||||
}
|
}
|
||||||
@ -118,6 +117,7 @@ class AlbumCard extends HookConsumerWidget {
|
|||||||
|
|
||||||
if (fetchedTracks == null || fetchedTracks.isEmpty) return;
|
if (fetchedTracks == null || fetchedTracks.isEmpty) return;
|
||||||
playlistNotifier.addTracks(fetchedTracks);
|
playlistNotifier.addTracks(fetchedTracks);
|
||||||
|
playlistNotifier.addCollection(album.id!);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
final snackbar = SnackBar(
|
final snackbar = SnackBar(
|
||||||
content: Text("Added ${album.tracks?.length} tracks to queue"),
|
content: Text("Added ${album.tracks?.length} tracks to queue"),
|
||||||
|
@ -24,13 +24,10 @@ class PlaylistCard extends HookConsumerWidget {
|
|||||||
final playing =
|
final playing =
|
||||||
useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying;
|
useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying;
|
||||||
final queryBowl = QueryClient.of(context);
|
final queryBowl = QueryClient.of(context);
|
||||||
final query = queryBowl.getQuery<List<Track>, dynamic>(
|
|
||||||
"playlist-tracks/${playlist.id}",
|
|
||||||
);
|
|
||||||
final tracks = useState<List<TrackSimple>?>(null);
|
final tracks = useState<List<TrackSimple>?>(null);
|
||||||
bool isPlaylistPlaying = useMemoized(
|
bool isPlaylistPlaying = useMemoized(
|
||||||
() => playlistQueue.containsTracks(tracks.value ?? query?.data ?? []),
|
() => playlistQueue.containsCollection(playlist.id!),
|
||||||
[playlistNotifier, tracks.value, query?.data],
|
[playlistQueue, playlist.id],
|
||||||
);
|
);
|
||||||
|
|
||||||
final updating = useState(false);
|
final updating = useState(false);
|
||||||
@ -72,6 +69,7 @@ class PlaylistCard extends HookConsumerWidget {
|
|||||||
if (fetchedTracks.isEmpty) return;
|
if (fetchedTracks.isEmpty) return;
|
||||||
|
|
||||||
await playlistNotifier.load(fetchedTracks, autoPlay: true);
|
await playlistNotifier.load(fetchedTracks, autoPlay: true);
|
||||||
|
playlistNotifier.addCollection(playlist.id!);
|
||||||
tracks.value = fetchedTracks;
|
tracks.value = fetchedTracks;
|
||||||
} finally {
|
} finally {
|
||||||
updating.value = false;
|
updating.value = false;
|
||||||
@ -90,6 +88,7 @@ class PlaylistCard extends HookConsumerWidget {
|
|||||||
if (fetchedTracks.isEmpty) return;
|
if (fetchedTracks.isEmpty) return;
|
||||||
|
|
||||||
playlistNotifier.addTracks(fetchedTracks);
|
playlistNotifier.addTracks(fetchedTracks);
|
||||||
|
playlistNotifier.addCollection(playlist.id!);
|
||||||
tracks.value = fetchedTracks;
|
tracks.value = fetchedTracks;
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
final snackbar = SnackBar(
|
final snackbar = SnackBar(
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
|
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@ -219,6 +218,9 @@ class TracksTableView extends HookConsumerWidget {
|
|||||||
case "play-next":
|
case "play-next":
|
||||||
{
|
{
|
||||||
playback.addTracksAtFirst(selectedTracks);
|
playback.addTracksAtFirst(selectedTracks);
|
||||||
|
if (playlistId != null) {
|
||||||
|
playback.addCollection(playlistId!);
|
||||||
|
}
|
||||||
selected.value = [];
|
selected.value = [];
|
||||||
showCheck.value = false;
|
showCheck.value = false;
|
||||||
break;
|
break;
|
||||||
@ -226,6 +228,9 @@ class TracksTableView extends HookConsumerWidget {
|
|||||||
case "add-to-queue":
|
case "add-to-queue":
|
||||||
{
|
{
|
||||||
playback.addTracks(selectedTracks);
|
playback.addTracks(selectedTracks);
|
||||||
|
if (playlistId != null) {
|
||||||
|
playback.addCollection(playlistId!);
|
||||||
|
}
|
||||||
selected.value = [];
|
selected.value = [];
|
||||||
showCheck.value = false;
|
showCheck.value = false;
|
||||||
break;
|
break;
|
||||||
|
@ -32,6 +32,7 @@ class AlbumPage extends HookConsumerWidget {
|
|||||||
sortedTracks,
|
sortedTracks,
|
||||||
initialIndex: sortedTracks.indexWhere((s) => s.id == currentTrack?.id),
|
initialIndex: sortedTracks.indexWhere((s) => s.id == currentTrack?.id),
|
||||||
);
|
);
|
||||||
|
playback.addCollection(album.id!);
|
||||||
} else if (isPlaylistPlaying &&
|
} else if (isPlaylistPlaying &&
|
||||||
currentTrack.id != null &&
|
currentTrack.id != null &&
|
||||||
currentTrack.id != playlist.activeTrack?.id) {
|
currentTrack.id != playlist.activeTrack?.id) {
|
||||||
@ -101,6 +102,7 @@ class AlbumPage extends HookConsumerWidget {
|
|||||||
TypeConversionUtils.simpleTrack_X_Track(track, album))
|
TypeConversionUtils.simpleTrack_X_Track(track, album))
|
||||||
.toList(),
|
.toList(),
|
||||||
);
|
);
|
||||||
|
playback.addCollection(album.id!);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onShare: () {
|
onShare: () {
|
||||||
|
@ -36,6 +36,7 @@ class PlaylistView extends HookConsumerWidget {
|
|||||||
initialIndex: sortedTracks.indexWhere((s) => s.id == currentTrack?.id),
|
initialIndex: sortedTracks.indexWhere((s) => s.id == currentTrack?.id),
|
||||||
autoPlay: true,
|
autoPlay: true,
|
||||||
);
|
);
|
||||||
|
playback.addCollection(playlist.id!);
|
||||||
} else if (isPlaylistPlaying &&
|
} else if (isPlaylistPlaying &&
|
||||||
currentTrack.id != null &&
|
currentTrack.id != null &&
|
||||||
currentTrack.id != proxyPlaylist.activeTrack?.id) {
|
currentTrack.id != proxyPlaylist.activeTrack?.id) {
|
||||||
@ -97,6 +98,7 @@ class PlaylistView extends HookConsumerWidget {
|
|||||||
onAddToQueue: () {
|
onAddToQueue: () {
|
||||||
if (tracksSnapshot.hasData && !isPlaylistPlaying) {
|
if (tracksSnapshot.hasData && !isPlaylistPlaying) {
|
||||||
playlistNotifier.addTracks(tracksSnapshot.data!);
|
playlistNotifier.addTracks(tracksSnapshot.data!);
|
||||||
|
playlistNotifier.addCollection(playlist.id!);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
bottomSpace: mediaQuery.mdAndDown,
|
bottomSpace: mediaQuery.mdAndDown,
|
||||||
|
@ -6,15 +6,20 @@ import 'package:spotube/models/spotube_track.dart';
|
|||||||
|
|
||||||
class ProxyPlaylist {
|
class ProxyPlaylist {
|
||||||
final Set<Track> tracks;
|
final Set<Track> tracks;
|
||||||
|
final Set<String> collections;
|
||||||
final int? active;
|
final int? active;
|
||||||
|
|
||||||
ProxyPlaylist(this.tracks, [this.active]);
|
ProxyPlaylist(this.tracks, [this.active, this.collections = const {}]);
|
||||||
|
|
||||||
factory ProxyPlaylist.fromJson(Map<String, dynamic> json) {
|
factory ProxyPlaylist.fromJson(Map<String, dynamic> json) {
|
||||||
return ProxyPlaylist(
|
return ProxyPlaylist(
|
||||||
List.castFrom<dynamic, Map<String, dynamic>>(
|
List.castFrom<dynamic, Map<String, dynamic>>(
|
||||||
json['tracks'] ?? <Map<String, dynamic>>[],
|
json['tracks'] ?? <Map<String, dynamic>>[],
|
||||||
).map(_makeAppropriateTrack).toSet(),
|
).map(_makeAppropriateTrack).toSet(),
|
||||||
json['active'] as int?,
|
json['active'] as int?,
|
||||||
|
json['collections'] == null
|
||||||
|
? {}
|
||||||
|
: (json['collections'] as List).toSet().cast<String>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,6 +31,10 @@ class ProxyPlaylist {
|
|||||||
activeTrack is! SpotubeTrack &&
|
activeTrack is! SpotubeTrack &&
|
||||||
activeTrack is! LocalTrack;
|
activeTrack is! LocalTrack;
|
||||||
|
|
||||||
|
bool containsCollection(String collection) {
|
||||||
|
return collections.contains(collection);
|
||||||
|
}
|
||||||
|
|
||||||
bool containsTrack(TrackSimple track) {
|
bool containsTrack(TrackSimple track) {
|
||||||
return tracks.firstWhereOrNull((element) => element.id == track.id) != null;
|
return tracks.firstWhereOrNull((element) => element.id == track.id) != null;
|
||||||
}
|
}
|
||||||
@ -57,16 +66,19 @@ class ProxyPlaylist {
|
|||||||
return {
|
return {
|
||||||
'tracks': tracks.map(_makeAppropriateTrackJson).toList(),
|
'tracks': tracks.map(_makeAppropriateTrackJson).toList(),
|
||||||
'active': active,
|
'active': active,
|
||||||
|
'collections': collections.toList(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxyPlaylist copyWith({
|
ProxyPlaylist copyWith({
|
||||||
Set<Track>? tracks,
|
Set<Track>? tracks,
|
||||||
int? active,
|
int? active,
|
||||||
|
Set<String>? collections,
|
||||||
}) {
|
}) {
|
||||||
return ProxyPlaylist(
|
return ProxyPlaylist(
|
||||||
tracks ?? this.tracks,
|
tracks ?? this.tracks,
|
||||||
active ?? this.active,
|
active ?? this.active,
|
||||||
|
collections ?? this.collections,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,6 +185,19 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addCollection(String collectionId) {
|
||||||
|
state = state.copyWith(collections: {
|
||||||
|
...state.collections,
|
||||||
|
collectionId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeCollection(String collectionId) {
|
||||||
|
state = state.copyWith(collections: {
|
||||||
|
...state.collections..remove(collectionId),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Safely Remove playing tracks
|
// TODO: Safely Remove playing tracks
|
||||||
|
|
||||||
Future<void> removeTrack(String trackId) async {
|
Future<void> removeTrack(String trackId) async {
|
||||||
@ -224,6 +237,7 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist>
|
|||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
tracks: tracks.toSet(),
|
tracks: tracks.toSet(),
|
||||||
active: initialIndex,
|
active: initialIndex,
|
||||||
|
collections: {},
|
||||||
);
|
);
|
||||||
await notificationService.addTrack(indexTrack);
|
await notificationService.addTrack(indexTrack);
|
||||||
} else {
|
} else {
|
||||||
@ -236,6 +250,7 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist>
|
|||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
tracks: mergeTracks([addableTrack], tracks),
|
tracks: mergeTracks([addableTrack], tracks),
|
||||||
active: initialIndex,
|
active: initialIndex,
|
||||||
|
collections: {},
|
||||||
);
|
);
|
||||||
await notificationService.addTrack(addableTrack);
|
await notificationService.addTrack(addableTrack);
|
||||||
await storeTrack(
|
await storeTrack(
|
||||||
|
Loading…
Reference in New Issue
Block a user