diff --git a/.idea/misc.xml b/.idea/misc.xml
index 22db2b6e..ef098457 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -88,6 +88,7 @@
+
diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistAdapter.java
index 29c5283f..a544a8e9 100644
--- a/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistAdapter.java
+++ b/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistAdapter.java
@@ -2,7 +2,6 @@ package com.cappielloantonio.play.adapter;
import android.content.Context;
import android.os.Bundle;
-import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -13,7 +12,6 @@ import androidx.annotation.NonNull;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.RecyclerView;
-import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Playlist;
@@ -23,6 +21,7 @@ import com.cappielloantonio.play.util.MusicUtil;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
public class PlaylistAdapter extends RecyclerView.Adapter {
private static final String TAG = "PlaylistAdapter";
@@ -30,14 +29,16 @@ public class PlaylistAdapter extends RecyclerView.Adapter playlists;
- public PlaylistAdapter(MainActivity activity, Context context) {
+ public PlaylistAdapter(MainActivity activity, Context context, boolean isDownloaded) {
this.activity = activity;
this.context = context;
this.mInflater = LayoutInflater.from(context);
this.playlists = new ArrayList<>();
+ this.isDownloaded = isDownloaded;
}
@NonNull
@@ -58,6 +59,8 @@ public class PlaylistAdapter extends RecyclerView.Adapter playlists;
private List playlistsFull;
- public PlaylistCatalogueAdapter(MainActivity activity, Context context) {
+ public PlaylistCatalogueAdapter(MainActivity activity, Context context, boolean isOffline) {
this.activity = activity;
this.context = context;
this.mInflater = LayoutInflater.from(context);
this.playlists = new ArrayList<>();
+ this.isOffline = isOffline;
}
@NonNull
@@ -133,6 +137,8 @@ public class PlaylistCatalogueAdapter extends RecyclerView.Adapter> getAll(String server);
- @Query("SELECT * FROM download WHERE server=:server GROUP BY artistName LIMIT :size")
+ @Query("SELECT * FROM download WHERE server=:server AND playlistId IS NULL GROUP BY artistName LIMIT :size")
LiveData> getSampleArtist(int size, String server);
- @Query("SELECT * FROM download WHERE server=:server GROUP BY albumName LIMIT :size")
+ @Query("SELECT * FROM download WHERE server=:server AND playlistId IS NULL GROUP BY albumName LIMIT :size")
LiveData> getSampleAlbum(int size, String server);
+ @Query("SELECT * FROM download WHERE server=:server AND playlistId IS NOT NULL GROUP BY playlistId LIMIT :size")
+ LiveData> getSamplePlaylist(int size, String server);
+
@Query("SELECT * FROM download WHERE server=:server LIMIT :size")
LiveData> getSample(int size, String server);
@@ -30,14 +33,20 @@ public interface DownloadDao {
@Query("SELECT * FROM download WHERE server=:server AND albumId=:albumId")
LiveData> getAllFromAlbum(String server, String albumId);
+ @Query("SELECT * FROM download WHERE server=:server AND playlistId=:playlistId")
+ LiveData> getAllFromPlaylist(String server, String playlistId);
+
+ @Query("SELECT * FROM download WHERE server=:server AND playlistId IS NOT NULL GROUP BY playlistId")
+ LiveData> getAllPlaylists(String server);
+
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Download download);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List downloads);
- @Query("DELETE FROM download WHERE id = :id")
- void delete(String id);
+ @Query("DELETE FROM download WHERE songId = :songId")
+ void delete(String songId);
@Query("DELETE FROM download WHERE server=:server")
void deleteAll(String server);
diff --git a/app/src/main/java/com/cappielloantonio/play/model/Download.java b/app/src/main/java/com/cappielloantonio/play/model/Download.java
index 5e2cfe43..18c0f41c 100644
--- a/app/src/main/java/com/cappielloantonio/play/model/Download.java
+++ b/app/src/main/java/com/cappielloantonio/play/model/Download.java
@@ -9,11 +9,16 @@ import com.cappielloantonio.play.App;
import com.cappielloantonio.play.util.MusicUtil;
import com.cappielloantonio.play.util.PreferenceUtil;
+import java.util.UUID;
+
@Entity(tableName = "download")
public class Download {
@NonNull
@PrimaryKey
@ColumnInfo(name = "id")
+ private String id;
+
+ @ColumnInfo(name = "songId")
private String songID;
@ColumnInfo(name = "title")
@@ -43,7 +48,14 @@ public class Download {
@ColumnInfo(name = "server")
private String server;
- public Download(@NonNull String songID, String title, String albumId, String albumName, String artistId, String artistName, int trackNumber, String primary, long duration, String server) {
+ @ColumnInfo(name = "playlistId")
+ private String playlistId;
+
+ @ColumnInfo(name = "playlistName")
+ private String playlistName;
+
+ public Download(@NonNull String id, String songID, String title, String albumId, String albumName, String artistId, String artistName, int trackNumber, String primary, long duration, String server, String playlistId, String playlistName) {
+ this.id = id;
this.songID = songID;
this.title = title;
this.albumId = albumId;
@@ -54,9 +66,12 @@ public class Download {
this.primary = primary;
this.duration = duration;
this.server = server;
+ this.playlistId = playlistId;
+ this.playlistName = playlistName;
}
- public Download(Song song) {
+ public Download(Song song, String playlistId, String playlistName) {
+ this.id = UUID.randomUUID().toString();
this.songID = song.getId();
this.title = song.getTitle();
this.albumId = song.getAlbumId();
@@ -67,14 +82,24 @@ public class Download {
this.primary = song.getPrimary();
this.duration = song.getDuration();
this.server = PreferenceUtil.getInstance(App.getInstance()).getServerId();
+ this.playlistId = playlistId;
+ this.playlistName = playlistName;
}
@NonNull
+ public String getId() {
+ return id;
+ }
+
+ public void setId(@NonNull String id) {
+ this.id = id;
+ }
+
public String getSongID() {
return songID;
}
- public void setSongID(@NonNull String songID) {
+ public void setSongID(String songID) {
this.songID = songID;
}
@@ -149,4 +174,20 @@ public class Download {
public void setServer(String server) {
this.server = server;
}
+
+ public String getPlaylistId() {
+ return playlistId;
+ }
+
+ public void setPlaylistId(String playlistId) {
+ this.playlistId = playlistId;
+ }
+
+ public String getPlaylistName() {
+ return playlistName;
+ }
+
+ public void setPlaylistName(String playlistName) {
+ this.playlistName = playlistName;
+ }
}
diff --git a/app/src/main/java/com/cappielloantonio/play/model/Playlist.java b/app/src/main/java/com/cappielloantonio/play/model/Playlist.java
index 221827cb..3723d9da 100644
--- a/app/src/main/java/com/cappielloantonio/play/model/Playlist.java
+++ b/app/src/main/java/com/cappielloantonio/play/model/Playlist.java
@@ -4,6 +4,9 @@ import android.os.Parcel;
import android.os.Parcelable;
public class Playlist implements Parcelable {
+ public static final String ALL = "ALL";
+ public static final String DOWNLOADED = "DOWNLOADED";
+
private String id;
private String name;
private String primary;
@@ -20,6 +23,11 @@ public class Playlist implements Parcelable {
this.duration = playlist.getDuration();
}
+ public Playlist(String id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
public String getId() {
return id;
}
diff --git a/app/src/main/java/com/cappielloantonio/play/repository/DownloadRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/DownloadRepository.java
index dd6fe0a6..86a8eb08 100644
--- a/app/src/main/java/com/cappielloantonio/play/repository/DownloadRepository.java
+++ b/app/src/main/java/com/cappielloantonio/play/repository/DownloadRepository.java
@@ -26,10 +26,11 @@ public class DownloadRepository {
return downloadDao.getAll(PreferenceUtil.getInstance(App.getInstance()).getServerId());
}
- public LiveData> getLiveDownloadSample(int size, boolean isArtist, boolean isAlbum, boolean isTrack) {
+ public LiveData> getLiveDownloadSample(int size, boolean isArtist, boolean isAlbum, boolean isTrack, boolean isPlaylist) {
if (isArtist) return downloadDao.getSampleArtist(size, PreferenceUtil.getInstance(App.getInstance()).getServerId());
else if (isAlbum) return downloadDao.getSampleAlbum(size, PreferenceUtil.getInstance(App.getInstance()).getServerId());
else if (isTrack) return downloadDao.getSample(size, PreferenceUtil.getInstance(App.getInstance()).getServerId());
+ else if (isPlaylist) return downloadDao.getSamplePlaylist(size, PreferenceUtil.getInstance(App.getInstance()).getServerId());
else return downloadDao.getSample(size, PreferenceUtil.getInstance(App.getInstance()).getServerId());
}
@@ -41,6 +42,14 @@ public class DownloadRepository {
return downloadDao.getAllFromAlbum(PreferenceUtil.getInstance(App.getInstance()).getServerId(), albumId);
}
+ public LiveData> getLiveDownloadFromPlaylist(String playlistId) {
+ return downloadDao.getAllFromPlaylist(PreferenceUtil.getInstance(App.getInstance()).getServerId(), playlistId);
+ }
+
+ public LiveData> getLivePlaylist() {
+ return downloadDao.getAllPlaylists(PreferenceUtil.getInstance(App.getInstance()).getServerId());
+ }
+
public void insert(Download download) {
InsertThreadSafe insert = new InsertThreadSafe(downloadDao, download);
Thread thread = new Thread(insert);
diff --git a/app/src/main/java/com/cappielloantonio/play/service/DownloadTracker.java b/app/src/main/java/com/cappielloantonio/play/service/DownloadTracker.java
index b39d5c68..145c84c3 100644
--- a/app/src/main/java/com/cappielloantonio/play/service/DownloadTracker.java
+++ b/app/src/main/java/com/cappielloantonio/play/service/DownloadTracker.java
@@ -87,17 +87,18 @@ public class DownloadTracker {
return new DownloadRequest.Builder(id, uri).build();
}
- public void download(List songs) {
+ public void download(List songs, String playlistId, String playlistName) {
DownloadRepository downloadRepository = new DownloadRepository(App.getInstance());
for (Song song : songs) {
if(isDownloaded(song)) {
+ downloadRepository.insert(MappingUtil.mapToDownload(song, playlistId, playlistName));
continue;
}
MediaItem mediaItem = MusicUtil.getMediaItemFromSong(song);
DownloadService.sendAddDownload(context, DownloaderService.class, getDownloadRequest(song.getId(), checkNotNull(mediaItem.playbackProperties).uri), false);
- downloadRepository.insert(MappingUtil.mapToDownload(song));
+ downloadRepository.insert(MappingUtil.mapToDownload(song, playlistId, playlistName));
}
}
@@ -111,7 +112,7 @@ public class DownloadTracker {
if (download != null && download.state != Download.STATE_FAILED) {
DownloadService.sendRemoveDownload(context, DownloaderService.class, download.request.id, false);
- downloadRepository.delete(MappingUtil.mapToDownload(song));
+ downloadRepository.delete(MappingUtil.mapToDownload(song, null, null));
}
}
}
diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumPageFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumPageFragment.java
index 16773cd0..7661eddc 100644
--- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumPageFragment.java
+++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumPageFragment.java
@@ -91,14 +91,11 @@ public class AlbumPageFragment extends Fragment {
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_download_album:
- albumPageViewModel.getAlbumSongLiveList(requireActivity()).observe(requireActivity(), songs -> {
- DownloadUtil.getDownloadTracker(requireContext()).download(songs);
- });
- return true;
- default:
- break;
+ if (item.getItemId() == R.id.action_download_album) {
+ albumPageViewModel.getAlbumSongLiveList(requireActivity()).observe(requireActivity(), songs -> {
+ DownloadUtil.getDownloadTracker(requireContext()).download(songs, null, null);
+ });
+ return true;
}
return false;
diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/DownloadFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/DownloadFragment.java
index 0d46e942..20db2a5d 100644
--- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/DownloadFragment.java
+++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/DownloadFragment.java
@@ -12,35 +12,27 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.PagerSnapHelper;
import androidx.recyclerview.widget.SnapHelper;
import androidx.viewpager2.widget.ViewPager2;
import com.cappielloantonio.play.R;
-import com.cappielloantonio.play.adapter.AlbumAdapter;
import com.cappielloantonio.play.adapter.AlbumHorizontalAdapter;
-import com.cappielloantonio.play.adapter.ArtistAdapter;
import com.cappielloantonio.play.adapter.ArtistHorizontalAdapter;
-import com.cappielloantonio.play.adapter.DiscoverSongAdapter;
-import com.cappielloantonio.play.adapter.SimilarTrackAdapter;
+import com.cappielloantonio.play.adapter.PlaylistAdapter;
import com.cappielloantonio.play.adapter.SongHorizontalAdapter;
-import com.cappielloantonio.play.adapter.TrackAdapter;
-import com.cappielloantonio.play.adapter.YearAdapter;
import com.cappielloantonio.play.databinding.FragmentDownloadBinding;
-import com.cappielloantonio.play.databinding.FragmentHomeBinding;
-import com.cappielloantonio.play.helper.recyclerview.CustomLinearSnapHelper;
import com.cappielloantonio.play.helper.recyclerview.DotsIndicatorDecoration;
import com.cappielloantonio.play.model.Album;
import com.cappielloantonio.play.model.Artist;
+import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.ui.activity.MainActivity;
-import com.cappielloantonio.play.util.MappingUtil;
import com.cappielloantonio.play.util.UIUtil;
import com.cappielloantonio.play.viewmodel.DownloadViewModel;
-import com.cappielloantonio.play.viewmodel.HomeViewModel;
import java.util.Objects;
@@ -54,6 +46,7 @@ public class DownloadFragment extends Fragment {
private ArtistHorizontalAdapter downloadedArtistAdapter;
private AlbumHorizontalAdapter downloadedAlbumAdapter;
private SongHorizontalAdapter downloadedTrackAdapter;
+ private PlaylistAdapter playlistAdapter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -89,6 +82,8 @@ public class DownloadFragment extends Fragment {
initDownloadedArtistView();
initDownloadedAlbumView();
initDownloadedSongView();
+ initDownloadedPlaylistSlideView();
+ initPlaceholder();
}
@Override
@@ -138,6 +133,12 @@ public class DownloadFragment extends Fragment {
bundle.putString(Song.DOWNLOADED, Song.DOWNLOADED);
activity.navController.navigate(R.id.action_downloadFragment_to_songListPageFragment, bundle);
});
+
+ bind.downloadedPlaylistTextViewClickable.setOnClickListener(v -> {
+ Bundle bundle = new Bundle();
+ bundle.putString(Playlist.DOWNLOADED, Playlist.DOWNLOADED);
+ activity.navController.navigate(R.id.action_downloadFragment_to_playlistCatalogueFragment, bundle);
+ });
}
private void initAppBar() {
@@ -155,12 +156,10 @@ public class DownloadFragment extends Fragment {
if (bind != null) bind.downloadDownloadedArtistPlaceholder.placeholder.setVisibility(View.VISIBLE);
if (bind != null) bind.downloadDownloadedArtistSector.setVisibility(View.GONE);
} else {
- if (bind != null && !artists.isEmpty()) bind.emptyDownloadLayout.setVisibility(View.GONE);
- if (bind != null && !artists.isEmpty()) bind.fragmentDownloadNestedScrollView.setVisibility(View.VISIBLE);
-
if (bind != null) bind.downloadDownloadedArtistPlaceholder.placeholder.setVisibility(View.GONE);
if (bind != null) bind.downloadDownloadedArtistSector.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
- if (bind != null) bind.downloadedArtistRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(artists.size(), 5), GridLayoutManager.HORIZONTAL, false));
+ if (bind != null)
+ bind.downloadedArtistRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(artists.size(), 5), GridLayoutManager.HORIZONTAL, false));
downloadedArtistAdapter.setItems(artists);
}
@@ -189,12 +188,10 @@ public class DownloadFragment extends Fragment {
if (bind != null) bind.downloadDownloadedAlbumPlaceholder.placeholder.setVisibility(View.VISIBLE);
if (bind != null) bind.downloadDownloadedAlbumSector.setVisibility(View.GONE);
} else {
- if (bind != null && !albums.isEmpty()) bind.emptyDownloadLayout.setVisibility(View.GONE);
- if (bind != null && !albums.isEmpty()) bind.fragmentDownloadNestedScrollView.setVisibility(View.VISIBLE);
-
if (bind != null) bind.downloadDownloadedAlbumPlaceholder.placeholder.setVisibility(View.GONE);
if (bind != null) bind.downloadDownloadedAlbumSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
- if (bind != null) bind.downloadedAlbumRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(albums.size(), 5), GridLayoutManager.HORIZONTAL, false));
+ if (bind != null)
+ bind.downloadedAlbumRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(albums.size(), 5), GridLayoutManager.HORIZONTAL, false));
downloadedAlbumAdapter.setItems(albums);
}
@@ -223,12 +220,10 @@ public class DownloadFragment extends Fragment {
if (bind != null) bind.downloadDownloadedTracksPlaceholder.placeholder.setVisibility(View.VISIBLE);
if (bind != null) bind.downloadDownloadedTracksSector.setVisibility(View.GONE);
} else {
- if (bind != null && !songs.isEmpty()) bind.emptyDownloadLayout.setVisibility(View.GONE);
- if (bind != null && !songs.isEmpty()) bind.fragmentDownloadNestedScrollView.setVisibility(View.VISIBLE);
-
if (bind != null) bind.downloadDownloadedTracksPlaceholder.placeholder.setVisibility(View.GONE);
if (bind != null) bind.downloadDownloadedTracksSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE);
- if (bind != null) bind.downloadedTracksRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(songs.size(), 5), GridLayoutManager.HORIZONTAL, false));
+ if (bind != null)
+ bind.downloadedTracksRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(songs.size(), 5), GridLayoutManager.HORIZONTAL, false));
downloadedTrackAdapter.setItems(songs);
}
@@ -246,4 +241,60 @@ public class DownloadFragment extends Fragment {
requireContext().getResources().getColor(R.color.titleTextColor, null))
);
}
+
+ private void initDownloadedPlaylistSlideView() {
+ bind.downloadedPlaylistViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
+
+ playlistAdapter = new PlaylistAdapter(activity, requireContext(), true);
+ bind.downloadedPlaylistViewPager.setAdapter(playlistAdapter);
+ bind.downloadedPlaylistViewPager.setOffscreenPageLimit(3);
+ downloadViewModel.getDownloadedPlaylists(requireActivity(), 5).observe(requireActivity(), playlists -> {
+ if (playlists == null) {
+ if (bind != null) bind.downloadDownloadedPlaylistPlaceholder.placeholder.setVisibility(View.VISIBLE);
+ if (bind != null) bind.downloadDownloadedPlaylistSector.setVisibility(View.GONE);
+ } else {
+ if (bind != null) bind.downloadDownloadedPlaylistPlaceholder.placeholder.setVisibility(View.GONE);
+ if (bind != null) bind.downloadDownloadedPlaylistSector.setVisibility(!playlists.isEmpty() ? View.VISIBLE : View.GONE);
+
+ playlistAdapter.setItems(playlists);
+ }
+ });
+
+ setSlideViewOffset(20, 16);
+ }
+
+ private void setSlideViewOffset(float pageOffset, float pageMargin) {
+ bind.downloadedPlaylistViewPager.setPageTransformer((page, position) -> {
+ float myOffset = position * -(2 * pageOffset + pageMargin);
+ if (bind.downloadedPlaylistViewPager.getOrientation() == ViewPager2.ORIENTATION_HORIZONTAL) {
+ if (ViewCompat.getLayoutDirection(bind.downloadedPlaylistViewPager) == ViewCompat.LAYOUT_DIRECTION_RTL) {
+ page.setTranslationX(-myOffset);
+ } else {
+ page.setTranslationX(myOffset);
+ }
+ } else {
+ page.setTranslationY(myOffset);
+ }
+ });
+ }
+
+ private void initPlaceholder() {
+ FragmentActivity requiredActivity = getActivity();
+
+ if (requiredActivity != null) {
+ downloadViewModel.getDownloadedTracks(requiredActivity, 20).observe(requiredActivity, songs ->
+ downloadViewModel.getDownloadedAlbums(requiredActivity, 20).observe(requiredActivity, albums ->
+ downloadViewModel.getDownloadedArtists(requiredActivity, 20).observe(requiredActivity, artists -> {
+ if ((songs != null && !songs.isEmpty()) || (albums != null && !albums.isEmpty()) || (artists != null && !artists.isEmpty())) {
+ if (bind != null) bind.emptyDownloadLayout.setVisibility(View.GONE);
+ if (bind != null) bind.fragmentDownloadNestedScrollView.setVisibility(View.VISIBLE);
+ } else {
+ if (bind != null) bind.emptyDownloadLayout.setVisibility(View.VISIBLE);
+ if (bind != null) bind.fragmentDownloadNestedScrollView.setVisibility(View.GONE);
+ }
+ })
+ )
+ );
+ }
+ }
}
diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java
index 9cbf209d..67c96281 100644
--- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java
+++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java
@@ -28,6 +28,7 @@ import com.cappielloantonio.play.adapter.PlaylistAdapter;
import com.cappielloantonio.play.databinding.FragmentLibraryBinding;
import com.cappielloantonio.play.helper.recyclerview.CustomLinearSnapHelper;
import com.cappielloantonio.play.helper.recyclerview.DotsIndicatorDecoration;
+import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.util.UIUtil;
@@ -118,7 +119,11 @@ public class LibraryFragment extends Fragment {
bind.albumCatalogueTextViewClickable.setOnClickListener(v -> activity.navController.navigate(R.id.action_libraryFragment_to_albumCatalogueFragment));
bind.artistCatalogueTextViewClickable.setOnClickListener(v -> activity.navController.navigate(R.id.action_libraryFragment_to_artistCatalogueFragment));
bind.genreCatalogueTextViewClickable.setOnClickListener(v -> activity.navController.navigate(R.id.action_libraryFragment_to_genreCatalogueFragment));
- bind.playlistCatalogueTextViewClickable.setOnClickListener(v -> activity.navController.navigate(R.id.action_libraryFragment_to_playlistCatalogueFragment));
+ bind.playlistCatalogueTextViewClickable.setOnClickListener(v -> {
+ Bundle bundle = new Bundle();
+ bundle.putString(Playlist.ALL, Playlist.ALL);
+ activity.navController.navigate(R.id.action_libraryFragment_to_playlistCatalogueFragment, bundle);
+ });
bind.albumCatalogueSampleTextViewRefreshable.setOnLongClickListener(view -> {
libraryViewModel.refreshAlbumSample(requireActivity());
@@ -249,7 +254,7 @@ public class LibraryFragment extends Fragment {
private void initPlaylistSlideView() {
bind.playlistViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
- playlistAdapter = new PlaylistAdapter(activity, requireContext());
+ playlistAdapter = new PlaylistAdapter(activity, requireContext(), false);
bind.playlistViewPager.setAdapter(playlistAdapter);
bind.playlistViewPager.setOffscreenPageLimit(3);
libraryViewModel.getPlaylistSample().observe(requireActivity(), playlists -> {
diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java
index 8ca537f2..004b3277 100644
--- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java
+++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java
@@ -23,6 +23,8 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.adapter.PlaylistCatalogueAdapter;
import com.cappielloantonio.play.databinding.FragmentPlaylistCatalogueBinding;
+import com.cappielloantonio.play.model.Album;
+import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.viewmodel.PlaylistCatalogueViewModel;
@@ -39,8 +41,6 @@ public class PlaylistCatalogueFragment extends Fragment {
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
-
- initData();
}
@Override
@@ -49,7 +49,9 @@ public class PlaylistCatalogueFragment extends Fragment {
bind = FragmentPlaylistCatalogueBinding.inflate(inflater, container, false);
View view = bind.getRoot();
+ playlistCatalogueViewModel = new ViewModelProvider(requireActivity()).get(PlaylistCatalogueViewModel.class);
+ init();
initAppBar();
initPlaylistCatalogueView();
@@ -68,8 +70,12 @@ public class PlaylistCatalogueFragment extends Fragment {
bind = null;
}
- private void initData() {
- playlistCatalogueViewModel = new ViewModelProvider(requireActivity()).get(PlaylistCatalogueViewModel.class);
+ private void init() {
+ if (getArguments().getString(Playlist.ALL) != null) {
+ playlistCatalogueViewModel.setType(Playlist.ALL);
+ } else if (getArguments().getString(Playlist.DOWNLOADED) != null) {
+ playlistCatalogueViewModel.setType(Playlist.DOWNLOADED);
+ }
}
private void initAppBar() {
@@ -100,9 +106,9 @@ public class PlaylistCatalogueFragment extends Fragment {
bind.playlistCatalogueRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
bind.playlistCatalogueRecyclerView.setHasFixedSize(true);
- playlistCatalogueAdapter = new PlaylistCatalogueAdapter(activity, requireContext());
+ playlistCatalogueAdapter = new PlaylistCatalogueAdapter(activity, requireContext(), playlistCatalogueViewModel.getType().equals(Playlist.DOWNLOADED));
bind.playlistCatalogueRecyclerView.setAdapter(playlistCatalogueAdapter);
- playlistCatalogueViewModel.getPlaylistList().observe(requireActivity(), playlist -> {
+ playlistCatalogueViewModel.getPlaylistList(requireActivity()).observe(requireActivity(), playlist -> {
playlistCatalogueAdapter.setItems(playlist);
});
diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistPageFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistPageFragment.java
index fb82f347..7d296307 100644
--- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistPageFragment.java
+++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistPageFragment.java
@@ -1,5 +1,6 @@
package com.cappielloantonio.play.ui.fragment;
+import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -81,12 +82,13 @@ public class PlaylistPageFragment extends Fragment {
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_download_playlist:
- DownloadUtil.getDownloadTracker(requireContext()).download(Objects.requireNonNull(playlistPageViewModel.getPlaylistSongLiveList().getValue()));
- return true;
- default:
- break;
+ if (item.getItemId() == R.id.action_download_playlist) {
+ playlistPageViewModel.getPlaylistSongLiveList(requireActivity()).observe(requireActivity(), songs -> {
+ if (getContext() != null) {
+ DownloadUtil.getDownloadTracker(requireContext()).download(songs, playlistPageViewModel.getPlaylist().getId(), playlistPageViewModel.getPlaylist().getName());
+ }
+ });
+ return true;
}
return false;
@@ -94,6 +96,7 @@ public class PlaylistPageFragment extends Fragment {
private void init() {
playlistPageViewModel.setPlaylist(getArguments().getParcelable("playlist_object"));
+ playlistPageViewModel.setOffline(getArguments().getBoolean("is_offline"));
}
private void initAppBar() {
@@ -110,13 +113,18 @@ public class PlaylistPageFragment extends Fragment {
bind.playlistSongCountLabel.setText("Song count: " + playlistPageViewModel.getPlaylist().getSongCount());
bind.playlistDurationLabel.setText("Playlist duration: " + MusicUtil.getReadableDurationString(playlistPageViewModel.getPlaylist().getDuration(), false));
+ if (playlistPageViewModel.isOffline()) {
+ bind.playlistSongCountLabel.setVisibility(View.GONE);
+ bind.playlistDurationLabel.setVisibility(View.GONE);
+ }
+
bind.animToolbar.setNavigationOnClickListener(v -> activity.navController.navigateUp());
Objects.requireNonNull(bind.animToolbar.getOverflowIcon()).setTint(requireContext().getResources().getColor(R.color.titleTextColor, null));
}
private void initMusicButton() {
- playlistPageViewModel.getPlaylistSongLiveList().observe(requireActivity(), songs -> {
+ playlistPageViewModel.getPlaylistSongLiveList(requireActivity()).observe(requireActivity(), songs -> {
if (bind != null) {
bind.playlistPagePlayButton.setOnClickListener(v -> {
QueueRepository queueRepository = new QueueRepository(App.getInstance());
@@ -158,6 +166,6 @@ public class PlaylistPageFragment extends Fragment {
songHorizontalAdapter = new SongHorizontalAdapter(activity, requireContext(), true);
bind.songRecyclerView.setAdapter(songHorizontalAdapter);
- playlistPageViewModel.getPlaylistSongLiveList().observe(requireActivity(), songs -> songHorizontalAdapter.setItems(songs));
+ playlistPageViewModel.getPlaylistSongLiveList(requireActivity()).observe(requireActivity(), songs -> songHorizontalAdapter.setItems(songs));
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java
index 95f0b5a8..d3dc0aee 100644
--- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java
+++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java
@@ -140,9 +140,8 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
TextView removeAll = view.findViewById(R.id.remove_all_text_view);
albumBottomSheetViewModel.getAlbumTracks().observe(requireActivity(), songs -> {
-
downloadAll.setOnClickListener(v -> {
- DownloadUtil.getDownloadTracker(requireContext()).download(songs);
+ DownloadUtil.getDownloadTracker(requireContext()).download(songs, null, null);
dismissBottomSheet();
});
diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java
index 36c0cefa..9d62dc65 100644
--- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java
+++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java
@@ -148,7 +148,7 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements
TextView download = view.findViewById(R.id.download_text_view);
download.setOnClickListener(v -> {
- DownloadUtil.getDownloadTracker(requireContext()).download(Arrays.asList(song));
+ DownloadUtil.getDownloadTracker(requireContext()).download(Arrays.asList(song), null, null);
dismissBottomSheet();
});
diff --git a/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java b/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java
index 0a104f9d..cd270d54 100644
--- a/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java
+++ b/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java
@@ -19,6 +19,7 @@ import com.cappielloantonio.play.subsonic.models.SimilarArtistID3;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
public class MappingUtil {
public static ArrayList mapSong(List children) {
@@ -144,18 +145,28 @@ public class MappingUtil {
return artists;
}
+ public static ArrayList mapDownloadToPlaylist(List downloads) {
+ ArrayList playlists = new ArrayList();
+
+ for (Download download : downloads) {
+ playlists.add(new Playlist(download.getPlaylistId(), download.getPlaylistName()));
+ }
+
+ return playlists;
+ }
+
public static ArrayList mapToDownload(List songs) {
ArrayList downloads = new ArrayList();
for (Song song : songs) {
- downloads.add(new Download(song));
+ downloads.add(new Download(song, null, null));
}
return downloads;
}
- public static Download mapToDownload(Song song) {
- return new Download(song);
+ public static Download mapToDownload(Song song, String playlistId, String playlistName) {
+ return new Download(song, playlistId, playlistName);
}
public static ArrayList mapGenre(List genreList) {
diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/DownloadViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/DownloadViewModel.java
index de4ea641..db4d3f10 100644
--- a/app/src/main/java/com/cappielloantonio/play/viewmodel/DownloadViewModel.java
+++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/DownloadViewModel.java
@@ -10,6 +10,7 @@ import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.model.Album;
import com.cappielloantonio.play.model.Artist;
+import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.repository.DownloadRepository;
import com.cappielloantonio.play.util.MappingUtil;
@@ -24,6 +25,7 @@ public class DownloadViewModel extends AndroidViewModel {
private final MutableLiveData> downloadedArtistSample = new MutableLiveData<>(null);
private final MutableLiveData> downloadedAlbumSample = new MutableLiveData<>(null);
private final MutableLiveData> downloadedTrackSample = new MutableLiveData<>(null);
+ private final MutableLiveData> downloadedPlaylistSample = new MutableLiveData<>(null);
public DownloadViewModel(@NonNull Application application) {
super(application);
@@ -32,17 +34,22 @@ public class DownloadViewModel extends AndroidViewModel {
}
public LiveData> getDownloadedArtists(LifecycleOwner owner, int size) {
- downloadRepository.getLiveDownloadSample(size, true, false, false).observe(owner, downloads -> downloadedArtistSample.postValue(MappingUtil.mapDownloadToArtist(downloads)));
+ downloadRepository.getLiveDownloadSample(size, true, false, false, false).observe(owner, downloads -> downloadedArtistSample.postValue(MappingUtil.mapDownloadToArtist(downloads)));
return downloadedArtistSample;
}
public LiveData> getDownloadedAlbums(LifecycleOwner owner, int size) {
- downloadRepository.getLiveDownloadSample(size, false, true, false).observe(owner, downloads -> downloadedAlbumSample.postValue(MappingUtil.mapDownloadToAlbum(downloads)));
+ downloadRepository.getLiveDownloadSample(size, false, true, false, false).observe(owner, downloads -> downloadedAlbumSample.postValue(MappingUtil.mapDownloadToAlbum(downloads)));
return downloadedAlbumSample;
}
public LiveData> getDownloadedTracks(LifecycleOwner owner, int size) {
- downloadRepository.getLiveDownloadSample(size, false, false, true).observe(owner, downloads -> downloadedTrackSample.postValue(MappingUtil.mapDownloadToSong(downloads)));
+ downloadRepository.getLiveDownloadSample(size, false, false, true, false).observe(owner, downloads -> downloadedTrackSample.postValue(MappingUtil.mapDownloadToSong(downloads)));
return downloadedTrackSample;
}
+
+ public LiveData> getDownloadedPlaylists(LifecycleOwner owner, int size) {
+ downloadRepository.getLiveDownloadSample(size, false, false, false, true).observe(owner, downloads -> downloadedPlaylistSample.postValue(MappingUtil.mapDownloadToPlaylist(downloads)));
+ return downloadedPlaylistSample;
+ }
}
diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/PlaylistCatalogueViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/PlaylistCatalogueViewModel.java
index eac3554e..835bda2b 100644
--- a/app/src/main/java/com/cappielloantonio/play/viewmodel/PlaylistCatalogueViewModel.java
+++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/PlaylistCatalogueViewModel.java
@@ -3,24 +3,57 @@ package com.cappielloantonio.play.viewmodel;
import android.app.Application;
import androidx.annotation.NonNull;
+import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import com.cappielloantonio.play.model.Album;
import com.cappielloantonio.play.model.Playlist;
+import com.cappielloantonio.play.repository.DownloadRepository;
import com.cappielloantonio.play.repository.PlaylistRepository;
+import com.cappielloantonio.play.util.MappingUtil;
+import java.util.ArrayList;
import java.util.List;
public class PlaylistCatalogueViewModel extends AndroidViewModel {
private final PlaylistRepository playlistRepository;
+ private final DownloadRepository downloadRepository;
+
+ private String type;
+
+ private MutableLiveData> playlistList;
public PlaylistCatalogueViewModel(@NonNull Application application) {
super(application);
playlistRepository = new PlaylistRepository(application);
+ downloadRepository = new DownloadRepository(application);
}
- public LiveData> getPlaylistList() {
- return playlistRepository.getPlaylists(false, -1);
+ public LiveData> getPlaylistList(FragmentActivity activity) {
+ playlistList = new MutableLiveData<>(new ArrayList<>());
+
+ switch (type) {
+ case Playlist.ALL:
+ playlistRepository.getPlaylists(false, -1).observe(activity, playlists -> playlistList.postValue(playlists));
+ break;
+ case Playlist.DOWNLOADED:
+ downloadRepository.getLivePlaylist().observe(activity, downloads -> playlistList.setValue(MappingUtil.mapDownloadToPlaylist(downloads)));
+ break;
+ }
+
+ playlistRepository.getPlaylists(false, -1);
+
+ return playlistList;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
}
}
diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/PlaylistPageViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/PlaylistPageViewModel.java
index 0193cdef..5b8f58e4 100644
--- a/app/src/main/java/com/cappielloantonio/play/viewmodel/PlaylistPageViewModel.java
+++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/PlaylistPageViewModel.java
@@ -3,28 +3,45 @@ package com.cappielloantonio.play.viewmodel;
import android.app.Application;
import androidx.annotation.NonNull;
+import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
+import com.cappielloantonio.play.model.Album;
import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.Song;
+import com.cappielloantonio.play.repository.DownloadRepository;
import com.cappielloantonio.play.repository.PlaylistRepository;
+import com.cappielloantonio.play.util.MappingUtil;
import java.util.List;
public class PlaylistPageViewModel extends AndroidViewModel {
private final PlaylistRepository playlistRepository;
+ private final DownloadRepository downloadRepository;
+
+ private MutableLiveData> playlistSongLiveList = new MutableLiveData<>();
private Playlist playlist;
+ private boolean isOffline;
public PlaylistPageViewModel(@NonNull Application application) {
super(application);
playlistRepository = new PlaylistRepository(application);
+ downloadRepository = new DownloadRepository(application);
}
- public MutableLiveData> getPlaylistSongLiveList() {
- return playlistRepository.getPlaylistSongs(playlist.getId());
+ public LiveData> getPlaylistSongLiveList(FragmentActivity activity) {
+ if (isOffline) {
+ downloadRepository.getLiveDownloadFromPlaylist(playlist.getId()).observe(activity, downloads -> playlistSongLiveList.postValue(MappingUtil.mapDownloadToSong(downloads)));
+ }
+ else {
+ playlistSongLiveList = playlistRepository.getPlaylistSongs(playlist.getId());
+ }
+
+ return playlistSongLiveList;
}
public Playlist getPlaylist() {
@@ -34,4 +51,12 @@ public class PlaylistPageViewModel extends AndroidViewModel {
public void setPlaylist(Playlist playlist) {
this.playlist = playlist;
}
+
+ public void setOffline(boolean offline) {
+ isOffline = offline;
+ }
+
+ public boolean isOffline() {
+ return isOffline;
+ }
}
diff --git a/app/src/main/res/layout/fragment_download.xml b/app/src/main/res/layout/fragment_download.xml
index c2f6ce31..1db03ee0 100644
--- a/app/src/main/res/layout/fragment_download.xml
+++ b/app/src/main/res/layout/fragment_download.xml
@@ -256,6 +256,61 @@
android:id="@+id/download_downloaded_tracks_placeholder"
layout="@layout/item_placeholder_horizontal"
android:visibility="gone" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml
index bf532104..1976f35f 100644
--- a/app/src/main/res/navigation/nav_graph.xml
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -119,6 +119,12 @@
+
+