From 2a103909d1811405260f1a70ee5cc520d9bfe009 Mon Sep 17 00:00:00 2001 From: CappielloAntonio Date: Sat, 15 Jan 2022 17:07:29 +0100 Subject: [PATCH] Added a new page dedicated to the favorites of artists, albums and songs --- .../cappielloantonio/play/model/Album.java | 1 + .../ui/fragment/AlbumListPageFragment.java | 5 +- .../play/ui/fragment/StarredFragment.java | 245 ++++++++++++++++++ .../viewmodel/AlbumListPageViewModel.java | 9 + .../play/viewmodel/StarredViewModel.java | 64 +++++ app/src/main/res/layout/fragment_starred.xml | 199 ++++++++++++++ app/src/main/res/navigation/nav_graph.xml | 21 ++ 7 files changed, 542 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/cappielloantonio/play/ui/fragment/StarredFragment.java create mode 100644 app/src/main/java/com/cappielloantonio/play/viewmodel/StarredViewModel.java create mode 100644 app/src/main/res/layout/fragment_starred.xml diff --git a/app/src/main/java/com/cappielloantonio/play/model/Album.java b/app/src/main/java/com/cappielloantonio/play/model/Album.java index 6b3b3f2f..b2927949 100644 --- a/app/src/main/java/com/cappielloantonio/play/model/Album.java +++ b/app/src/main/java/com/cappielloantonio/play/model/Album.java @@ -22,6 +22,7 @@ public class Album implements Parcelable { public static final String DOWNLOADED = "DOWNLOADED"; public static final String STARRED = "STARRED"; public static final String FROM_ARTIST = "FROM_ARTIST"; + public static final String NEW_RELEASES = "NEW_RELEASES"; private String id; private String title; diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumListPageFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumListPageFragment.java index a5840b20..93cb8d7d 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumListPageFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumListPageFragment.java @@ -1,6 +1,5 @@ package com.cappielloantonio.play.ui.fragment; -import android.annotation.SuppressLint; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -25,7 +24,6 @@ public class AlbumListPageFragment extends Fragment { private MainActivity activity; private AlbumListPageViewModel albumListPageViewModel; - private AlbumHorizontalAdapter albumHorizontalAdapter; @Override @@ -68,6 +66,9 @@ public class AlbumListPageFragment extends Fragment { } else if (requireArguments().getString(Album.STARRED) != null) { albumListPageViewModel.title = Album.STARRED; bind.pageTitleLabel.setText(R.string.album_list_page_starred); + } else if (requireArguments().getString(Album.NEW_RELEASES) != null) { + albumListPageViewModel.title = Album.NEW_RELEASES; + bind.pageTitleLabel.setText(R.string.album_list_page_new_releases); } else if (requireArguments().getString(Album.DOWNLOADED) != null) { albumListPageViewModel.title = Album.DOWNLOADED; bind.pageTitleLabel.setText(R.string.album_list_page_downloaded); diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/StarredFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/StarredFragment.java new file mode 100644 index 00000000..222256c9 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/StarredFragment.java @@ -0,0 +1,245 @@ +package com.cappielloantonio.play.ui.fragment; + +import android.annotation.SuppressLint; +import android.content.ComponentName; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.media3.session.MediaBrowser; +import androidx.media3.session.SessionToken; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.PagerSnapHelper; +import androidx.recyclerview.widget.SnapHelper; + +import com.cappielloantonio.play.R; +import com.cappielloantonio.play.adapter.AlbumHorizontalAdapter; +import com.cappielloantonio.play.adapter.ArtistHorizontalAdapter; +import com.cappielloantonio.play.adapter.SongHorizontalAdapter; +import com.cappielloantonio.play.databinding.FragmentStarredBinding; +import com.cappielloantonio.play.helper.recyclerview.DotsIndicatorDecoration; +import com.cappielloantonio.play.model.Album; +import com.cappielloantonio.play.model.Artist; +import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.service.MediaService; +import com.cappielloantonio.play.ui.activity.MainActivity; +import com.cappielloantonio.play.util.UIUtil; +import com.cappielloantonio.play.viewmodel.StarredViewModel; +import com.google.common.util.concurrent.ListenableFuture; + +public class StarredFragment extends Fragment { + private FragmentStarredBinding bind; + private MainActivity activity; + private StarredViewModel starredViewModel; + + private SongHorizontalAdapter starredSongAdapter; + private AlbumHorizontalAdapter starredAlbumAdapter; + private ArtistHorizontalAdapter starredArtistAdapter; + + private ListenableFuture mediaBrowserListenableFuture; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + activity = (MainActivity) getActivity(); + + bind = FragmentStarredBinding.inflate(inflater, container, false); + View view = bind.getRoot(); + starredViewModel = new ViewModelProvider(requireActivity()).get(StarredViewModel.class); + + init(); + initAppBar(); + initStarredTracksView(); + initStarredAlbumsView(); + initStarredArtistsView(); + + return view; + } + + @Override + public void onStart() { + super.onStart(); + + initializeMediaBrowser(); + activity.setBottomNavigationBarVisibility(false); + } + + @Override + public void onResume() { + super.onResume(); + + setMediaBrowserListenableFuture(); + } + + @Override + public void onStop() { + releaseMediaBrowser(); + super.onStop(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + bind = null; + } + + private void init() { + bind.starredTracksTextViewClickable.setOnClickListener(v -> { + Bundle bundle = new Bundle(); + bundle.putString(Song.STARRED, Song.STARRED); + activity.navController.navigate(R.id.action_starredFragment_to_songListPageFragment, bundle); + }); + + bind.starredAlbumsTextViewClickable.setOnClickListener(v -> { + Bundle bundle = new Bundle(); + bundle.putString(Album.STARRED, Album.STARRED); + activity.navController.navigate(R.id.action_starredFragment_to_albumListPageFragment, bundle); + }); + + bind.starredArtistsTextViewClickable.setOnClickListener(v -> { + Bundle bundle = new Bundle(); + bundle.putString(Artist.STARRED, Artist.STARRED); + activity.navController.navigate(R.id.action_starredFragment_to_artistListPageFragment, bundle); + }); + + bind.starredTracksTextViewRefreshable.setOnLongClickListener(v -> { + starredViewModel.refreshStarredTracks(requireActivity()); + return true; + }); + + bind.starredAlbumsTextViewRefreshable.setOnLongClickListener(v -> { + starredViewModel.refreshStarredAlbums(requireActivity()); + return true; + }); + + bind.starredArtistsTextViewRefreshable.setOnLongClickListener(v -> { + starredViewModel.refreshStarredArtists(requireActivity()); + return true; + }); + } + + private void initAppBar() { + activity.setSupportActionBar(bind.toolbar); + + if (activity.getSupportActionBar() != null) { + activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + activity.getSupportActionBar().setDisplayShowHomeEnabled(true); + } + + bind.toolbar.setNavigationOnClickListener(v -> activity.navController.navigateUp()); + + bind.toolbar.setTitle(R.string.starred_title); + } + + private void initStarredTracksView() { + bind.starredTracksRecyclerView.setHasFixedSize(true); + + starredSongAdapter = new SongHorizontalAdapter(activity, requireContext(), true); + bind.starredTracksRecyclerView.setAdapter(starredSongAdapter); + starredViewModel.getStarredTracks(requireActivity()).observe(requireActivity(), songs -> { + if (songs == null) { + if (bind != null) bind.starredTracksPlaceholder.placeholder.setVisibility(View.VISIBLE); + if (bind != null) bind.starredTracksSector.setVisibility(View.GONE); + } else { + if (bind != null) bind.starredTracksPlaceholder.placeholder.setVisibility(View.GONE); + if (bind != null) bind.starredTracksSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE); + if (bind != null) + bind.starredTracksRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(songs.size(), 5), GridLayoutManager.HORIZONTAL, false)); + + starredSongAdapter.setItems(songs); + } + }); + + SnapHelper starredTrackSnapHelper = new PagerSnapHelper(); + starredTrackSnapHelper.attachToRecyclerView(bind.starredTracksRecyclerView); + + bind.starredTracksRecyclerView.addItemDecoration( + new DotsIndicatorDecoration( + getResources().getDimensionPixelSize(R.dimen.radius), + getResources().getDimensionPixelSize(R.dimen.radius) * 4, + getResources().getDimensionPixelSize(R.dimen.dots_height), + requireContext().getResources().getColor(R.color.titleTextColor, null), + requireContext().getResources().getColor(R.color.titleTextColor, null)) + ); + } + + private void initStarredAlbumsView() { + bind.starredAlbumsRecyclerView.setHasFixedSize(true); + + starredAlbumAdapter = new AlbumHorizontalAdapter(requireContext(), false); + bind.starredAlbumsRecyclerView.setAdapter(starredAlbumAdapter); + starredViewModel.getStarredAlbums(requireActivity()).observe(requireActivity(), albums -> { + if (albums == null) { + if (bind != null) bind.starredAlbumsPlaceholder.placeholder.setVisibility(View.VISIBLE); + if (bind != null) bind.starredAlbumsSector.setVisibility(View.GONE); + } else { + if (bind != null) bind.starredAlbumsPlaceholder.placeholder.setVisibility(View.GONE); + if (bind != null) bind.starredAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE); + if (bind != null) + bind.starredAlbumsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(albums.size(), 5), GridLayoutManager.HORIZONTAL, false)); + + starredAlbumAdapter.setItems(albums); + } + }); + + SnapHelper starredAlbumSnapHelper = new PagerSnapHelper(); + starredAlbumSnapHelper.attachToRecyclerView(bind.starredAlbumsRecyclerView); + + bind.starredAlbumsRecyclerView.addItemDecoration( + new DotsIndicatorDecoration( + getResources().getDimensionPixelSize(R.dimen.radius), + getResources().getDimensionPixelSize(R.dimen.radius) * 4, + getResources().getDimensionPixelSize(R.dimen.dots_height), + requireContext().getResources().getColor(R.color.titleTextColor, null), + requireContext().getResources().getColor(R.color.titleTextColor, null)) + ); + } + + private void initStarredArtistsView() { + bind.starredArtistsRecyclerView.setHasFixedSize(true); + + starredArtistAdapter = new ArtistHorizontalAdapter(requireContext(), false); + bind.starredArtistsRecyclerView.setAdapter(starredArtistAdapter); + starredViewModel.getStarredArtists(requireActivity()).observe(requireActivity(), artists -> { + if (artists == null) { + if (bind != null) bind.starredArtistsPlaceholder.placeholder.setVisibility(View.VISIBLE); + if (bind != null) bind.starredArtistsSector.setVisibility(View.GONE); + } else { + if (bind != null) bind.starredArtistsPlaceholder.placeholder.setVisibility(View.GONE); + if (bind != null) bind.starredArtistsSector.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE); + if (bind != null) + bind.starredArtistsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(artists.size(), 5), GridLayoutManager.HORIZONTAL, false)); + + starredArtistAdapter.setItems(artists); + } + }); + + SnapHelper starredArtistSnapHelper = new PagerSnapHelper(); + starredArtistSnapHelper.attachToRecyclerView(bind.starredArtistsRecyclerView); + + bind.starredArtistsRecyclerView.addItemDecoration( + new DotsIndicatorDecoration( + getResources().getDimensionPixelSize(R.dimen.radius), + getResources().getDimensionPixelSize(R.dimen.radius) * 4, + getResources().getDimensionPixelSize(R.dimen.dots_height), + requireContext().getResources().getColor(R.color.titleTextColor, null), + requireContext().getResources().getColor(R.color.titleTextColor, null)) + ); + } + + @SuppressLint("UnsafeOptInUsageError") + private void initializeMediaBrowser() { + mediaBrowserListenableFuture = new MediaBrowser.Builder(requireContext(), new SessionToken(requireContext(), new ComponentName(requireContext(), MediaService.class))).buildAsync(); + } + + private void releaseMediaBrowser() { + MediaBrowser.releaseFuture(mediaBrowserListenableFuture); + } + + private void setMediaBrowserListenableFuture() { + starredSongAdapter.setMediaBrowserListenableFuture(mediaBrowserListenableFuture); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumListPageViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumListPageViewModel.java index bbbd3efa..df1736d4 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumListPageViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumListPageViewModel.java @@ -16,6 +16,8 @@ import com.cappielloantonio.play.repository.DownloadRepository; import com.cappielloantonio.play.util.MappingUtil; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Comparator; import java.util.List; public class AlbumListPageViewModel extends AndroidViewModel { @@ -50,6 +52,13 @@ public class AlbumListPageViewModel extends AndroidViewModel { case Album.STARRED: albumList = albumRepository.getStarredAlbums(false, -1); break; + case Album.NEW_RELEASES: + int currentYear = Calendar.getInstance().get(Calendar.YEAR); + albumRepository.getAlbums("byYear", 500, currentYear, currentYear).observe(owner, albums -> { + albums.sort(Comparator.comparing(Album::getCreated).reversed()); + albumList.postValue(albums.subList(0, Math.min(20, albums.size()))); + }); + break; case Album.DOWNLOADED: downloadRepository.getLiveDownload().observe(owner, downloads -> albumList.setValue(MappingUtil.mapDownloadToAlbum(downloads))); break; diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/StarredViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/StarredViewModel.java new file mode 100644 index 00000000..33353cd2 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/StarredViewModel.java @@ -0,0 +1,64 @@ +package com.cappielloantonio.play.viewmodel; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import com.cappielloantonio.play.model.Album; +import com.cappielloantonio.play.model.Artist; +import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.repository.AlbumRepository; +import com.cappielloantonio.play.repository.ArtistRepository; +import com.cappielloantonio.play.repository.SongRepository; + +import java.util.List; + +public class StarredViewModel extends AndroidViewModel { + private final SongRepository songRepository; + private final AlbumRepository albumRepository; + private final ArtistRepository artistRepository; + + private final MutableLiveData> starredTracks = new MutableLiveData<>(null); + private final MutableLiveData> starredAlbums = new MutableLiveData<>(null); + private final MutableLiveData> starredArtists = new MutableLiveData<>(null); + + + public StarredViewModel(@NonNull Application application) { + super(application); + + songRepository = new SongRepository(application); + albumRepository = new AlbumRepository(application); + artistRepository = new ArtistRepository(application); + } + + public LiveData> getStarredTracks(LifecycleOwner owner) { + songRepository.getStarredSongs(true, 20).observe(owner, starredTracks::postValue); + return starredTracks; + } + + public LiveData> getStarredAlbums(LifecycleOwner owner) { + albumRepository.getStarredAlbums(true, 20).observe(owner, starredAlbums::postValue); + return starredAlbums; + } + + public LiveData> getStarredArtists(LifecycleOwner owner) { + artistRepository.getStarredArtists(true, 20).observe(owner, starredArtists::postValue); + return starredArtists; + } + + public void refreshStarredTracks(LifecycleOwner owner) { + songRepository.getStarredSongs(true, 20).observe(owner, starredTracks::postValue); + } + + public void refreshStarredAlbums(LifecycleOwner owner) { + albumRepository.getStarredAlbums(true, 20).observe(owner, starredAlbums::postValue); + } + + public void refreshStarredArtists(LifecycleOwner owner) { + artistRepository.getStarredArtists(true, 20).observe(owner, starredArtists::postValue); + } +} diff --git a/app/src/main/res/layout/fragment_starred.xml b/app/src/main/res/layout/fragment_starred.xml new file mode 100644 index 00000000..1250a681 --- /dev/null +++ b/app/src/main/res/layout/fragment_starred.xml @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index b2156df1..6ebec048 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -101,6 +101,12 @@ + + + + + + +