Skip to content

Commit

Permalink
fix: handle dublicated items in playback queue correctly #1852
Browse files Browse the repository at this point in the history
  • Loading branch information
KRTirtho committed Sep 15, 2024
1 parent 36d161c commit 9cb828b
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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();
Expand Down
19 changes: 19 additions & 0 deletions lib/extensions/list.dart
Original file line number Diff line number Diff line change
@@ -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;
}
}
7 changes: 5 additions & 2 deletions lib/pages/track/track.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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),
Expand All @@ -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),
Expand Down
20 changes: 18 additions & 2 deletions lib/provider/audio_player/audio_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand All @@ -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));
}

Expand All @@ -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
Expand Down
8 changes: 0 additions & 8 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 0 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 9cb828b

Please sign in to comment.