Skip to content

Commit

Permalink
Merge pull request #579 from bcc-code/feature/569-add-to-playlist-for…
Browse files Browse the repository at this point in the history
…-curated-and-private-playlists

Add to Playlist for Curated and Private playlists
  • Loading branch information
akrol95 authored Oct 2, 2024
2 parents 8c2a86a + ed2c820 commit 7f3d4e7
Show file tree
Hide file tree
Showing 27 changed files with 264 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace BMM.Api.Framework.Exceptions
{
public class CollectionAlreadyInTrackCollectionException : BadRequestException
{ }
}
6 changes: 4 additions & 2 deletions BMM.Api/Framework/HTTP/ApiUris.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ public class ApiUris
public static string TrackTranscriptions = "track/{id}/transcription";
public static string TrackCover = "track/{id}/cover";
public static string TrackCollections = "track_collection/";
public static string TrackCollection = "track_collection/{id}";
public static string TrackCollectionAlbum = "track_collection/{id}/album/{albumId}";
public static string TrackCollection = "track_collection/{targetId}";
public static string TrackCollectionAlbum = "track_collection/{targetId}/album/{albumId}";
public static string TrackCollectionPlaylist = "track_collection/{targetId}/playlist/{playlistId}";
public static string TrackCollectionTrackCollection = "track_collection/{targetId}/track_collection/{playlistId}";
public static string TrackCollectionResetShare = "track_collection/{id}/reset-share";
public static string TrackCollectionUnfollow = "track_collection/{id}/unfollow";
public static string TrackCollectionTopSongs = "track_collection/top-songs";
Expand Down
2 changes: 2 additions & 0 deletions BMM.Api/Framework/HTTP/BadRequestThrower.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public async Task ThrowExceptionForBadRequest(HttpResponseMessage response)
throw new TrackNotInTrackCollectionException();
if (status.Errors.Any(e => e.StartsWith("AlbumAlreadyInTrackCollection")))
throw new AlbumAlreadyInTrackCollectionException();
if (status.Errors.Any(e => e.StartsWith("CollectionAlreadyInTrackCollection")))
throw new CollectionAlreadyInTrackCollectionException();
if (status.Errors.Any(e => e.StartsWith("You cannot follow your own track_collection")))
throw new FollowOwnTrackCollectionException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ namespace BMM.Api.Implementation.Clients.Contracts
public interface ITrackCollectionClient
{
/// <summary>Adds the tracks with the specified ids to the track collection.</summary>
Task<bool> AddTracksToTrackCollection(int id, IList<int> trackIds);
Task<bool> AddTracksToTrackCollection(int targetId, IList<int> trackIds);

Task AddAlbumToTrackCollection(int id, int albumId);
Task AddAlbumToTrackCollection(int targetId, int albumId);

Task AddPlaylistToTrackCollection(int targetId, int playlistId);

Task AddTrackCollectionToTrackCollection(int targetId, int trackCollectionId);

/// <summary>Deletes the track collection.</summary>
Task<bool> Delete(int id);
Expand Down
34 changes: 25 additions & 9 deletions BMM.Api/Implementation/Clients/TrackCollectionClient.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using BMM.Api.Abstraction;
using BMM.Api.Abstraction;
using BMM.Api.Framework;
using BMM.Api.Framework.HTTP;
using BMM.Api.Implementation.Clients.Contracts;
Expand All @@ -17,26 +13,46 @@ public TrackCollectionClient(IRequestHandler handler, ApiBaseUri baseUri, ILogge
: base(handler, baseUri, logger)
{ }

public async Task AddAlbumToTrackCollection(int id, int albumId)
public async Task AddAlbumToTrackCollection(int targetId, int albumId)
{
var uri = new UriTemplate(ApiUris.TrackCollectionAlbum);
uri.SetParameter("id", id);
uri.SetParameter("targetId", targetId);
uri.SetParameter("albumId", albumId);

var request = BuildRequest(uri, HttpMethod.Post);
await RequestIsSuccessful(request);
}

public async Task<bool> AddTracksToTrackCollection(int id, IList<int> trackIds)
public async Task<bool> AddTracksToTrackCollection(int targetId, IList<int> trackIds)
{
var uri = new UriTemplate(ApiUris.TrackCollection);
uri.SetParameter("id", id);
uri.SetParameter("targetId", targetId);

var request = BuildRequest(uri, HttpMethod.Post);
SetLinkHeader(trackIds, request);

return await RequestIsSuccessful(request);
}

public async Task AddPlaylistToTrackCollection(int targetId, int playlistId)
{
var uri = new UriTemplate(ApiUris.TrackCollectionPlaylist);
uri.SetParameter("targetId", targetId);
uri.SetParameter("playlistId", playlistId);

var request = BuildRequest(uri, HttpMethod.Post);
await RequestIsSuccessful(request);
}

public async Task AddTrackCollectionToTrackCollection(int targetId, int trackCollectionId)
{
var uri = new UriTemplate(ApiUris.TrackCollectionTrackCollection);
uri.SetParameter("targetId", targetId);
uri.SetParameter("playlistId", trackCollectionId);

var request = BuildRequest(uri, HttpMethod.Post);
await RequestIsSuccessful(request);
}

public async Task<bool> Delete(int id)
{
Expand Down
20 changes: 20 additions & 0 deletions BMM.Core/Extensions/ActionSheetConfigExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Acr.UserDialogs;
using BMM.Core.Constants;
using BMM.Core.Helpers;
using BMM.Core.Implementations.Localization;
using BMM.Core.Implementations.Localization.Interfaces;
using BMM.Core.Translation;

namespace BMM.Core.Extensions;

public static class ActionSheetConfigExtensions
{
private static IBMMLanguageBinder TextSource => BMMLanguageBinderLocator.TextSource;

public static ActionSheetConfig AddOptionForAddToTrackCollection(this ActionSheetConfig actionSheetConfig, Func<Task> action)
{
return actionSheetConfig.AddHandled(TextSource[Translations.UserDialogs_AddAllToPlaylist],
async () => await action(),
ImageResourceNames.IconFavorites);
}
}
1 change: 1 addition & 0 deletions BMM.Core/Helpers/IShareLink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public interface IShareLink
Task Share(Track track);
Task Share(Album album);
Task Share(Contributor contributor);
Task Share(Playlist playlist);
Task PerformRequestFor(string link);
}
}
5 changes: 5 additions & 0 deletions BMM.Core/Helpers/ShareLink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public async Task Share(Contributor contributor)
await GenerateLinkAndShare($"playlist/contributor/{contributor.Id}/{contributor.Name}");
}

