Skip to content

Commit

Permalink
Play Next for Android + Swipes (#653)
Browse files Browse the repository at this point in the history
* Play next handled, when playing from queue

* Play Next and Add To Playlist added to swipes on Track

* iOS pipeline fix
  • Loading branch information
akrol95 authored Jan 15, 2025
1 parent 4792ac3 commit 794331a
Show file tree
Hide file tree
Showing 35 changed files with 510 additions and 143 deletions.
53 changes: 15 additions & 38 deletions BMM.Core/GuardedActions/TrackOptions/PrepareTrackOptionsAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using BMM.Core.GuardedActions.TrackOptions.Parameters;
using BMM.Core.GuardedActions.TrackOptions.Parameters.Interfaces;
using BMM.Core.GuardedActions.Tracks.Interfaces;
using BMM.Core.GuardedActions.Tracks.Parameters;
using BMM.Core.Helpers;
using BMM.Core.Helpers.PresentationHints;
using BMM.Core.Implementations;
Expand Down Expand Up @@ -61,6 +62,8 @@ public class PrepareTrackOptionsAction :
private readonly IMediaPlayer _mediaPlayer;
private readonly IShowTrackInfoAction _showTrackInfoAction;
private readonly ILikeUnlikeTrackAction _likeUnlikeTrackAction;
private readonly IPlayNextAction _playNextAction;
private readonly IAddToPlaylistAction _addToPlaylistAction;

private readonly List<decimal> _availablePlaybackSpeed = new()
{
Expand All @@ -82,7 +85,9 @@ public PrepareTrackOptionsAction(IConnection connection,
IAnalytics analytics,
IMediaPlayer mediaPlayer,
IShowTrackInfoAction showTrackInfoAction,
ILikeUnlikeTrackAction likeUnlikeTrackAction)
ILikeUnlikeTrackAction likeUnlikeTrackAction,
IPlayNextAction playNextAction,
IAddToPlaylistAction addToPlaylistAction)
{
_connection = connection;
_bmmLanguageBinder = bmmLanguageBinder;
Expand All @@ -97,6 +102,8 @@ public PrepareTrackOptionsAction(IConnection connection,
_mediaPlayer = mediaPlayer;
_showTrackInfoAction = showTrackInfoAction;
_likeUnlikeTrackAction = likeUnlikeTrackAction;
_playNextAction = playNextAction;
_addToPlaylistAction = addToPlaylistAction;
}

private bool IsSleepTimerOptionAvailable => _featurePreviewPermission.IsFeaturePreviewEnabled() || _firebaseRemoteConfig.IsSleepTimerEnabled;
Expand Down Expand Up @@ -139,48 +146,18 @@ protected override async Task<IList<StandardIconOptionPO>> Execute(IPrepareTrack
new StandardIconOptionPO(
_bmmLanguageBinder[Translations.UserDialogs_Track_AddToPlaylist],
ImageResourceNames.IconPlaylist,
new MvxAsyncCommand(async () =>
{
await _mvxNavigationService.ChangePresentation(new CloseFragmentsOverPlayerHint());
_mvxMessenger.Publish(new TogglePlayerMessage(this, false));
await Task.Delay(ViewConstants.DefaultAnimationDurationInMilliseconds);

await _mvxNavigationService.Navigate<TrackCollectionsAddToViewModel, TrackCollectionsAddToViewModel.Parameter>(
new TrackCollectionsAddToViewModel.Parameter
{
DocumentId = track.Id,
DocumentType = track.DocumentType,
OriginViewModel = sourceVM.PlaybackOriginString()
});
})));
new MvxAsyncCommand(() => _addToPlaylistAction.ExecuteGuarded(new TrackActionsParameter(track, sourceVM.PlaybackOriginString())))));
}

