Skip to content

Commit

Permalink
Merge pull request #554 from bcc-code/feature/downloaded-curated-play…
Browse files Browse the repository at this point in the history
…lists

Feature/downloaded curated playlists
  • Loading branch information
kkuepper authored Jul 11, 2024
2 parents afa0cf1 + 86a6851 commit b677884
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 58 deletions.
1 change: 1 addition & 0 deletions BMM.Core/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ public override void Initialize()
Mvx.IoCProvider.LazyConstructAndRegisterSingleton<IDocumentsPOFactory, DocumentsPOFactory>();
Mvx.IoCProvider.LazyConstructAndRegisterSingleton<ITrackPOFactory, TrackPOFactory>();
Mvx.IoCProvider.LazyConstructAndRegisterSingleton<ITrackCollectionPOFactory, TrackCollectionPOFactory>();
Mvx.IoCProvider.LazyConstructAndRegisterSingleton<IPlaylistPOFactory, PlaylistPOFactory>();
Mvx.IoCProvider.LazyConstructAndRegisterSingleton<IListeningStreakPOFactory, ListeningStreakPOFactory>();
Mvx.IoCProvider.LazyConstructAndRegisterSingleton<IDiscoverSectionHeaderPOFactory, DiscoverSectionHeaderPOFactory>();
Mvx.IoCProvider.LazyConstructAndRegisterSingleton<ITilePOFactory, TilePOFactory>();
Expand Down
13 changes: 5 additions & 8 deletions BMM.Core/Implementations/Factories/DocumentsPOFactory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Collections.Generic;
using BMM.Api.Implementation.Models;
using BMM.Core.Implementations.Factories.ContinueListening;
using BMM.Core.Implementations.Factories.DiscoverSection;
Expand All @@ -9,20 +8,15 @@
using BMM.Core.Implementations.Factories.YearInReview;
using BMM.Core.Implementations.TrackInformation.Strategies;
using BMM.Core.Models.POs.Albums;
using BMM.Core.Models.POs.Base;
using BMM.Core.Models.POs.Base.Interfaces;
using BMM.Core.Models.POs.BibleStudy;
using BMM.Core.Models.POs.Carousels;
using BMM.Core.Models.POs.Contributors;
using BMM.Core.Models.POs.InfoMessages;
using BMM.Core.Models.POs.Other;
using BMM.Core.Models.POs.Playlists;
using BMM.Core.Models.POs.Podcasts;
using BMM.Core.Models.POs.Recommendations;
using BMM.Core.Models.POs.Tiles;
using BMM.Core.Models.POs.Tracks;
using BMM.Core.Models.POs.Tracks.Interfaces;
using BMM.Core.Models.POs.YearInReview;
using MvvmCross.Commands;
using MvvmCross.Navigation;

Expand All @@ -37,6 +31,7 @@ public class DocumentsPOFactory : IDocumentsPOFactory
private readonly ITilePOFactory _tilePOFactory;
private readonly IYearInReviewTeaserPOFactory _yearInReviewTeaserPOFactory;
private readonly IHighlightedTextTrackPOFactory _highlightedTextTrackPOFactory;
private readonly IPlaylistPOFactory _playlistPOFactory;
private readonly IMvxNavigationService _mvxNavigationService;