public async Task Share(Playlist playlist)
{
await GenerateLinkAndShare($"playlist/curated/{playlist.Id}/{playlist.Title}");
}

public async Task PerformRequestFor(string link)
{
await Microsoft.Maui.ApplicationModel.DataTransfer.Share.RequestAsync(new ShareTextRequest
Expand Down
4 changes: 4 additions & 0 deletions BMM.Core/Implementations/Analytics/Event.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,9 @@ public class Event
public const string ProblemWithOfflineFileDetected = "Problem with offline file detected";
public const string NavigateToExternalLink = "Navigate to external link";
public const string BCCMediaOpenedFromPlayer = "BCC Media opened from player";
public const string AlbumAddedToTrackCollection = "added album to track_collection";
public const string TrackAddedToTrackCollection = "added track to track_collection";
public const string PlaylistAddedToTrackCollection = "added playlist to track_collection";
public const string TrackCollectionAddedToTrackCollection = "added track collection to track_collection";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,24 @@ public CachedTrackCollectionClientDecorator(ITrackCollectionClient client, IClie
_clientCache = clientCache;
}

public Task<bool> AddTracksToTrackCollection(int id, IList<int> trackIds)
public Task<bool> AddTracksToTrackCollection(int targetId, IList<int> trackIds)
{
return _client.AddTracksToTrackCollection(id, trackIds);
return _client.AddTracksToTrackCollection(targetId, trackIds);
}

public Task AddAlbumToTrackCollection(int id, int albumId)
public Task AddAlbumToTrackCollection(int targetId, int albumId)
{
return _client.AddAlbumToTrackCollection(id, albumId);
return _client.AddAlbumToTrackCollection(targetId, albumId);
}

public Task AddPlaylistToTrackCollection(int targetId, int playlistId)
{
return _client.AddPlaylistToTrackCollection(targetId, playlistId);
}

public Task AddTrackCollectionToTrackCollection(int targetId, int trackCollectionId)
{
return _client.AddTrackCollectionToTrackCollection(targetId, trackCollectionId);
}

public Task<bool> Delete(int id)
Expand Down
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;
using BMM.Api.Implementation.Clients.Contracts;
using BMM.Api.Implementation.Models;
using BMM.Core.Implementations.Analytics;
Expand All @@ -18,14 +16,24 @@ public MeasuringTrackCollectionClientDecorator(ITrackCollectionClient client, IC
_stopwatchManager = stopwatchManager;
}

public Task<bool> AddTracksToTrackCollection(int id, IList<int> trackIds)
public Task<bool> AddTracksToTrackCollection(int targetId, IList<int> trackIds)
{
return _client.AddTracksToTrackCollection(id, trackIds);
return _client.AddTracksToTrackCollection(targetId, trackIds);
}

public Task AddAlbumToTrackCollection(int id, int albumId)
public Task AddAlbumToTrackCollection(int targetId, int albumId)
{
return _client.AddAlbumToTrackCollection(id, albumId);
return _client.AddAlbumToTrackCollection(targetId, albumId);
}

public Task AddPlaylistToTrackCollection(int targetId, int playlistId)
{
return _client.AddPlaylistToTrackCollection(targetId, playlistId);
}

public Task AddTrackCollectionToTrackCollection(int targetId, int trackCollectionId)
{
return _client.AddTrackCollectionToTrackCollection(targetId, trackCollectionId);
}

public Task<bool> Delete(int id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public async Task AddToTrackCollection(TrackCollection trackCollection, int id,
if (type == DocumentType.Album)
{
await _bmmClient.TrackCollection.AddAlbumToTrackCollection(trackCollection.Id, id);
_analytics.LogEvent("added album to track_collection",
_analytics.LogEvent(Event.AlbumAddedToTrackCollection,
new Dictionary<string, object>
{
{"AlbumId", id},
Expand All @@ -78,13 +78,33 @@ public async Task AddToTrackCollection(TrackCollection trackCollection, int id,
else if (type == DocumentType.Track)
{
await _bmmClient.TrackCollection.AddTracksToTrackCollection(trackCollection.Id, new List<int> {id});
_analytics.LogEvent("added track to track_collection",
_analytics.LogEvent(Event.TrackAddedToTrackCollection,
new Dictionary<string, object>
{
{"TrackId", id},
{"Origin", origin}
});
}
else if (type == DocumentType.Playlist)
{
await _bmmClient.TrackCollection.AddPlaylistToTrackCollection(trackCollection.Id, id);
_analytics.LogEvent(Event.PlaylistAddedToTrackCollection,
new Dictionary<string, object>
{
{"PlaylistId", id},
{"Origin", origin}
});
}
else if (type == DocumentType.TrackCollection)
{
await _bmmClient.TrackCollection.AddTrackCollectionToTrackCollection(trackCollection.Id, id);
_analytics.LogEvent(Event.TrackCollectionAddedToTrackCollection,
new Dictionary<string, object>
{
{"TrackCollectionId", id},
{"Origin", origin}
});
}
else
{
throw new UnsupportedDocumentTypeException();
Expand Down
2 changes: 2 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.

2 changes: 2 additions & 0 deletions BMM.Core/Translation/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@
"SearchHint": "Search",
"FailedToAdd": "Failed to add the track to the playlist. Please try again later.",
"AlbumFailedToAddAlreadyExists": "This album is already in your playlist.",
"CollectionAlreadyInTrackCollection": "Collection is already added to your playlist.",
"TrackAlreadyExistInTrackCollection": "Track already exists in playlist {0}",
"FailedToAddAlbum": "Failed to add the album to the playlist because it contains albums.",
"FailedToAddUnknownType": "Adding a \"{0}\" to a playlist is currently not supported.",
Expand Down Expand Up @@ -456,6 +457,7 @@
"Contributor.Play": "Play",
"Contributor.Share": "Share contributor",
"OfflineTrackCollection.DeletePlaylist": "Delete playlist",
"AddAllToPlaylist": "Add all tracks to playlist",
"Cancel": "Cancel"
},
"Notifications": {
Expand Down
2 changes: 1 addition & 1 deletion BMM.Core/ViewModels/AlbumViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public AlbumViewModel(
_documentsPOFactory = documentsPOFactory;
_playOrResumePlayAction.AttachDataContext(this);

AddToPlaylistCommand = new ExceptionHandlingCommand(async () => await AddAlbumToTrackCollection(Album.Id));
AddToPlaylistCommand = new ExceptionHandlingCommand(async () => await AddToTrackCollection(Album.Id, DocumentType.Album));
ShareCommand = new ExceptionHandlingCommand(async () => await shareLink.Share(_album));

var audiobookStyler = new AudiobookPodcastInfoProvider(TrackInfoProvider);
Expand Down
37 changes: 27 additions & 10 deletions BMM.Core/ViewModels/Base/BaseViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Acr.UserDialogs;
using Acr.UserDialogs;
using BMM.Api;
using BMM.Api.Abstraction;
using BMM.Api.Framework;
using BMM.Api.Implementation.Models;
using BMM.Core.Constants;
using BMM.Core.Extensions;
using BMM.Core.GuardedActions.TrackOptions.Interfaces;
using BMM.Core.GuardedActions.TrackOptions.Parameters;
using BMM.Core.Helpers;
Expand Down Expand Up @@ -195,7 +191,7 @@ protected virtual async Task OptionsAction(Document item)
var album = (Album)item;
bmmUserDialogs.ActionSheet(new ActionSheetConfig()
.SetTitle(album.Title)
.AddHandled(TextSource[Translations.UserDialogs_Album_AddToPlaylist], async () => await AddAlbumToTrackCollection(album.Id), ImageResourceNames.IconFavorites)
.AddHandled(TextSource[Translations.UserDialogs_Album_AddToPlaylist], async () => await AddToTrackCollection(album.Id, DocumentType.Album), ImageResourceNames.IconFavorites)
.AddHandled(TextSource[Translations.UserDialogs_Album_Share], async () => await Mvx.IoCProvider.Resolve<IShareLink>().Share(album), ImageResourceNames.IconShare)
.SetCancel(TextSource[Translations.UserDialogs_Cancel]));
break;
Expand Down Expand Up @@ -231,6 +227,21 @@ protected virtual async Task OptionsAction(Document item)
var podcastId = item.Id;
await NavigationService.Navigate<AutomaticDownloadViewModel, int>(podcastId);
break;

case DocumentType.Playlist:
var playlist = (Playlist)item;

bmmUserDialogs.ActionSheet(new ActionSheetConfig()
.SetTitle(playlist.Title)
.AddOptionForAddToTrackCollection(async () => await AddToTrackCollection(
playlist.Id,
DocumentType.Playlist))
.AddHandled(TextSource[Translations.TrackCollectionViewModel_SharePlaylist],
async () => await Mvx.IoCProvider.Resolve<IShareLink>().Share(playlist),
ImageResourceNames.IconShare)
.SetCancel(TextSource[Translations.UserDialogs_Cancel]));

break;

default:
throw new ArgumentOutOfRangeException();
Expand All @@ -250,6 +261,9 @@ private void ShowActionSheetIfSharedTrackCollection(
{
userDialogs.ActionSheet(new ActionSheetConfig()
.SetTitle(trackCollection.Name)
.AddOptionForAddToTrackCollection(async () => await AddToTrackCollection(
trackCollection.Id,
DocumentType.TrackCollection))
.AddHandled(
TextSource[Translations.TrackCollectionViewModel_RemovePlaylist],
async () => await RemoveSharedPlaylist(trackCollection.Id),
Expand All @@ -265,6 +279,9 @@ private void ShowActionSheetIfPrivateTrackCollection(
{
userDialogs.ActionSheet(new ActionSheetConfig()
.SetTitle(trackCollection.Name)
.AddOptionForAddToTrackCollection(async () => await AddToTrackCollection(
trackCollection.Id,
DocumentType.TrackCollection))
.AddHandled(TextSource[Translations.TrackCollectionViewModel_SharePlaylist],
async () =>
{
Expand Down Expand Up @@ -437,12 +454,12 @@ protected virtual async Task<bool> DeleteTrackCollection(TrackCollection item)
return false;
}

protected Task AddAlbumToTrackCollection(int albumId)
protected Task AddToTrackCollection(int documentId, DocumentType documentType)
{
return NavigationService.Navigate<TrackCollectionsAddToViewModel, TrackCollectionsAddToViewModel.Parameter>(new TrackCollectionsAddToViewModel.Parameter
{
DocumentId = albumId,
DocumentType = DocumentType.Album,
DocumentId = documentId,
DocumentType = documentType,
OriginViewModel = PlaybackOriginString()
});
}
Expand Down
Loading

0 comments on commit 7f3d4e7

Please sign in to comment.