if (sourceVM is not QueueViewModel && sourceVM is not PlayerViewModel)
{
var mediaPlayer = Mvx.IoCProvider.Resolve<IMediaPlayer>();

if (DeviceInfo.Platform == DevicePlatform.iOS)
{
options.Add(new StandardIconOptionPO(
_bmmLanguageBinder[Translations.UserDialogs_Track_QueueToPlayNext],
ImageResourceNames.IconPlayMini,
new MvxAsyncCommand(async () =>
{
var success = await mediaPlayer.QueueToPlayNext(track, sourceVM.PlaybackOriginString());
if (success)
{
await Mvx.IoCProvider.Resolve<IToastDisplayer>()
.Success(_bmmLanguageBinder.GetText(Translations.UserDialogs_Track_AddedToQueue, track.Title));

Mvx.IoCProvider.Resolve<IAnalytics>()
.LogEvent(Event.TrackHasBeenAddedToBePlayedNext,
new Dictionary<string, object>
{
{ "track", track.Id }
});
}
})));
}
options.Add(new StandardIconOptionPO(
_bmmLanguageBinder[Translations.UserDialogs_Track_QueueToPlayNext],
ImageResourceNames.IconPlayMini,
new MvxAsyncCommand(() => _playNextAction.ExecuteGuarded(
new TrackActionsParameter(track, sourceVM.PlaybackOriginString())))));

options.Add(
new StandardIconOptionPO(
Expand All @@ -194,7 +171,7 @@ await Mvx.IoCProvider.Resolve<IToastDisplayer>()
await Mvx.IoCProvider.Resolve<IToastDisplayer>()
.Success(_bmmLanguageBinder.GetText(Translations.UserDialogs_Track_AddedToQueue, track.Title));

Mvx.IoCProvider.Resolve<IAnalytics>()
_analytics
.LogEvent(Event.TrackHasBeenAddedToEndOfQueue,
new Dictionary<string, object>
{
Expand Down
42 changes: 42 additions & 0 deletions BMM.Core/GuardedActions/Tracks/AddToPlaylistAction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using BMM.Core.Constants;
using BMM.Core.GuardedActions.Base;
using BMM.Core.GuardedActions.Tracks.Interfaces;
using BMM.Core.GuardedActions.Tracks.Parameters;
using BMM.Core.Helpers.PresentationHints;
using BMM.Core.Messages;
using BMM.Core.ViewModels;
using MvvmCross.Navigation;
using MvvmCross.Plugin.Messenger;

namespace BMM.Core.GuardedActions.Tracks;

public class AddToPlaylistAction
: GuardedActionWithParameter<TrackActionsParameter>,
IAddToPlaylistAction
{
private readonly IMvxNavigationService _mvxNavigationService;
private readonly IMvxMessenger _mvxMessenger;

public AddToPlaylistAction(
IMvxNavigationService mvxNavigationService,
IMvxMessenger mvxMessenger)
{
_mvxNavigationService = mvxNavigationService;
_mvxMessenger = mvxMessenger;
}

protected override async Task Execute(TrackActionsParameter parameter)
{
await _mvxNavigationService.ChangePresentation(new CloseFragmentsOverPlayerHint());
_mvxMessenger.Publish(new TogglePlayerMessage(this, false));
await Task.Delay(ViewConstants.DefaultAnimationDurationInMilliseconds);

await _mvxNavigationService.Navigate<TrackCollectionsAddToViewModel, TrackCollectionsAddToViewModel.Parameter>(
new TrackCollectionsAddToViewModel.Parameter
{
DocumentId = parameter.Track.Id,
DocumentType = parameter.Track.DocumentType,
OriginViewModel = parameter.PlaybackOrigin
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using BMM.Core.GuardedActions.Base.Interfaces;
using BMM.Core.GuardedActions.Tracks.Parameters;

namespace BMM.Core.GuardedActions.Tracks.Interfaces;

public interface IAddToPlaylistAction : IGuardedActionWithParameter<TrackActionsParameter>
{
}
9 changes: 9 additions & 0 deletions BMM.Core/GuardedActions/Tracks/Interfaces/IPlayNextAction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using BMM.Core.GuardedActions.Base.Interfaces;
using BMM.Core.GuardedActions.Tracks.Parameters;

namespace BMM.Core.GuardedActions.Tracks.Interfaces;

public interface IPlayNextAction : IGuardedActionWithParameter<TrackActionsParameter>
{

}
15 changes: 15 additions & 0 deletions BMM.Core/GuardedActions/Tracks/Parameters/TrackActionsParameter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using BMM.Api.Implementation.Models;

namespace BMM.Core.GuardedActions.Tracks.Parameters;

public class TrackActionsParameter
{
public TrackActionsParameter(Track track, string playbackOrigin)
{
Track = track;
PlaybackOrigin = playbackOrigin;
}

public Track Track { get; }
public string PlaybackOrigin { get; }
}
50 changes: 50 additions & 0 deletions BMM.Core/GuardedActions/Tracks/PlayNextAction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using BMM.Core.GuardedActions.Base;
using BMM.Core.GuardedActions.Tracks.Interfaces;
using BMM.Core.GuardedActions.Tracks.Parameters;
using BMM.Core.Implementations.Analytics;
using BMM.Core.Implementations.Localization.Interfaces;
using BMM.Core.Implementations.UI;
using BMM.Core.NewMediaPlayer.Abstractions;
using BMM.Core.Translation;

namespace BMM.Core.GuardedActions.Tracks;

public class PlayNextAction
: GuardedActionWithParameter<TrackActionsParameter>,
IPlayNextAction
{
private readonly IMediaPlayer _mediaPlayer;
private readonly IToastDisplayer _toastDisplayer;
private readonly IBMMLanguageBinder _bmmLanguageBinder;
private readonly IAnalytics _analytics;

public PlayNextAction(
IMediaPlayer mediaPlayer,
IToastDisplayer toastDisplayer,
IBMMLanguageBinder bmmLanguageBinder,
IAnalytics analytics)
{
_mediaPlayer = mediaPlayer;
_toastDisplayer = toastDisplayer;
_bmmLanguageBinder = bmmLanguageBinder;
_analytics = analytics;
}

protected override async Task Execute(TrackActionsParameter parameter)
{
bool success = await _mediaPlayer.QueueToPlayNext(parameter.Track, parameter.PlaybackOrigin);

if (success)
{
await _toastDisplayer
.Success(_bmmLanguageBinder.GetText(Translations.UserDialogs_Track_AddedToQueue, parameter.Track.Title));

_analytics
.LogEvent(Event.TrackHasBeenAddedToBePlayedNext,
new Dictionary<string, object>
{
{ "track", parameter.Track.Id }
});
}
}
}
42 changes: 17 additions & 25 deletions BMM.Core/Helpers/AnalyticsInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,22 @@ namespace BMM.Core.Helpers
{
public abstract class AnalyticsInitializer
{
private static string iOSPrefix = "ios_";
private static string AndroidPrefix = "android_";
private static string Dev = "dev";
private static string Prod = "prod";

public static void DroidRegister()
{
if (!AppCenter.Configured)
AppCenter.Start(GlobalConstants.DroidAppSecret, typeof(Analytics));

InitSentry();
}
private const string iOSPrefix = "ios_";
private const string AndroidPrefix = "android_";
private const string Dev = "dev";
private const string Prod = "prod";

public static bool ShouldInitSentry => !GlobalConstants.SentryDsn.Contains(GlobalConstants.Placeholder);

public static void IOSRegister()
{
if (!AppCenter.Configured)
AppCenter.Start(GlobalConstants.iOSAppSecret, typeof(Analytics));

InitSentry();
if (ShouldInitSentry)
SentrySdk.Init(SetupSentry);
}

private static void InitSentry()
{
SentrySdk.Init(options =>
{
options.Dsn = GlobalConstants.SentryDsn;
options.Environment = GetSentryEnvironment();
options.Debug = false;
options.TracesSampleRate = 1.0;
options.ProfilesSampleRate = 1.0;
});
}

private static string GetSentryEnvironment()
{
string env;
Expand All @@ -53,5 +36,14 @@ private static string GetSentryEnvironment()
? $"{AndroidPrefix}{env}"
: $"{iOSPrefix}{env}";
}

public static void SetupSentry(SentryOptions options)
{
options.Dsn = GlobalConstants.SentryDsn;
options.Environment = GetSentryEnvironment();
options.Debug = false;
options.TracesSampleRate = 1.0;
options.ProfilesSampleRate = 1.0;
}
}
}
1 change: 1 addition & 0 deletions BMM.Core/Helpers/GlobalConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
public class GlobalConstants
{
public const string Placeholder = "PLACEHOLDER";
public const string PackageName = "org.brunstad.bmm";

public const string ApiUrlInt = "https://int-bmm-api.brunstad.org";
Expand Down
4 changes: 3 additions & 1 deletion BMM.Core/Implementations/Factories/Tracks/ITrackPOFactory.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using BMM.Api.Implementation.Models;
using BMM.Core.Implementations.TrackInformation.Strategies;
using BMM.Core.Models.Enums;
using BMM.Core.Models.POs.Tracks.Interfaces;
using MvvmCross.Commands;

Expand All @@ -10,6 +11,7 @@ public interface ITrackPOFactory
ITrackPO Create(
ITrackInfoProvider trackInfoProvider,
IMvxAsyncCommand<Document> optionsClickedCommand,
Track track);
Track track,
TrackSwipeType trackSwipeType = TrackSwipeType.PlayNextAndAddToPlaylist);
}
}
17 changes: 14 additions & 3 deletions BMM.Core/Implementations/Factories/Tracks/TrackPOFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using BMM.Core.Implementations.FirebaseRemoteConfig;
using BMM.Core.Implementations.TrackInformation.Strategies;
using BMM.Core.Implementations.TrackListenedObservation;
using BMM.Core.Models.Enums;
using BMM.Core.Models.POs.Tracks;
using BMM.Core.Models.POs.Tracks.Interfaces;
using BMM.Core.NewMediaPlayer.Abstractions;
Expand All @@ -22,6 +23,8 @@ public class TrackPOFactory : ITrackPOFactory
private readonly IShowTrackInfoAction _showTrackInfoAction;
private readonly IListenedTracksStorage _listenedTracksStorage;
private readonly IFirebaseRemoteConfig _config;
private readonly IPlayNextAction _playNextAction;
private readonly IAddToPlaylistAction _addToPlaylistAction;

public TrackPOFactory(
IMediaPlayer mediaPlayer,
Expand All @@ -30,7 +33,9 @@ public TrackPOFactory(
IDownloadQueue downloadQueue,
IShowTrackInfoAction showTrackInfoAction,
IListenedTracksStorage listenedTracksStorage,
IFirebaseRemoteConfig config)
IFirebaseRemoteConfig config,
IPlayNextAction playNextAction,
IAddToPlaylistAction addToPlaylistAction)
{
_mediaPlayer = mediaPlayer;
_storageManager = storageManager;
Expand All @@ -39,17 +44,21 @@ public TrackPOFactory(
_showTrackInfoAction = showTrackInfoAction;
_listenedTracksStorage = listenedTracksStorage;
_config = config;
_playNextAction = playNextAction;
_addToPlaylistAction = addToPlaylistAction;
}

public ITrackPO Create(
ITrackInfoProvider trackInfoProvider,
IMvxAsyncCommand<Document> optionsClickedCommand,
Track track)
Track track,
TrackSwipeType trackSwipeType = TrackSwipeType.PlayNextAndAddToPlaylist)
{
if (track == null)
return null;

return new TrackPO(
trackSwipeType,
_mediaPlayer,
_storageManager,
_connection,
Expand All @@ -59,7 +68,9 @@ public ITrackPO Create(
trackInfoProvider,
_listenedTracksStorage,
track,
_config);
_config,
_playNextAction,
_addToPlaylistAction);
}
}
}
Loading

0 comments on commit 794331a

Please sign in to comment.