public DocumentsPOFactory(
Expand All @@ -47,7 +42,8 @@ public DocumentsPOFactory(
ITilePOFactory tilePOFactory,
IYearInReviewTeaserPOFactory yearInReviewTeaserPOFactory,
IHighlightedTextTrackPOFactory highlightedTextTrackPOFactory,
IMvxNavigationService mvxNavigationService)
IMvxNavigationService mvxNavigationService,
IPlaylistPOFactory playlistPOFactory)
{
_trackPOFactory = trackPOFactory;
_trackCollectionPOFactory = trackCollectionPOFactory;
Expand All @@ -57,6 +53,7 @@ public DocumentsPOFactory(
_yearInReviewTeaserPOFactory = yearInReviewTeaserPOFactory;
_highlightedTextTrackPOFactory = highlightedTextTrackPOFactory;
_mvxNavigationService = mvxNavigationService;
_playlistPOFactory = playlistPOFactory;
}

public IEnumerable<IDocumentPO> Create(
Expand Down Expand Up @@ -108,7 +105,7 @@ public IEnumerable<IDocumentPO> Create(
documentsPOList.Add(_discoverSectionHeaderPOFactory.Create(discoverSectionHeader));
break;
case Playlist playlist:
documentsPOList.Add(new PlaylistPO(playlist));
documentsPOList.Add(_playlistPOFactory.Create(playlist));
break;
case ListeningStreak listeningStreak:
documentsPOList.Add(_listeningStreakPOFactory.Create(listeningStreak));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using BMM.Api.Implementation.Models;
using BMM.Core.Models.POs.Playlists;

namespace BMM.Core.Implementations.Factories.TrackCollections;

public interface IPlaylistPOFactory
{
PlaylistPO Create(Playlist playlist);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using BMM.Api.Implementation.Models;
using BMM.Core.Models.POs.Playlists;

namespace BMM.Core.Implementations.Factories.TrackCollections;

public class PlaylistPOFactory : IPlaylistPOFactory
{
public PlaylistPO Create(Playlist playlist)
{
return new PlaylistPO(playlist);
}
}
42 changes: 33 additions & 9 deletions BMM.Core/ViewModels/MyContent/DownloadedContentViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using BMM.Api.Implementation.Models;
using BMM.Core.Implementations.Factories.TrackCollections;
using BMM.Core.Implementations.FileStorage;
using BMM.Core.Implementations.PlaylistPersistence;
using BMM.Core.Implementations.Podcasts;
using BMM.Core.Implementations.TrackCollections;
using BMM.Core.Models.POs.Base;
Expand All @@ -24,18 +25,24 @@ namespace BMM.Core.ViewModels.MyContent
public class DownloadedContentViewModel : ContentBaseViewModel
{
private readonly IConnection _connection;
private readonly IOfflinePlaylistStorage _playlistOfflineStorage;
private readonly IPlaylistPOFactory _playlistPOFactory;

public bool IsEmpty { get; private set; }

public DownloadedContentViewModel(
IStorageManager storageManager,
IConnection connection,
ITrackCollectionPOFactory trackCollectionPOFactory)
ITrackCollectionPOFactory trackCollectionPOFactory,
IOfflinePlaylistStorage playlistOfflineStorage,
IPlaylistPOFactory playlistPOFactory)
: base(
storageManager,
trackCollectionPOFactory)
{
_connection = connection;
_playlistOfflineStorage = playlistOfflineStorage;
_playlistPOFactory = playlistPOFactory;
}

protected override void AttachEvents()
Expand Down Expand Up @@ -63,7 +70,7 @@ private void DocumentsOnCollectionChanged(object sender, NotifyCollectionChanged
RaisePropertyChanged(() => IsEmpty);
}

private async Task<IList<TrackCollectionPO>> TrackCollectionContainOfflineFiles(IEnumerable<TrackCollectionPO> allCollections, CachePolicy cachePolicy)
private async Task<IList<TrackCollectionPO>> TrackCollectionContainingOfflineFiles(IEnumerable<TrackCollectionPO> allCollections, CachePolicy cachePolicy)
{
var offlineCollection = allCollections?.Where(tc => tc.IsAvailableOffline).ToList();
var isOnline = _connection.GetStatus() == ConnectionStatus.Online;
Expand Down Expand Up @@ -92,19 +99,36 @@ public override async Task Load()
public override async Task<IEnumerable<IDocumentPO>> LoadItems(CachePolicy policy = CachePolicy.UseCacheAndRefreshOutdated)
{
var allCollectionsExceptMyTracks = (await base.LoadItems(policy))?.OfType<TrackCollectionPO>();
var offlineTrackCollections = await TrackCollectionContainingOfflineFiles(allCollectionsExceptMyTracks, policy);
var offlinePlaylists = await BuildDownloadedCuratedPlaylists();

var offlineTrackCollections = await TrackCollectionContainOfflineFiles(allCollectionsExceptMyTracks, policy);
var items = new List<DocumentPO>();

var offlineTrackCollectionsPlusPinnedItems = new List<DocumentPO>();

offlineTrackCollectionsPlusPinnedItems.AddRange(await BuildPinnedItems());
items.AddRange(await BuildPinnedItems());
items.AddRange(offlinePlaylists);
if (offlineTrackCollections != null)
offlineTrackCollectionsPlusPinnedItems.AddRange(offlineTrackCollections);
items.AddRange(offlineTrackCollections);

if (offlineTrackCollectionsPlusPinnedItems.Count == 0)
if (items.Count == 0)
IsEmpty = true;

return offlineTrackCollectionsPlusPinnedItems;
return items;
}

private async Task<IEnumerable<DocumentPO>> BuildDownloadedCuratedPlaylists()
{
var documents = new List<DocumentPO>();
IList<Playlist> playlists = await Client.Playlist.GetAll(CachePolicy.UseCache);
var downloadedPlaylistIds = await _playlistOfflineStorage.GetPlaylistIds();
foreach (var playlist in playlists.OrderBy(x => x.Title))
{
if (downloadedPlaylistIds.Contains(playlist.Id))
{
documents.Add(_playlistPOFactory.Create(playlist));
}
}

return documents;
}

private async Task<IEnumerable<PinnedItemPO>> BuildPinnedItems()
Expand Down
9 changes: 6 additions & 3 deletions BMM.Core/ViewModels/PlayerBaseViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using BMM.Core.ViewModels.Base;
using System;
using System.Threading.Tasks;
using BMM.Api.Abstraction;
using BMM.Api.Implementation.Models;
using BMM.Core.Extensions;
Expand Down Expand Up @@ -31,7 +29,12 @@ public class PlayerBaseViewModel : BaseViewModel
public MvxCommand PlayPauseCommand { get; }

public bool IsLiked => CurrentTrack?.IsLiked ?? false;


public override string PlaybackOriginString(int? index = null)
{
return _currentTrack.PlaybackOrigin;
}

/// <summary>
/// When changing the song on Android, exo player sends few current track updates, where few of them is just null.
///
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using BMM.Api.Abstraction;
using BMM.Api.Abstraction;
using BMM.Api.Framework;
using BMM.Api.Implementation.Models;
using BMM.Core.Implementations.Factories.TrackCollections;
using BMM.Core.Implementations.FileStorage;
using BMM.Core.Implementations.TrackCollections;
using BMM.Core.Implementations.PlaylistPersistence;
using BMM.Core.Test.Unit.ViewModels.Base;
using BMM.Core.ViewModels.MyContent;
using Moq;
using NUnit.Framework;

namespace BMM.Core.Test.Unit.ViewModels
{
[TestFixture]
public class MyContentTrackCollectionsViewModelTests : BaseViewModelTests
{
private readonly Mock<IConnection> _connectionMock = new Mock<IConnection>();
private readonly Mock<IOfflinePlaylistStorage> _playlistOfflineStorageMock = new Mock<IOfflinePlaylistStorage>();

public override void SetUp()
{
base.SetUp();
_connectionMock.Setup(x => x.GetStatus()).Returns(ConnectionStatus.Online);
_playlistOfflineStorageMock.Setup(x => x.GetPlaylistIds()).ReturnsAsync(new HashSet<int>());

Client.Setup(x => x.Playlist.GetAll(It.IsAny<CachePolicy>()))
.Returns(Task.FromResult<IList<Playlist>>(new List<Playlist>()));
}

[Test]
Expand All @@ -40,7 +42,9 @@ public async Task LoadItems_ShouldHandleNullValueAndDisplayEmptyDocumentIfConnec
var newestViewModel = new DownloadedContentViewModel(
new Mock<IStorageManager>().Object,
_connectionMock.Object,
new Mock<ITrackCollectionPOFactory>().Object);
new Mock<ITrackCollectionPOFactory>().Object,
_playlistOfflineStorageMock.Object,
new PlaylistPOFactory());
newestViewModel.TextSource = TextResource.Object;

// Act
Expand Down Expand Up @@ -73,7 +77,9 @@ public async Task LoadItems_ShouldHandleNullValueAndDisplayEmptyDocumentIfConnec
var newestViewModel = new DownloadedContentViewModel(
mockStorage.Object,
_connectionMock.Object,
new Mock<ITrackCollectionPOFactory>().Object);
new Mock<ITrackCollectionPOFactory>().Object,
_playlistOfflineStorageMock.Object,
new PlaylistPOFactory());

newestViewModel.TextSource = TextResource.Object;
_connectionMock.Setup(x => x.GetStatus()).Returns(ConnectionStatus.Offline);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
android:gravity="center"
app:cardCornerRadius="@dimen/corner_radius_mini"
app:cardElevation="0dp"
android:padding="2dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
Expand Down
14 changes: 8 additions & 6 deletions BMM.UI.Android/Resources/layout/listitem_pinned_item.axml
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,26 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:minHeight="@dimen/row_document_height"
android:minHeight="@dimen/row_feature_item_height"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/padding_medium"
android:paddingRight="@dimen/padding_medium"
android:showDividers="end"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="match_parent"
android:minHeight="@dimen/row_document_height"
android:minHeight="@dimen/row_feature_item_height"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground">

<androidx.cardview.widget.CardView
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/element_margin_medium"
android:layout_marginRight="@dimen/element_margin_medium"
android:id="@+id/image_view_row_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
local:cardBackgroundColor="@color/background_two_color"
local:cardElevation="0dp"
local:cardCornerRadius="6dp">
Expand All @@ -37,7 +38,9 @@
android:orientation="vertical"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/image_view_row_icon"
android:layout_toLeftOf="@+id/image_button_options">
android:layout_toLeftOf="@+id/image_button_options"
android:layout_marginLeft="@dimen/element_margin_small"
android:layout_marginStart="12dp">
<TextView
android:text="My Content"
android:layout_width="fill_parent"
Expand All @@ -54,7 +57,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/element_margin_medium"
android:paddingRight="@dimen/element_margin_medium"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/icon_chevron_right" />
Expand Down
18 changes: 9 additions & 9 deletions BMM.UI.Android/Resources/layout/listitem_trackcollection.axml
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:minHeight="@dimen/row_document_height"
android:minHeight="@dimen/row_feature_item_height"
android:layout_height="wrap_content"
android:showDividers="end"
android:paddingLeft="@dimen/padding_medium"
android:paddingRight="@dimen/padding_medium"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:minHeight="@dimen/row_document_height"
android:minHeight="@dimen/row_feature_item_height"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground">

<androidx.cardview.widget.CardView
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:paddingLeft="@dimen/element_margin_medium"
android:paddingRight="@dimen/element_margin_medium"
android:layout_marginLeft="@dimen/element_margin_medium"
android:layout_marginRight="@dimen/element_margin_medium"
android:id="@+id/image_view_row_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
local:cardBackgroundColor="@color/background_two_color"
local:cardElevation="0dp"
local:cardCornerRadius="6dp">
Expand All @@ -39,7 +38,9 @@
android:orientation="vertical"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/image_view_row_icon"
android:layout_toLeftOf="@+id/SharedPlaylistIcon">
android:layout_toLeftOf="@+id/SharedPlaylistIcon"
android:layout_marginLeft="@dimen/element_margin_small"
android:layout_marginStart="12dp">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
Expand Down Expand Up @@ -82,11 +83,10 @@
<ImageView
android:src="@drawable/icon_chevron_right"
android:layout_width="wrap_content"
android:minHeight="@dimen/row_document_height"
android:minHeight="@dimen/row_feature_item_height"
android:layout_height="fill_parent"
android:id="@+id/image_button_options"
android:paddingLeft="@dimen/margin_small"
android:paddingRight="@dimen/element_margin_medium"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
</RelativeLayout>
Expand Down
Loading

0 comments on commit b677884

Please sign in to comment.