diff --git a/lib/modules/player/sibling_tracks_sheet.dart b/lib/modules/player/sibling_tracks_sheet.dart index a1a87dfc..451f77d7 100644 --- a/lib/modules/player/sibling_tracks_sheet.dart +++ b/lib/modules/player/sibling_tracks_sheet.dart @@ -18,6 +18,7 @@ import 'package:spotube/hooks/utils/use_debounce.dart'; import 'package:spotube/models/database/database.dart'; import 'package:spotube/models/metadata/metadata.dart'; import 'package:spotube/models/playback/track_sources.dart'; +import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/querying_track_info.dart'; import 'package:spotube/provider/server/active_track_sources.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; @@ -95,7 +96,7 @@ class SiblingTracksSheet extends HookConsumerWidget { final controller = useScrollController(); final searchRequest = useMemoized(() async { - if (searchTerm.trim().isEmpty) { + if (searchTerm.trim().isEmpty || activeTrackSource == null) { return []; } if (preferences.audioSource == AudioSource.jiosaavn) { @@ -107,7 +108,7 @@ class SiblingTracksSheet extends HookConsumerWidget { return siblingType.info; })); - final activeSourceInfo = activeTrackSource?.info as TrackSourceInfo; + final activeSourceInfo = activeTrackSource.info; return results ..removeWhere((element) => element.id == activeSourceInfo.id) @@ -122,18 +123,18 @@ class SiblingTracksSheet extends HookConsumerWidget { resultsYt .map(YoutubeVideoInfo.fromVideo) .mapIndexed((i, video) async { - final siblingType = - await YoutubeSourcedTrack.toSiblingType(i, video, ref); - return siblingType.info; - }), + if (!context.mounted) return null; + final siblingType = + await YoutubeSourcedTrack.toSiblingType(i, video, ref); + return siblingType.info; + }) + .whereType>() + .toList(), ); - final activeSourceInfo = activeTrackSource?.info as TrackSourceInfo; + final activeSourceInfo = activeTrackSource.info; return searchResults ..removeWhere((element) => element.id == activeSourceInfo.id) - ..insert( - 0, - activeSourceInfo, - ); + ..insert(0, activeSourceInfo); } }, [ searchTerm, @@ -165,8 +166,8 @@ class SiblingTracksSheet extends HookConsumerWidget { }, [activeTrack, previousActiveTrack]); final itemBuilder = useCallback( - (TrackSourceInfo sourceInfo) { - final icon = sourceInfoToIconMap[sourceInfo.runtimeType]; + (TrackSourceInfo sourceInfo, AudioSource source) { + final icon = sourceInfoToIconMap[source]; return ButtonTile( style: ButtonVariance.ghost, padding: const EdgeInsets.symmetric(horizontal: 8), @@ -197,14 +198,18 @@ class SiblingTracksSheet extends HookConsumerWidget { enabled: !isFetchingActiveTrack, selected: !isFetchingActiveTrack && sourceInfo.id == activeTrackSource?.info.id, - onPressed: () { + onPressed: () async { if (!isFetchingActiveTrack && sourceInfo.id != activeTrackSource?.info.id) { - activeTrackNotifier?.swapWithSibling(sourceInfo); - if (MediaQuery.sizeOf(context).mdAndUp) { - closeOverlay(context); - } else { - closeDrawer(context); + await activeTrackNotifier?.swapWithSibling(sourceInfo); + await ref.read(audioPlayerProvider.notifier).swapActiveSource(); + + if (context.mounted) { + if (MediaQuery.sizeOf(context).mdAndUp) { + closeOverlay(context); + } else { + closeDrawer(context); + } } } }, @@ -301,8 +306,8 @@ class SiblingTracksSheet extends HookConsumerWidget { controller: controller, itemCount: siblings.length, separatorBuilder: (context, index) => const Gap(8), - itemBuilder: (context, index) => - itemBuilder(siblings[index]), + itemBuilder: (context, index) => itemBuilder( + siblings[index], activeTrackSource!.source), ), true => FutureBuilder( future: searchRequest, @@ -321,8 +326,10 @@ class SiblingTracksSheet extends HookConsumerWidget { controller: controller, itemCount: snapshot.data!.length, separatorBuilder: (context, index) => const Gap(8), - itemBuilder: (context, index) => - itemBuilder(snapshot.data![index]), + itemBuilder: (context, index) => itemBuilder( + snapshot.data![index], + preferences.audioSource, + ), ); }, ), diff --git a/lib/provider/audio_player/audio_player.dart b/lib/provider/audio_player/audio_player.dart index 9e760256..a4b3aa88 100644 --- a/lib/provider/audio_player/audio_player.dart +++ b/lib/provider/audio_player/audio_player.dart @@ -421,6 +421,20 @@ class AudioPlayerNotifier extends Notifier { ); } + Future swapActiveSource() async { + if (state.tracks.isEmpty || state.activeTrack is! SpotubeFullTrackObject) { + return; + } + + final currentIndex = state.currentIndex; + final currentTrack = state.activeTrack as SpotubeFullTrackObject; + final swappedMedia = SpotubeMedia(currentTrack); + + await audioPlayer.addTrackAt(swappedMedia, currentIndex + 1); + await audioPlayer.skipToNext(); + await audioPlayer.removeTrack(currentIndex); + } + Future jumpToTrack(SpotubeTrackObject track) async { final index = state.tracks.toList().indexWhere((element) => element.id == track.id); diff --git a/lib/services/sourced_track/sources/jiosaavn.dart b/lib/services/sourced_track/sources/jiosaavn.dart index 4b67e717..02e97479 100644 --- a/lib/services/sourced_track/sources/jiosaavn.dart +++ b/lib/services/sourced_track/sources/jiosaavn.dart @@ -216,7 +216,7 @@ class JioSaavnSourcedTrack extends SourcedTrack { ref: ref, siblings: newSiblings, sources: source!, - info: info, + info: newSourceInfo, query: query, source: AudioSource.jiosaavn, ); diff --git a/lib/services/sourced_track/sources/piped.dart b/lib/services/sourced_track/sources/piped.dart index 65d613a6..78beda10 100644 --- a/lib/services/sourced_track/sources/piped.dart +++ b/lib/services/sourced_track/sources/piped.dart @@ -269,7 +269,7 @@ class PipedSourcedTrack extends SourcedTrack { ref: ref, siblings: newSiblings, sources: toSources(manifest), - info: info, + info: newSourceInfo, query: query, source: source, ); diff --git a/lib/services/sourced_track/sources/youtube.dart b/lib/services/sourced_track/sources/youtube.dart index c090c916..399d5e10 100644 --- a/lib/services/sourced_track/sources/youtube.dart +++ b/lib/services/sourced_track/sources/youtube.dart @@ -120,6 +120,7 @@ class YoutubeSourcedTrack extends SourcedTrack { dynamic ref, ) async { assert(ref is WidgetRef || ref is Ref, "Invalid ref type"); + List? sourceMap; if (index == 0) { final manifest = @@ -338,6 +339,7 @@ class YoutubeSourcedTrack extends SourcedTrack { final newSourceInfo = isStepSibling ? sibling : siblings.firstWhere((s) => s.id == sibling.id); + final newSiblings = siblings.where((s) => s.id != sibling.id).toList() ..insert(0, info); @@ -364,7 +366,7 @@ class YoutubeSourcedTrack extends SourcedTrack { source: source, siblings: newSiblings, sources: toTrackSources(manifest), - info: info, + info: newSourceInfo, query: query, ); }