Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delete from queue #639

Merged
merged 7 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions BMM.Core/Constants/ViewConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ public class ViewConstants
public const float LongAnimationDuration = 0.6f;
public const float DefaultAnimationDuration = 0.3f;
public const float QuickAnimationDuration = DefaultAnimationDuration / 2;
public const float SwiftAnimationDuration = 0.1f;
public const int SwiftAnimationDurationInMilliseconds = (int)(SwiftAnimationDuration * 1000);
public const int DefaultAnimationDurationInMilliseconds = (int)(DefaultAnimationDuration * 1000);
public const int LongAnimationDurationInMilliseconds = (int)(LongAnimationDuration * 1000);
public const int QuickAnimationDurationInMilliseconds = (int)(QuickAnimationDuration * 1000);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,12 @@ await _mvxNavigationService.Navigate<AlbumViewModel, Album>(new Album
{
await _showTrackInfoAction.ExecuteGuarded(track);
})));

options.AddIf(() => sourceVM is QueueViewModel,
new StandardIconOptionPO(
_bmmLanguageBinder[Translations.QueueViewModel_RemoveFromQueueOption],
ImageResourceNames.IconRemove,
new MvxAsyncCommand(() => _mediaPlayer.DeleteFromQueue(track))));

return options;
}
Expand Down
24 changes: 22 additions & 2 deletions BMM.Core/Helpers/ListHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,32 @@ public static int FindIndex<T>(this IList<T> source, Predicate<T> match, int sta
for (int i = startIndex; i < source.Count; i++)
{
if (match(source[i]))
{
return i;
}
}

return NumericConstants.Undefined;
}

public static T FindNextAfter<T>(this IList<T> source, T item)
{
int nextIndex = source
.IndexOf(item) + 1;

if (nextIndex >= source.Count)
return default;

return source[nextIndex];
}

