Download entire playlists in separate section

This commit is contained in:
CappielloAntonio 2021-09-03 17:51:55 +02:00
parent f89f3454c4
commit d2a80c064c
23 changed files with 367 additions and 79 deletions

1
.idea/misc.xml generated
View file

@ -88,6 +88,7 @@
<entry key="app/src/main/res/menu/main_page_menu.xml" value="0.3229166666666667" /> <entry key="app/src/main/res/menu/main_page_menu.xml" value="0.3229166666666667" />
<entry key="app/src/main/res/menu/playlist_page_menu.xml" value="0.3229166666666667" /> <entry key="app/src/main/res/menu/playlist_page_menu.xml" value="0.3229166666666667" />
<entry key="app/src/main/res/menu/toolbar_menu.xml" value="0.3229166666666667" /> <entry key="app/src/main/res/menu/toolbar_menu.xml" value="0.3229166666666667" />
<entry key="app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.28055555555555556" />
</map> </map>
</option> </option>
</component> </component>

View file

@ -2,7 +2,6 @@ package com.cappielloantonio.play.adapter;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -13,7 +12,6 @@ import androidx.annotation.NonNull;
import androidx.navigation.Navigation; import androidx.navigation.Navigation;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.cappielloantonio.play.R; import com.cappielloantonio.play.R;
import com.cappielloantonio.play.glide.CustomGlideRequest; import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Playlist; import com.cappielloantonio.play.model.Playlist;
@ -23,6 +21,7 @@ import com.cappielloantonio.play.util.MusicUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHolder> { public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHolder> {
private static final String TAG = "PlaylistAdapter"; private static final String TAG = "PlaylistAdapter";
@ -30,14 +29,16 @@ public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHo
private final MainActivity activity; private final MainActivity activity;
private final Context context; private final Context context;
private final LayoutInflater mInflater; private final LayoutInflater mInflater;
private final boolean isDownloaded;
private List<Playlist> playlists; private List<Playlist> playlists;
public PlaylistAdapter(MainActivity activity, Context context) { public PlaylistAdapter(MainActivity activity, Context context, boolean isDownloaded) {
this.activity = activity; this.activity = activity;
this.context = context; this.context = context;
this.mInflater = LayoutInflater.from(context); this.mInflater = LayoutInflater.from(context);
this.playlists = new ArrayList<>(); this.playlists = new ArrayList<>();
this.isDownloaded = isDownloaded;
} }
@NonNull @NonNull
@ -58,6 +59,8 @@ public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHo
.from(context, playlist.getPrimary(), CustomGlideRequest.PLAYLIST_PIC, null) .from(context, playlist.getPrimary(), CustomGlideRequest.PLAYLIST_PIC, null)
.build() .build()
.into(holder.cover); .into(holder.cover);
if (isDownloaded) holder.textPlaylistSongCount.setVisibility(View.GONE);
} }
@Override @Override
@ -87,14 +90,21 @@ public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHo
cover = itemView.findViewById(R.id.playlist_cover_image_view); cover = itemView.findViewById(R.id.playlist_cover_image_view);
itemView.setOnClickListener(this); itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this); if (!isDownloaded) itemView.setOnLongClickListener(this);
} }
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable("playlist_object", playlists.get(getBindingAdapterPosition())); bundle.putParcelable("playlist_object", playlists.get(getBindingAdapterPosition()));
Navigation.findNavController(view).navigate(R.id.action_libraryFragment_to_playlistPageFragment, bundle);
if (Objects.requireNonNull(Navigation.findNavController(view).getCurrentDestination()).getId() == R.id.libraryFragment) {
bundle.putBoolean("is_offline", false);
Navigation.findNavController(view).navigate(R.id.action_libraryFragment_to_playlistPageFragment, bundle);
} else if (Objects.requireNonNull(Navigation.findNavController(view).getCurrentDestination()).getId() == R.id.downloadFragment) {
bundle.putBoolean("is_offline", true);
Navigation.findNavController(view).navigate(R.id.action_downloadFragment_to_playlistPageFragment, bundle);
}
} }
@Override @Override

View file

