mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
fix: handle dublicated items in playback queue correctly #1852
This commit is contained in:
parent
36d161c05a
commit
9cb828bb55
@ -15,6 +15,7 @@ import 'package:spotube/components/tracks_view/sections/body/track_view_body_hea
|
||||
import 'package:spotube/components/tracks_view/sections/body/use_is_user_playlist.dart';
|
||||
import 'package:spotube/components/tracks_view/track_view_props.dart';
|
||||
import 'package:spotube/components/tracks_view/track_view_provider.dart';
|
||||
import 'package:spotube/extensions/list.dart';
|
||||
import 'package:spotube/models/connect/connect.dart';
|
||||
import 'package:spotube/provider/connect/connect.dart';
|
||||
import 'package:spotube/provider/history/history.dart';
|
||||
@ -96,7 +97,7 @@ class TrackViewBodySection extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (isActive || playlist.tracks.contains(track)) {
|
||||
if (isActive || playlist.tracks.containsBy(track, (a) => a.id)) {
|
||||
await playlistNotifier.jumpToTrack(track);
|
||||
} else {
|
||||
final tracks = await props.pagination.onFetchAll();
|
||||
|
19
lib/extensions/list.dart
Normal file
19
lib/extensions/list.dart
Normal file
@ -0,0 +1,19 @@
|
||||
extension UniqueItemExtension<T> on List<T> {
|
||||
List<T> unique(bool Function(T a, T b) equals) {
|
||||
final copy = <T>[];
|
||||
|
||||
for (final item in this) {
|
||||
if (copy.any((element) => equals(element, item))) continue;
|
||||
copy.add(item);
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
bool containsBy(T item, dynamic Function(T a) fn) {
|
||||
for (final el in this) {
|
||||
if (fn(el) == fn(item)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import 'package:spotube/components/titlebar/titlebar.dart';
|
||||
import 'package:spotube/components/track_tile/track_options.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/extensions/image.dart';
|
||||
import 'package:spotube/extensions/list.dart';
|
||||
import 'package:spotube/provider/audio_player/audio_player.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
import 'package:spotube/services/audio_player/audio_player.dart';
|
||||
@ -167,7 +168,8 @@ class TrackPage extends HookConsumerWidget {
|
||||
children: [
|
||||
const Gap(5),
|
||||
if (!isActive &&
|
||||
!playlist.tracks.contains(track))
|
||||
!playlist.tracks
|
||||
.containsBy(track, (t) => t.id))
|
||||
OutlinedButton.icon(
|
||||
icon: const Icon(SpotubeIcons.queueAdd),
|
||||
label: Text(context.l10n.queue),
|
||||
@ -177,7 +179,8 @@ class TrackPage extends HookConsumerWidget {
|
||||
),
|
||||
const Gap(5),
|
||||
if (!isActive &&
|
||||
!playlist.tracks.contains(track))
|
||||
!playlist.tracks
|
||||
.containsBy(track, (t) => t.id))
|
||||
IconButton.outlined(
|
||||
icon:
|
||||
const Icon(SpotubeIcons.lightning),
|
||||
|
@ -4,6 +4,7 @@ import 'package:drift/drift.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:media_kit/media_kit.dart' hide Track;
|
||||
import 'package:spotify/spotify.dart' hide Playlist;
|
||||
import 'package:spotube/extensions/list.dart';
|
||||
import 'package:spotube/extensions/track.dart';
|
||||
import 'package:spotube/models/database/database.dart';
|
||||
import 'package:spotube/models/local_track.dart';
|
||||
@ -256,6 +257,10 @@ class AudioPlayerNotifier extends Notifier<AudioPlayerState> {
|
||||
for (int i = 0; i < tracks.length; i++) {
|
||||
final track = tracks.elementAt(i);
|
||||
|
||||
if (state.tracks.any((element) => _compareTracks(element, track))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await audioPlayer.addTrackAt(
|
||||
SpotubeMedia(track),
|
||||
max(state.playlist.index, 0) + i + 1,
|
||||
@ -265,6 +270,7 @@ class AudioPlayerNotifier extends Notifier<AudioPlayerState> {
|
||||
|
||||
Future<void> addTrack(Track track) async {
|
||||
if (_blacklist.contains(track)) return;
|
||||
if (state.tracks.any((element) => _compareTracks(element, track))) return;
|
||||
await audioPlayer.addTrack(SpotubeMedia(track));
|
||||
}
|
||||
|
||||
@ -289,13 +295,23 @@ class AudioPlayerNotifier extends Notifier<AudioPlayerState> {
|
||||
}
|
||||
}
|
||||
|
||||
bool _compareTracks(Track a, Track b) {
|
||||
if ((a is LocalTrack && b is! LocalTrack) ||
|
||||
(a is! LocalTrack && b is LocalTrack)) return false;
|
||||
|
||||
return a is LocalTrack && b is LocalTrack
|
||||
? (a).path == (b).path
|
||||
: a.id == b.id;
|
||||
}
|
||||
|
||||
Future<void> load(
|
||||
List<Track> tracks, {
|
||||
int initialIndex = 0,
|
||||
bool autoPlay = false,
|
||||
}) async {
|
||||
final medias =
|
||||
(_blacklist.filter(tracks).toList() as List<Track>).asMediaList();
|
||||
final medias = (_blacklist.filter(tracks).toList() as List<Track>)
|
||||
.asMediaList()
|
||||
.unique((a, b) => _compareTracks(a.track, b.track));
|
||||
|
||||
// Giving the initial track a boost so MediaKit won't skip
|
||||
// because of timeout
|
||||
|
@ -758,14 +758,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.20.5"
|
||||
flutter_hooks_lint:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_hooks_lint
|
||||
sha256: fc6e18505b597737e5d620656e340ac60e7a58980cca29e18c1216bd15083674
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
flutter_inappwebview:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -158,7 +158,6 @@ dev_dependencies:
|
||||
xml: ^6.5.0
|
||||
io: ^1.0.4
|
||||
drift_dev: ^2.18.0
|
||||
flutter_hooks_lint: ^1.2.0
|
||||
|
||||
dependency_overrides:
|
||||
uuid: ^4.4.0
|
||||
|
Loading…
Reference in New Issue
Block a user