public static T FindPreviousBefore<T>(this IList<T> source, T item)
{
int previousIndex = source
.IndexOf(item) - 1;

if (previousIndex < NumericConstants.Zero)
return default;

return source[previousIndex];
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
using BMM.Core.Extensions;
using BMM.Core.Implementations.Device;
using BMM.Core.Implementations.LiveRadio;
using BMM.Core.Implementations.Localization.Interfaces;
using BMM.Core.Implementations.UI;
using BMM.Core.Messages.MediaPlayer;
using BMM.Core.NewMediaPlayer;
using BMM.Core.NewMediaPlayer.Abstractions;
using BMM.Core.NewMediaPlayer.Constants;
using BMM.Core.Translation;
using BMM.Core.ViewModels;
using MvvmCross.Navigation;
using MvvmCross.Plugin.Messenger;
Expand All @@ -31,6 +34,8 @@ public class ViewModelHandlingMediaPlayerDecorator : IMediaPlayer

private readonly ILiveTime _liveTime;
private readonly IMvxMessenger _mvxMessenger;
private readonly IToastDisplayer _toastDisplayer;
private readonly IBMMLanguageBinder _bmmLanguageBinder;

private bool _isViewmodelShown;

Expand All @@ -42,7 +47,9 @@ public ViewModelHandlingMediaPlayerDecorator(
IMediaPlayerInitializer mediaPlayerInitializer,
IPlayerErrorHandler playerErrorHandler,
ILiveTime liveTime,
IMvxMessenger mvxMessenger)
IMvxMessenger mvxMessenger,
IToastDisplayer toastDisplayer,
IBMMLanguageBinder bmmLanguageBinder)
{
_deviceInfo = deviceInfo;
_navigationService = navigationService;
Expand All @@ -52,6 +59,8 @@ public ViewModelHandlingMediaPlayerDecorator(
_playerErrorHandler = playerErrorHandler;
_liveTime = liveTime;
_mvxMessenger = mvxMessenger;
_toastDisplayer = toastDisplayer;
_bmmLanguageBinder = bmmLanguageBinder;

_mediaPlayer.ContinuingPreviousSession = () => { ShowViewmodelIfNecessary(); };
}
Expand Down Expand Up @@ -195,6 +204,18 @@ public void Stop()

public decimal CurrentPlaybackSpeed => _mediaPlayer.CurrentPlaybackSpeed;

public async Task DeleteFromQueue(IMediaTrack track)
{
if (track.Id == CurrentTrack?.Id)
{
await _toastDisplayer.WarnAsync(_bmmLanguageBinder[Translations.QueueViewModel_CannotRemoveFromQueue]);
return;
}

await _mediaPlayer.DeleteFromQueue(track);
await _toastDisplayer.Success(_bmmLanguageBinder[Translations.QueueViewModel_TrackRemovedFromQueue]);
}

public Task<bool> AddToEndOfQueue(IMediaTrack track, string playbackOrigin, bool ignoreIfAlreadyAdded = false)
{
if (ignoreIfAlreadyAdded && _queue.Tracks.Any(t => t.Equals(track)))
Expand Down
10 changes: 10 additions & 0 deletions BMM.Core/Messages/MediaPlayer/QueueChangedMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using MvvmCross.Plugin.Messenger;

namespace BMM.Core.Messages.MediaPlayer;

public class QueueChangedMessage : MvxMessage
{
public QueueChangedMessage(object sender) : base(sender)
{
}
}
7 changes: 7 additions & 0 deletions BMM.Core/Models/Enums/SwipePlacement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace BMM.Core.Models.Enums;

public enum SwipePlacement
{
Left,
Right
}
7 changes: 7 additions & 0 deletions BMM.Core/Models/POs/Tracks/TrackPO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using BMM.Core.Constants;
using BMM.Core.Extensions;
using BMM.Core.GuardedActions.Tracks.Interfaces;
using BMM.Core.Helpers;
using BMM.Core.Implementations.Downloading.DownloadQueue;
using BMM.Core.Implementations.FileStorage;
using BMM.Core.Implementations.FirebaseRemoteConfig;
Expand Down Expand Up @@ -65,13 +66,19 @@ public TrackPO(
{
await optionsClickedCommand.ExecuteAsync(Track);
});

DeleteFromQueueCommand = new ExceptionHandlingCommand(async () =>
{
await mediaPlayer.DeleteFromQueue(track);
});

RefreshState().FireAndForget();
SetTrackInformation();
}

public IMvxAsyncCommand ShowTrackInfoCommand { get; }
public IMvxAsyncCommand OptionButtonClickedCommand { get; }
public IMvxAsyncCommand DeleteFromQueueCommand { get; }

private void SetTrackInformation()
{
Expand Down
2 changes: 2 additions & 0 deletions BMM.Core/NewMediaPlayer/Abstractions/IMediaPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ public interface ICommonMediaPlayer

decimal CurrentPlaybackSpeed { get; }

Task DeleteFromQueue(IMediaTrack track);

Task<bool> AddToEndOfQueue(IMediaTrack track, string playbackOrigin, bool ignoreIfAlreadyAdded = false);

Task<bool> QueueToPlayNext(IMediaTrack track, string playbackOrigin);
Expand Down
7 changes: 4 additions & 3 deletions BMM.Core/NewMediaPlayer/Abstractions/IMediaQueue.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using BMM.Api.Abstraction;
using BMM.Api.Abstraction;

namespace BMM.Core.NewMediaPlayer.Abstractions
{
Expand All @@ -13,8 +11,11 @@ public interface IMediaQueue
Task<bool> PlayNext(IMediaTrack track, IMediaTrack currentPlayedTrack);

Task<bool> Append(IMediaTrack track);

void Delete(IMediaTrack track);

IList<IMediaTrack> Tracks { get; }
bool HasPendingChanges { get; set; }

bool IsSameQueue(IList<IMediaTrack> newMediaTracks);

Expand Down
22 changes: 19 additions & 3 deletions BMM.Core/NewMediaPlayer/MediaQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
using BMM.Core.Implementations.Localization.Interfaces;
using BMM.Core.Implementations.Media;
using BMM.Core.Implementations.UI;
using BMM.Core.Messages.MediaPlayer;
using BMM.Core.NewMediaPlayer.Abstractions;
using BMM.Core.Translation;
using BMM.Core.ViewModels.MyContent;
using MvvmCross;
using MvvmCross.Base;
using MvvmCross.Localization;
using MvvmCross.Plugin.Messenger;

namespace BMM.Core.NewMediaPlayer
{
Expand All @@ -26,19 +28,23 @@ public class MediaQueue : IMediaQueue
private readonly MediaFileUrlSetter _mediaFileUrlSetter;
private readonly IToastDisplayer _toastDisplayer;
private readonly IBMMLanguageBinder _bmmLanguageBinder;

public IList<IMediaTrack> Tracks { get; private set; }
private readonly IMvxMessenger _mvxMessenger;

public MediaQueue(
MediaFileUrlSetter mediaFileUrlSetter,
IToastDisplayer toastDisplayer,
IBMMLanguageBinder bmmLanguageBinder)
IBMMLanguageBinder bmmLanguageBinder,
IMvxMessenger mvxMessenger)
{
_mediaFileUrlSetter = mediaFileUrlSetter;
_toastDisplayer = toastDisplayer;
_bmmLanguageBinder = bmmLanguageBinder;
_mvxMessenger = mvxMessenger;
Tracks = new List<IMediaTrack>();
}

public IList<IMediaTrack> Tracks { get; private set; }
public bool HasPendingChanges { get; set; }

public void Replace(IMediaTrack track)
{
Expand Down Expand Up @@ -119,6 +125,16 @@ public async Task<bool> PlayNext(IMediaTrack track, IMediaTrack currentPlayedTra

return true;
}

public void Delete(IMediaTrack track)
{
lock (_lock)
{
Tracks.Remove(track);
_mvxMessenger.Publish(new QueueChangedMessage(this));
HasPendingChanges = true;
}
}

// todo this should be handled without checking the UI!
private async Task<bool> FileNotDownloadedButInOfflineViewModel(IMediaTrack track)
Expand Down
14 changes: 14 additions & 0 deletions BMM.Core/NewMediaPlayer/ShuffleableQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ public Task<bool> Append(IMediaTrack track)
return _queue.Append(track);
}

public void Delete(IMediaTrack track)
{
if (IsShuffleEnabled)
_shuffledTracks.Remove(track);

_queue.Delete(track);
}

public Task<bool> PlayNext(IMediaTrack track, IMediaTrack currentPlayedTrack)
{
if (IsShuffleEnabled)
Expand All @@ -61,6 +69,12 @@ public Task<bool> PlayNext(IMediaTrack track, IMediaTrack currentPlayedTrack)

public IList<IMediaTrack> Tracks => IsShuffleEnabled ? _shuffledTracks : _queue.Tracks;

public bool HasPendingChanges
{
get => _queue.HasPendingChanges;
set => _queue.HasPendingChanges = value;
}

public bool IsSameQueue(IList<IMediaTrack> newMediaTracks)
{
return _queue.IsSameQueue(newMediaTracks);
Expand Down
4 changes: 4 additions & 0 deletions BMM.Core/Translation/en/Translations.designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion BMM.Core/Translation/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,11 @@
"Read": "Read"
},
"QueueViewModel": {
"Title": "Queue"
"Title": "Queue",
"Delete": "Delete",
"CannotRemoveFromQueue": "Cannot remove currently playing track from the queue",
"TrackRemovedFromQueue": "Track has been removed from the queue",
"RemoveFromQueueOption": "Remove from queue"
},
"SearchViewModel": {
"Title": "Search",
Expand Down
3 changes: 3 additions & 0 deletions BMM.Core/ViewModels/OptionsListViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ namespace BMM.Core.ViewModels
{
public class OptionsListViewModel : BaseViewModel<IOptionsListParameter>, ITrackOptionsViewModel
{
private const int TimeForDialogCloseInMillis = 250;

public OptionsListViewModel()
{
CloseOptionsCommand = new MvxCommand(() => CloseInteraction.Raise());
OptionSelectedCommand = new MvxAsyncCommand<StandardIconOptionPO>(async option =>
{
await CloseCommand.ExecuteAsync();
await Task.Delay(TimeForDialogCloseInMillis);
option.ClickCommand.Execute();
});
}
Expand Down
31 changes: 29 additions & 2 deletions BMM.Core/ViewModels/QueueViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,60 @@
using System.Threading.Tasks;
using BMM.Api.Abstraction;
using BMM.Api.Implementation.Models;
using BMM.Core.Extensions;
using BMM.Core.Implementations.Factories.Tracks;
using BMM.Core.Implementations.UI;
using BMM.Core.Messages.MediaPlayer;
using BMM.Core.Models.POs.Base;
using BMM.Core.Models.POs.Base.Interfaces;
using BMM.Core.Models.POs.Tracks;
using BMM.Core.NewMediaPlayer.Abstractions;
using BMM.Core.ViewModels.Base;
using MvvmCross;
using MvvmCross.Plugin.Messenger;

namespace BMM.Core.ViewModels
{
public class QueueViewModel : DocumentsViewModel
{
private readonly IMediaQueue _mediaQueue;
private readonly ITrackPOFactory _trackPOFactory;
private readonly IMediaPlayer _mediaPlayer;
private readonly IMvxMessenger _mvxMessenger;
private MvxSubscriptionToken _token;

public QueueViewModel(
IMediaQueue mediaQueue,
ITrackPOFactory trackPOFactory)
ITrackPOFactory trackPOFactory,
IMediaPlayer mediaPlayer,
IMvxMessenger mvxMessenger)
{
_mediaQueue = mediaQueue;
_trackPOFactory = trackPOFactory;
_mediaPlayer = mediaPlayer;
_mvxMessenger = mvxMessenger;
}

public override void ViewAppeared()
{
base.ViewAppeared();
_token = _mvxMessenger.Subscribe<QueueChangedMessage>(QueueChangedAction);
}

public override void ViewDisappeared()
{
base.ViewDisappeared();
_mvxMessenger.UnsubscribeSafe<QueueChangedMessage>(_token);
}

private async void QueueChangedAction(QueueChangedMessage queueChangedMessage)
{
await Refresh();
}

protected override async Task DocumentAction(IDocumentPO item, IList<Track> list)
{
await Mvx.IoCProvider.Resolve<IMediaPlayer>().Play(_mediaQueue.Tracks, ((TrackPO)item).Track);
await _mediaPlayer.Play(_mediaQueue.Tracks, ((TrackPO)item).Track);
}

public async override Task<IEnumerable<IDocumentPO>> LoadItems(CachePolicy policy = CachePolicy.UseCacheAndRefreshOutdated)
Expand Down
Loading