@ -35,6 +35,9 @@ public class PlaylistCatalogueAdapter extends RecyclerView.Adapter<PlaylistCatal
private final LayoutInflater mInflater; private final LayoutInflater mInflater;
private final MainActivity activity; private final MainActivity activity;
private final Context context; private final Context context;
private final boolean isOffline;
private final Filter filtering = new Filter() { private final Filter filtering = new Filter() {
@Override @Override
protected FilterResults performFiltering(CharSequence constraint) { protected FilterResults performFiltering(CharSequence constraint) {
@ -69,11 +72,12 @@ public class PlaylistCatalogueAdapter extends RecyclerView.Adapter<PlaylistCatal
private List<Playlist> playlists; private List<Playlist> playlists;
private List<Playlist> playlistsFull; private List<Playlist> playlistsFull;
public PlaylistCatalogueAdapter(MainActivity activity, Context context) { public PlaylistCatalogueAdapter(MainActivity activity, Context context, boolean isOffline) {
this.activity = activity; this.activity = activity;
this.context = context; this.context = context;
this.mInflater = LayoutInflater.from(context); this.mInflater = LayoutInflater.from(context);
this.playlists = new ArrayList<>(); this.playlists = new ArrayList<>();
this.isOffline = isOffline;
} }
@NonNull @NonNull
@ -133,6 +137,8 @@ public class PlaylistCatalogueAdapter extends RecyclerView.Adapter<PlaylistCatal
public void onClick(View view) { public void onClick(View view) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable("playlist_object", playlists.get(getBindingAdapterPosition())); bundle.putParcelable("playlist_object", playlists.get(getBindingAdapterPosition()));
bundle.putBoolean("is_offline", isOffline);
Navigation.findNavController(view).navigate(R.id.action_playlistCatalogueFragment_to_playlistPageFragment, bundle); Navigation.findNavController(view).navigate(R.id.action_playlistCatalogueFragment_to_playlistPageFragment, bundle);
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);

View file

@ -15,7 +15,7 @@ import com.cappielloantonio.play.model.Queue;
import com.cappielloantonio.play.model.RecentSearch; import com.cappielloantonio.play.model.RecentSearch;
import com.cappielloantonio.play.model.Server; import com.cappielloantonio.play.model.Server;
@Database(entities = {Queue.class, Server.class, RecentSearch.class, Download.class}, version = 17, exportSchema = false) @Database(entities = {Queue.class, Server.class, RecentSearch.class, Download.class}, version = 23, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase { public abstract class AppDatabase extends RoomDatabase {
private static final String TAG = "AppDatabase"; private static final String TAG = "AppDatabase";

View file

@ -15,12 +15,15 @@ public interface DownloadDao {
@Query("SELECT * FROM download WHERE server=:server") @Query("SELECT * FROM download WHERE server=:server")
LiveData<List<Download>> getAll(String server); LiveData<List<Download>> 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<List<Download>> getSampleArtist(int size, String server); LiveData<List<Download>> 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<List<Download>> getSampleAlbum(int size, String server); LiveData<List<Download>> getSampleAlbum(int size, String server);
@Query("SELECT * FROM download WHERE server=:server AND playlistId IS NOT NULL GROUP BY playlistId LIMIT :size")
LiveData<List<Download>> getSamplePlaylist(int size, String server);
@Query("SELECT * FROM download WHERE server=:server LIMIT :size") @Query("SELECT * FROM download WHERE server=:server LIMIT :size")
LiveData<List<Download>> getSample(int size, String server); LiveData<List<Download>> getSample(int size, String server);
@ -30,14 +33,20 @@ public interface DownloadDao {
@Query("SELECT * FROM download WHERE server=:server AND albumId=:albumId") @Query("SELECT * FROM download WHERE server=:server AND albumId=:albumId")
LiveData<List<Download>> getAllFromAlbum(String server, String albumId); LiveData<List<Download>> getAllFromAlbum(String server, String albumId);
@Query("SELECT * FROM download WHERE server=:server AND playlistId=:playlistId")
LiveData<List<Download>> getAllFromPlaylist(String server, String playlistId);
@Query("SELECT * FROM download WHERE server=:server AND playlistId IS NOT NULL GROUP BY playlistId")
LiveData<List<Download>> getAllPlaylists(String server);
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Download download); void insert(Download download);
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<Download> downloads); void insertAll(List<Download> downloads);
@Query("DELETE FROM download WHERE id = :id") @Query("DELETE FROM download WHERE songId = :songId")
void delete(String id); void delete(String songId);
@Query("DELETE FROM download WHERE server=:server") @Query("DELETE FROM download WHERE server=:server")
void deleteAll(String server); void deleteAll(String server);

View file

@ -9,11 +9,16 @@ import com.cappielloantonio.play.App;
import com.cappielloantonio.play.util.MusicUtil; import com.cappielloantonio.play.util.MusicUtil;
import com.cappielloantonio.play.util.PreferenceUtil; import com.cappielloantonio.play.util.PreferenceUtil;
import java.util.UUID;
@Entity(tableName = "download") @Entity(tableName = "download")
public class Download { public class Download {
@NonNull @NonNull
@PrimaryKey @PrimaryKey
@ColumnInfo(name = "id") @ColumnInfo(name = "id")
private String id;
@ColumnInfo(name = "songId")
private String songID; private String songID;
@ColumnInfo(name = "title") @ColumnInfo(name = "title")
@ -43,7 +48,14 @@ public class Download {
@ColumnInfo(name = "server") @ColumnInfo(name = "server")
private String 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.songID = songID;
this.title = title; this.title = title;
this.albumId = albumId; this.albumId = albumId;
@ -54,9 +66,12 @@ public class Download {
this.primary = primary; this.primary = primary;
this.duration = duration; this.duration = duration;
this.server = server; 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.songID = song.getId();
this.title = song.getTitle(); this.title = song.getTitle();
this.albumId = song.getAlbumId(); this.albumId = song.getAlbumId();
@ -67,14 +82,24 @@ public class Download {
this.primary = song.getPrimary(); this.primary = song.getPrimary();
this.duration = song.getDuration(); this.duration = song.getDuration();
this.server = PreferenceUtil.getInstance(App.getInstance()).getServerId(); this.server = PreferenceUtil.getInstance(App.getInstance()).getServerId();
this.playlistId = playlistId;
this.playlistName = playlistName;
} }
@NonNull @NonNull
public String getId() {
return id;
}
public void setId(@NonNull String id) {
this.id = id;
}
public String getSongID() { public String getSongID() {
return songID; return songID;
} }
public void setSongID(@NonNull String songID) { public void setSongID(String songID) {
this.songID = songID; this.songID = songID;
} }
@ -149,4 +174,20 @@ public class Download {
public void setServer(String server) { public void setServer(String server) {
this.server = 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;
}
} }

View file

@ -4,6 +4,9 @@ import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
public class Playlist implements Parcelable { public class Playlist implements Parcelable {
public static final String ALL = "ALL";
public static final String DOWNLOADED = "DOWNLOADED";
private String id; private String id;
private String name; private String name;
private String primary; private String primary;
@ -20,6 +23,11 @@ public class Playlist implements Parcelable {
this.duration = playlist.getDuration(); this.duration = playlist.getDuration();
} }
public Playlist(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() { public String getId() {
return id; return id;
} }

View file

@ -26,10 +26,11 @@ public class DownloadRepository {
return downloadDao.getAll(PreferenceUtil.getInstance(App.getInstance()).getServerId()); return downloadDao.getAll(PreferenceUtil.getInstance(App.getInstance()).getServerId());
} }
public LiveData<List<Download>> getLiveDownloadSample(int size, boolean isArtist, boolean isAlbum, boolean isTrack) { public LiveData<List<Download>> getLiveDownloadSample(int size, boolean isArtist, boolean isAlbum, boolean isTrack, boolean isPlaylist) {
if (isArtist) return downloadDao.getSampleArtist(size, PreferenceUtil.getInstance(App.getInstance()).getServerId()); 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 (isAlbum) return downloadDao.getSampleAlbum(size, PreferenceUtil.getInstance(App.getInstance()).getServerId());
else if (isTrack) return downloadDao.getSample(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()); 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); return downloadDao.getAllFromAlbum(PreferenceUtil.getInstance(App.getInstance()).getServerId(), albumId);
} }
public LiveData<List<Download>> getLiveDownloadFromPlaylist(String playlistId) {
return downloadDao.getAllFromPlaylist(PreferenceUtil.getInstance(App.getInstance()).getServerId(), playlistId);
}
public LiveData<List<Download>> getLivePlaylist() {
return downloadDao.getAllPlaylists(PreferenceUtil.getInstance(App.getInstance()).getServerId());
}
public void insert(Download download) { public void insert(Download download) {
InsertThreadSafe insert = new InsertThreadSafe(downloadDao, download); InsertThreadSafe insert = new InsertThreadSafe(downloadDao, download);
Thread thread = new Thread(insert); Thread thread = new Thread(insert);

View file

@ -87,17 +87,18 @@ public class DownloadTracker {
return new DownloadRequest.Builder(id, uri).build(); return new DownloadRequest.Builder(id, uri).build();
} }
public void download(List<Song> songs) { public void download(List<Song> songs, String playlistId, String playlistName) {
DownloadRepository downloadRepository = new DownloadRepository(App.getInstance()); DownloadRepository downloadRepository = new DownloadRepository(App.getInstance());
for (Song song : songs) { for (Song song : songs) {
if(isDownloaded(song)) { if(isDownloaded(song)) {
downloadRepository.insert(MappingUtil.mapToDownload(song, playlistId, playlistName));
continue; continue;
} }
MediaItem mediaItem = MusicUtil.getMediaItemFromSong(song); MediaItem mediaItem = MusicUtil.getMediaItemFromSong(song);
DownloadService.sendAddDownload(context, DownloaderService.class, getDownloadRequest(song.getId(), checkNotNull(mediaItem.playbackProperties).uri), false); 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) { if (download != null && download.state != Download.STATE_FAILED) {
DownloadService.sendRemoveDownload(context, DownloaderService.class, download.request.id, false); DownloadService.sendRemoveDownload(context, DownloaderService.class, download.request.id, false);
downloadRepository.delete(MappingUtil.mapToDownload(song)); downloadRepository.delete(MappingUtil.mapToDownload(song, null, null));
} }
} }
} }

View file

@ -91,14 +91,11 @@ public class AlbumPageFragment extends Fragment {
@Override @Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) { public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) { if (item.getItemId() == R.id.action_download_album) {
case R.id.action_download_album: albumPageViewModel.getAlbumSongLiveList(requireActivity()).observe(requireActivity(), songs -> {
albumPageViewModel.getAlbumSongLiveList(requireActivity()).observe(requireActivity(), songs -> { DownloadUtil.getDownloadTracker(requireContext()).download(songs, null, null);
DownloadUtil.getDownloadTracker(requireContext()).download(songs); });
}); return true;
return true;
default:
break;
} }
return false; return false;

View file

@ -12,35 +12,27 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.PagerSnapHelper; import androidx.recyclerview.widget.PagerSnapHelper;
import androidx.recyclerview.widget.SnapHelper; import androidx.recyclerview.widget.SnapHelper;
import androidx.viewpager2.widget.ViewPager2; import androidx.viewpager2.widget.ViewPager2;
import com.cappielloantonio.play.R; import com.cappielloantonio.play.R;
import com.cappielloantonio.play.adapter.AlbumAdapter;
import com.cappielloantonio.play.adapter.AlbumHorizontalAdapter; import com.cappielloantonio.play.adapter.AlbumHorizontalAdapter;
import com.cappielloantonio.play.adapter.ArtistAdapter;
import com.cappielloantonio.play.adapter.ArtistHorizontalAdapter; import com.cappielloantonio.play.adapter.ArtistHorizontalAdapter;
import com.cappielloantonio.play.adapter.DiscoverSongAdapter; import com.cappielloantonio.play.adapter.PlaylistAdapter;
import com.cappielloantonio.play.adapter.SimilarTrackAdapter;
import com.cappielloantonio.play.adapter.SongHorizontalAdapter; 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.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.helper.recyclerview.DotsIndicatorDecoration;
import com.cappielloantonio.play.model.Album; import com.cappielloantonio.play.model.Album;
import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.model.Artist;
import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.ui.activity.MainActivity; import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.util.MappingUtil;
import com.cappielloantonio.play.util.UIUtil; import com.cappielloantonio.play.util.UIUtil;
import com.cappielloantonio.play.viewmodel.DownloadViewModel; import com.cappielloantonio.play.viewmodel.DownloadViewModel;
import com.cappielloantonio.play.viewmodel.HomeViewModel;
import java.util.Objects; import java.util.Objects;
@ -54,6 +46,7 @@ public class DownloadFragment extends Fragment {
private ArtistHorizontalAdapter downloadedArtistAdapter; private ArtistHorizontalAdapter downloadedArtistAdapter;
private AlbumHorizontalAdapter downloadedAlbumAdapter; private AlbumHorizontalAdapter downloadedAlbumAdapter;
private SongHorizontalAdapter downloadedTrackAdapter; private SongHorizontalAdapter downloadedTrackAdapter;
private PlaylistAdapter playlistAdapter;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
@ -89,6 +82,8 @@ public class DownloadFragment extends Fragment {
initDownloadedArtistView(); initDownloadedArtistView();
initDownloadedAlbumView(); initDownloadedAlbumView();
initDownloadedSongView(); initDownloadedSongView();
initDownloadedPlaylistSlideView();
initPlaceholder();
} }
@Override @Override
@ -138,6 +133,12 @@ public class DownloadFragment extends Fragment {
bundle.putString(Song.DOWNLOADED, Song.DOWNLOADED); bundle.putString(Song.DOWNLOADED, Song.DOWNLOADED);
activity.navController.navigate(R.id.action_downloadFragment_to_songListPageFragment, bundle); 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() { 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.downloadDownloadedArtistPlaceholder.placeholder.setVisibility(View.VISIBLE);
if (bind != null) bind.downloadDownloadedArtistSector.setVisibility(View.GONE); if (bind != null) bind.downloadDownloadedArtistSector.setVisibility(View.GONE);
} else { } 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.downloadDownloadedArtistPlaceholder.placeholder.setVisibility(View.GONE);
if (bind != null) bind.downloadDownloadedArtistSector.setVisibility(!artists.isEmpty() ? View.VISIBLE : 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); 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.downloadDownloadedAlbumPlaceholder.placeholder.setVisibility(View.VISIBLE);
if (bind != null) bind.downloadDownloadedAlbumSector.setVisibility(View.GONE); if (bind != null) bind.downloadDownloadedAlbumSector.setVisibility(View.GONE);
} else { } 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.downloadDownloadedAlbumPlaceholder.placeholder.setVisibility(View.GONE);
if (bind != null) bind.downloadDownloadedAlbumSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : 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); 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.downloadDownloadedTracksPlaceholder.placeholder.setVisibility(View.VISIBLE);
if (bind != null) bind.downloadDownloadedTracksSector.setVisibility(View.GONE); if (bind != null) bind.downloadDownloadedTracksSector.setVisibility(View.GONE);
} else { } 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.downloadDownloadedTracksPlaceholder.placeholder.setVisibility(View.GONE);
if (bind != null) bind.downloadDownloadedTracksSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : 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); downloadedTrackAdapter.setItems(songs);
} }
@ -246,4 +241,60 @@ public class DownloadFragment extends Fragment {
requireContext().getResources().getColor(R.color.titleTextColor, null)) 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);
}
})
)
);
}
}
} }

View file

@ -28,6 +28,7 @@ import com.cappielloantonio.play.adapter.PlaylistAdapter;
import com.cappielloantonio.play.databinding.FragmentLibraryBinding; import com.cappielloantonio.play.databinding.FragmentLibraryBinding;
import com.cappielloantonio.play.helper.recyclerview.CustomLinearSnapHelper; import com.cappielloantonio.play.helper.recyclerview.CustomLinearSnapHelper;
import com.cappielloantonio.play.helper.recyclerview.DotsIndicatorDecoration; import com.cappielloantonio.play.helper.recyclerview.DotsIndicatorDecoration;
import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.ui.activity.MainActivity; import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.util.UIUtil; 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.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.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.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 -> { bind.albumCatalogueSampleTextViewRefreshable.setOnLongClickListener(view -> {
libraryViewModel.refreshAlbumSample(requireActivity()); libraryViewModel.refreshAlbumSample(requireActivity());
@ -249,7 +254,7 @@ public class LibraryFragment extends Fragment {
private void initPlaylistSlideView() { private void initPlaylistSlideView() {
bind.playlistViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL); bind.playlistViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
playlistAdapter = new PlaylistAdapter(activity, requireContext()); playlistAdapter = new PlaylistAdapter(activity, requireContext(), false);
bind.playlistViewPager.setAdapter(playlistAdapter); bind.playlistViewPager.setAdapter(playlistAdapter);
bind.playlistViewPager.setOffscreenPageLimit(3); bind.playlistViewPager.setOffscreenPageLimit(3);
libraryViewModel.getPlaylistSample().observe(requireActivity(), playlists -> { libraryViewModel.getPlaylistSample().observe(requireActivity(), playlists -> {

View file

@ -23,6 +23,8 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import com.cappielloantonio.play.R; import com.cappielloantonio.play.R;
import com.cappielloantonio.play.adapter.PlaylistCatalogueAdapter; import com.cappielloantonio.play.adapter.PlaylistCatalogueAdapter;
import com.cappielloantonio.play.databinding.FragmentPlaylistCatalogueBinding; 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.ui.activity.MainActivity;
import com.cappielloantonio.play.viewmodel.PlaylistCatalogueViewModel; import com.cappielloantonio.play.viewmodel.PlaylistCatalogueViewModel;
@ -39,8 +41,6 @@ public class PlaylistCatalogueFragment extends Fragment {
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setHasOptionsMenu(true); setHasOptionsMenu(true);
initData();
} }
@Override @Override
@ -49,7 +49,9 @@ public class PlaylistCatalogueFragment extends Fragment {
bind = FragmentPlaylistCatalogueBinding.inflate(inflater, container, false); bind = FragmentPlaylistCatalogueBinding.inflate(inflater, container, false);
View view = bind.getRoot(); View view = bind.getRoot();
playlistCatalogueViewModel = new ViewModelProvider(requireActivity()).get(PlaylistCatalogueViewModel.class);
init();
initAppBar(); initAppBar();
initPlaylistCatalogueView(); initPlaylistCatalogueView();
@ -68,8 +70,12 @@ public class PlaylistCatalogueFragment extends Fragment {
bind = null; bind = null;
} }
private void initData() { private void init() {
playlistCatalogueViewModel = new ViewModelProvider(requireActivity()).get(PlaylistCatalogueViewModel.class); if (getArguments().getString(Playlist.ALL) != null) {
playlistCatalogueViewModel.setType(Playlist.ALL);
} else if (getArguments().getString(Playlist.DOWNLOADED) != null) {
playlistCatalogueViewModel.setType(Playlist.DOWNLOADED);
}
} }
private void initAppBar() { private void initAppBar() {
@ -100,9 +106,9 @@ public class PlaylistCatalogueFragment extends Fragment {
bind.playlistCatalogueRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); bind.playlistCatalogueRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
bind.playlistCatalogueRecyclerView.setHasFixedSize(true); bind.playlistCatalogueRecyclerView.setHasFixedSize(true);
playlistCatalogueAdapter = new PlaylistCatalogueAdapter(activity, requireContext()); playlistCatalogueAdapter = new PlaylistCatalogueAdapter(activity, requireContext(), playlistCatalogueViewModel.getType().equals(Playlist.DOWNLOADED));
bind.playlistCatalogueRecyclerView.setAdapter(playlistCatalogueAdapter); bind.playlistCatalogueRecyclerView.setAdapter(playlistCatalogueAdapter);
playlistCatalogueViewModel.getPlaylistList().observe(requireActivity(), playlist -> { playlistCatalogueViewModel.getPlaylistList(requireActivity()).observe(requireActivity(), playlist -> {
playlistCatalogueAdapter.setItems(playlist); playlistCatalogueAdapter.setItems(playlist);
}); });

View file

@ -1,5 +1,6 @@
package com.cappielloantonio.play.ui.fragment; package com.cappielloantonio.play.ui.fragment;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
@ -81,12 +82,13 @@ public class PlaylistPageFragment extends Fragment {
@Override @Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) { public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) { if (item.getItemId() == R.id.action_download_playlist) {
case R.id.action_download_playlist: playlistPageViewModel.getPlaylistSongLiveList(requireActivity()).observe(requireActivity(), songs -> {
DownloadUtil.getDownloadTracker(requireContext()).download(Objects.requireNonNull(playlistPageViewModel.getPlaylistSongLiveList().getValue())); if (getContext() != null) {
return true; DownloadUtil.getDownloadTracker(requireContext()).download(songs, playlistPageViewModel.getPlaylist().getId(), playlistPageViewModel.getPlaylist().getName());
default: }
break; });
return true;
} }
return false; return false;
@ -94,6 +96,7 @@ public class PlaylistPageFragment extends Fragment {
private void init() { private void init() {
playlistPageViewModel.setPlaylist(getArguments().getParcelable("playlist_object")); playlistPageViewModel.setPlaylist(getArguments().getParcelable("playlist_object"));
playlistPageViewModel.setOffline(getArguments().getBoolean("is_offline"));
} }
private void initAppBar() { private void initAppBar() {
@ -110,13 +113,18 @@ public class PlaylistPageFragment extends Fragment {
bind.playlistSongCountLabel.setText("Song count: " + playlistPageViewModel.getPlaylist().getSongCount()); bind.playlistSongCountLabel.setText("Song count: " + playlistPageViewModel.getPlaylist().getSongCount());
bind.playlistDurationLabel.setText("Playlist duration: " + MusicUtil.getReadableDurationString(playlistPageViewModel.getPlaylist().getDuration(), false)); 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()); bind.animToolbar.setNavigationOnClickListener(v -> activity.navController.navigateUp());
Objects.requireNonNull(bind.animToolbar.getOverflowIcon()).setTint(requireContext().getResources().getColor(R.color.titleTextColor, null)); Objects.requireNonNull(bind.animToolbar.getOverflowIcon()).setTint(requireContext().getResources().getColor(R.color.titleTextColor, null));
} }
private void initMusicButton() { private void initMusicButton() {
playlistPageViewModel.getPlaylistSongLiveList().observe(requireActivity(), songs -> { playlistPageViewModel.getPlaylistSongLiveList(requireActivity()).observe(requireActivity(), songs -> {
if (bind != null) { if (bind != null) {
bind.playlistPagePlayButton.setOnClickListener(v -> { bind.playlistPagePlayButton.setOnClickListener(v -> {
QueueRepository queueRepository = new QueueRepository(App.getInstance()); QueueRepository queueRepository = new QueueRepository(App.getInstance());
@ -158,6 +166,6 @@ public class PlaylistPageFragment extends Fragment {
songHorizontalAdapter = new SongHorizontalAdapter(activity, requireContext(), true); songHorizontalAdapter = new SongHorizontalAdapter(activity, requireContext(), true);
bind.songRecyclerView.setAdapter(songHorizontalAdapter); bind.songRecyclerView.setAdapter(songHorizontalAdapter);
playlistPageViewModel.getPlaylistSongLiveList().observe(requireActivity(), songs -> songHorizontalAdapter.setItems(songs)); playlistPageViewModel.getPlaylistSongLiveList(requireActivity()).observe(requireActivity(), songs -> songHorizontalAdapter.setItems(songs));
} }
} }

View file

@ -140,9 +140,8 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
TextView removeAll = view.findViewById(R.id.remove_all_text_view); TextView removeAll = view.findViewById(R.id.remove_all_text_view);
albumBottomSheetViewModel.getAlbumTracks().observe(requireActivity(), songs -> { albumBottomSheetViewModel.getAlbumTracks().observe(requireActivity(), songs -> {
downloadAll.setOnClickListener(v -> { downloadAll.setOnClickListener(v -> {
DownloadUtil.getDownloadTracker(requireContext()).download(songs); DownloadUtil.getDownloadTracker(requireContext()).download(songs, null, null);
dismissBottomSheet(); dismissBottomSheet();
}); });

View file

@ -148,7 +148,7 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements
TextView download = view.findViewById(R.id.download_text_view); TextView download = view.findViewById(R.id.download_text_view);
download.setOnClickListener(v -> { download.setOnClickListener(v -> {
DownloadUtil.getDownloadTracker(requireContext()).download(Arrays.asList(song)); DownloadUtil.getDownloadTracker(requireContext()).download(Arrays.asList(song), null, null);
dismissBottomSheet(); dismissBottomSheet();
}); });

View file

@ -19,6 +19,7 @@ import com.cappielloantonio.play.subsonic.models.SimilarArtistID3;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class MappingUtil { public class MappingUtil {
public static ArrayList<Song> mapSong(List<Child> children) { public static ArrayList<Song> mapSong(List<Child> children) {
@ -144,18 +145,28 @@ public class MappingUtil {
return artists; return artists;
} }
public static ArrayList<Playlist> mapDownloadToPlaylist(List<Download> downloads) {
ArrayList<Playlist> playlists = new ArrayList();
for (Download download : downloads) {
playlists.add(new Playlist(download.getPlaylistId(), download.getPlaylistName()));
}
return playlists;
}
public static ArrayList<Download> mapToDownload(List<Song> songs) { public static ArrayList<Download> mapToDownload(List<Song> songs) {
ArrayList<Download> downloads = new ArrayList(); ArrayList<Download> downloads = new ArrayList();
for (Song song : songs) { for (Song song : songs) {
downloads.add(new Download(song)); downloads.add(new Download(song, null, null));
} }
return downloads; return downloads;
} }
public static Download mapToDownload(Song song) { public static Download mapToDownload(Song song, String playlistId, String playlistName) {
return new Download(song); return new Download(song, playlistId, playlistName);
} }
public static ArrayList<com.cappielloantonio.play.model.Genre> mapGenre(List<Genre> genreList) { public static ArrayList<com.cappielloantonio.play.model.Genre> mapGenre(List<Genre> genreList) {

View file

@ -10,6 +10,7 @@ import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.model.Album; import com.cappielloantonio.play.model.Album;
import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.model.Artist;
import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.repository.DownloadRepository; import com.cappielloantonio.play.repository.DownloadRepository;
import com.cappielloantonio.play.util.MappingUtil; import com.cappielloantonio.play.util.MappingUtil;
@ -24,6 +25,7 @@ public class DownloadViewModel extends AndroidViewModel {
private final MutableLiveData<List<Artist>> downloadedArtistSample = new MutableLiveData<>(null); private final MutableLiveData<List<Artist>> downloadedArtistSample = new MutableLiveData<>(null);
private final MutableLiveData<List<Album>> downloadedAlbumSample = new MutableLiveData<>(null); private final MutableLiveData<List<Album>> downloadedAlbumSample = new MutableLiveData<>(null);
private final MutableLiveData<List<Song>> downloadedTrackSample = new MutableLiveData<>(null); private final MutableLiveData<List<Song>> downloadedTrackSample = new MutableLiveData<>(null);
private final MutableLiveData<List<Playlist>> downloadedPlaylistSample = new MutableLiveData<>(null);
public DownloadViewModel(@NonNull Application application) { public DownloadViewModel(@NonNull Application application) {
super(application); super(application);
@ -32,17 +34,22 @@ public class DownloadViewModel extends AndroidViewModel {
} }
public LiveData<List<Artist>> getDownloadedArtists(LifecycleOwner owner, int size) { public LiveData<List<Artist>> 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; return downloadedArtistSample;
} }
public LiveData<List<Album>> getDownloadedAlbums(LifecycleOwner owner, int size) { public LiveData<List<Album>> 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; return downloadedAlbumSample;
} }
public LiveData<List<Song>> getDownloadedTracks(LifecycleOwner owner, int size) { public LiveData<List<Song>> 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; return downloadedTrackSample;
} }
public LiveData<List<Playlist>> getDownloadedPlaylists(LifecycleOwner owner, int size) {
downloadRepository.getLiveDownloadSample(size, false, false, false, true).observe(owner, downloads -> downloadedPlaylistSample.postValue(MappingUtil.mapDownloadToPlaylist(downloads)));
return downloadedPlaylistSample;
}
} }

View file

@ -3,24 +3,57 @@ package com.cappielloantonio.play.viewmodel;
import android.app.Application; import android.app.Application;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData; 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.Playlist;
import com.cappielloantonio.play.repository.DownloadRepository;
import com.cappielloantonio.play.repository.PlaylistRepository; import com.cappielloantonio.play.repository.PlaylistRepository;
import com.cappielloantonio.play.util.MappingUtil;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class PlaylistCatalogueViewModel extends AndroidViewModel { public class PlaylistCatalogueViewModel extends AndroidViewModel {
private final PlaylistRepository playlistRepository; private final PlaylistRepository playlistRepository;
private final DownloadRepository downloadRepository;
private String type;
private MutableLiveData<List<Playlist>> playlistList;
public PlaylistCatalogueViewModel(@NonNull Application application) { public PlaylistCatalogueViewModel(@NonNull Application application) {
super(application); super(application);
playlistRepository = new PlaylistRepository(application); playlistRepository = new PlaylistRepository(application);
downloadRepository = new DownloadRepository(application);
} }
public LiveData<List<Playlist>> getPlaylistList() { public LiveData<List<Playlist>> getPlaylistList(FragmentActivity activity) {
return playlistRepository.getPlaylists(false, -1); 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;
} }
} }

View file

@ -3,28 +3,45 @@ package com.cappielloantonio.play.viewmodel;
import android.app.Application; import android.app.Application;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.model.Album;
import com.cappielloantonio.play.model.Playlist; import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.repository.DownloadRepository;
import com.cappielloantonio.play.repository.PlaylistRepository; import com.cappielloantonio.play.repository.PlaylistRepository;
import com.cappielloantonio.play.util.MappingUtil;
import java.util.List; import java.util.List;
public class PlaylistPageViewModel extends AndroidViewModel { public class PlaylistPageViewModel extends AndroidViewModel {
private final PlaylistRepository playlistRepository; private final PlaylistRepository playlistRepository;
private final DownloadRepository downloadRepository;
private MutableLiveData<List<Song>> playlistSongLiveList = new MutableLiveData<>();
private Playlist playlist; private Playlist playlist;
private boolean isOffline;
public PlaylistPageViewModel(@NonNull Application application) { public PlaylistPageViewModel(@NonNull Application application) {
super(application); super(application);
playlistRepository = new PlaylistRepository(application); playlistRepository = new PlaylistRepository(application);
downloadRepository = new DownloadRepository(application);
} }
public MutableLiveData<List<Song>> getPlaylistSongLiveList() { public LiveData<List<Song>> getPlaylistSongLiveList(FragmentActivity activity) {
return playlistRepository.getPlaylistSongs(playlist.getId()); 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() { public Playlist getPlaylist() {
@ -34,4 +51,12 @@ public class PlaylistPageViewModel extends AndroidViewModel {
public void setPlaylist(Playlist playlist) { public void setPlaylist(Playlist playlist) {
this.playlist = playlist; this.playlist = playlist;
} }
public void setOffline(boolean offline) {
isOffline = offline;
}
public boolean isOffline() {
return isOffline;
}
} }

View file

@ -256,6 +256,61 @@
android:id="@+id/download_downloaded_tracks_placeholder" android:id="@+id/download_downloaded_tracks_placeholder"
layout="@layout/item_placeholder_horizontal" layout="@layout/item_placeholder_horizontal"
android:visibility="gone" /> android:visibility="gone" />
<LinearLayout
android:id="@+id/download_downloaded_playlist_sector"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="8dp">
<!-- Label and button -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="8dp"
android:paddingTop="8dp"
android:paddingEnd="8dp">
<TextView
android:id="@+id/downloaded_playlist_text_view_refreshable"
style="@style/HeadlineTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingStart="8dp"
android:paddingTop="12dp"
android:paddingEnd="8dp"
android:text="Playlists" />
<TextView
android:id="@+id/downloaded_playlist_text_view_clickable"
style="@style/SubheadTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="8dp"
android:paddingTop="12dp"
android:paddingEnd="8dp"
android:text="See all" />
</LinearLayout>
<!-- slideview -->
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/downloaded_playlist_view_pager"
android:layout_width="match_parent"
android:layout_height="212dp"
android:clipToPadding="false"
android:paddingTop="8dp"
android:paddingBottom="8dp" />
</LinearLayout>
<include
android:id="@+id/download_downloaded_playlist_placeholder"
layout="@layout/item_placeholder_album"
android:visibility="gone" />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -119,6 +119,12 @@
<action <action
android:id="@+id/action_downloadFragment_to_searchFragment" android:id="@+id/action_downloadFragment_to_searchFragment"
app:destination="@id/searchFragment" /> app:destination="@id/searchFragment" />
<action
android:id="@+id/action_downloadFragment_to_playlistPageFragment"
app:destination="@id/playlistPageFragment" />
<action
android:id="@+id/action_downloadFragment_to_playlistCatalogueFragment"
app:destination="@id/playlistCatalogueFragment" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/settingsFragment" android:id="@+id/settingsFragment"

View file

@ -6,7 +6,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.0.1' classpath 'com.android.tools.build:gradle:7.0.2'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30' classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong