diff --git a/app/src/main/java/com/cappielloantonio/tempo/database/dao/ChronologyDao.java b/app/src/main/java/com/cappielloantonio/tempo/database/dao/ChronologyDao.java index 906f7efa..1bb02ea0 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/database/dao/ChronologyDao.java +++ b/app/src/main/java/com/cappielloantonio/tempo/database/dao/ChronologyDao.java @@ -15,7 +15,7 @@ public interface ChronologyDao { @Query("SELECT * FROM chronology WHERE server == :server GROUP BY id ORDER BY timestamp DESC LIMIT :count") LiveData> getLastPlayed(String server, int count); - @Query("SELECT * FROM chronology WHERE timestamp >= :startDate AND timestamp < :endDate AND server == :server GROUP BY id ORDER BY COUNT(id) DESC LIMIT 9") + @Query("SELECT * FROM chronology WHERE timestamp >= :endDate AND timestamp < :startDate AND server == :server GROUP BY id ORDER BY COUNT(id) DESC LIMIT 20") LiveData> getAllFrom(long startDate, long endDate, String server); @Insert(onConflict = OnConflictStrategy.REPLACE) diff --git a/app/src/main/java/com/cappielloantonio/tempo/repository/ChronologyRepository.java b/app/src/main/java/com/cappielloantonio/tempo/repository/ChronologyRepository.java index ba775e42..8c9420c0 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/repository/ChronologyRepository.java +++ b/app/src/main/java/com/cappielloantonio/tempo/repository/ChronologyRepository.java @@ -12,28 +12,8 @@ import java.util.List; public class ChronologyRepository { private final ChronologyDao chronologyDao = AppDatabase.getInstance().chronologyDao(); - public LiveData> getThisWeek(String server) { - Calendar calendar = Calendar.getInstance(); - - Calendar first = (Calendar) calendar.clone(); - first.add(Calendar.DAY_OF_WEEK, first.getFirstDayOfWeek() - first.get(Calendar.DAY_OF_WEEK)); - - Calendar last = (Calendar) first.clone(); - last.add(Calendar.DAY_OF_YEAR, 6); - - return chronologyDao.getAllFrom(first.getTime().getTime(), last.getTime().getTime(), server); - } - - public LiveData> getLastWeek(String server) { - Calendar calendar = Calendar.getInstance(); - - Calendar first = (Calendar) calendar.clone(); - first.add(Calendar.DAY_OF_WEEK, first.getFirstDayOfWeek() - first.get(Calendar.DAY_OF_WEEK) - 6); - - Calendar last = (Calendar) first.clone(); - last.add(Calendar.DAY_OF_YEAR, 6); - - return chronologyDao.getAllFrom(first.getTime().getTime(), last.getTime().getTime(), server); + public LiveData> getChronology(String server, long start, long end) { + return chronologyDao.getAllFrom(start, end, server); } public void insert(Chronology item) { diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/HomeTabMusicFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/HomeTabMusicFragment.java index 7772b5ec..7649dbaf 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/HomeTabMusicFragment.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/HomeTabMusicFragment.java @@ -8,6 +8,7 @@ import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.PopupMenu; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -29,7 +30,6 @@ import com.cappielloantonio.tempo.R; import com.cappielloantonio.tempo.databinding.FragmentHomeTabMusicBinding; import com.cappielloantonio.tempo.helper.recyclerview.CustomLinearSnapHelper; import com.cappielloantonio.tempo.helper.recyclerview.DotsIndicatorDecoration; -import com.cappielloantonio.tempo.helper.recyclerview.GridItemDecoration; import com.cappielloantonio.tempo.interfaces.ClickCallback; import com.cappielloantonio.tempo.model.Download; import com.cappielloantonio.tempo.model.HomeSector; @@ -62,6 +62,7 @@ import com.google.common.util.concurrent.ListenableFuture; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @UnstableApi public class HomeTabMusicFragment extends Fragment implements ClickCallback { @@ -76,6 +77,7 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback { private ArtistAdapter radioArtistAdapter; private ArtistAdapter bestOfArtistAdapter; private SongHorizontalAdapter starredSongAdapter; + private SongHorizontalAdapter topSongAdapter; private AlbumHorizontalAdapter starredAlbumAdapter; private ArtistHorizontalAdapter starredArtistAdapter; private AlbumAdapter recentlyAddedAlbumAdapter; @@ -119,7 +121,7 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback { initNewReleasesView(); initYearSongView(); initRecentAddedAlbumView(); - initGridView(); + initTopSongsView(); initSharesView(); initHomeReorganizer(); @@ -253,6 +255,8 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback { homeViewModel.refreshShares(getViewLifecycleOwner()); return true; }); + + bind.gridTracksPreTextView.setOnClickListener(view -> showPopupMenu(view, R.menu.filter_top_songs_popup_menu)); } private void initSyncStarredView() { @@ -404,30 +408,41 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback { artistRadioSnapHelper.attachToRecyclerView(bind.radioArtistRecyclerView); } - private void initGridView() { + private void initTopSongsView() { if (homeViewModel.checkHomeSectorVisibility(Constants.HOME_SECTOR_TOP_SONGS)) return; - bind.gridTracksRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 3)); - bind.gridTracksRecyclerView.addItemDecoration(new GridItemDecoration(3, 8, false)); - bind.gridTracksRecyclerView.setHasFixedSize(true); + bind.topSongsRecyclerView.setHasFixedSize(true); - gridTrackAdapter = new GridTrackAdapter(this); - bind.gridTracksRecyclerView.setAdapter(gridTrackAdapter); + topSongAdapter = new SongHorizontalAdapter(this, true, false, null); + bind.topSongsRecyclerView.setAdapter(topSongAdapter); + homeViewModel.getChronologySample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), chronologies -> { + if (chronologies == null || chronologies.isEmpty()) { + if (bind != null) bind.homeGridTracksSector.setVisibility(View.GONE); + if (bind != null) bind.afterGridDivider.setVisibility(View.GONE); + } else { + if (bind != null) bind.homeGridTracksSector.setVisibility(View.VISIBLE); + if (bind != null) bind.afterGridDivider.setVisibility(View.VISIBLE); + if (bind != null) bind.topSongsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(chronologies.size(), 5), GridLayoutManager.HORIZONTAL, false)); - homeViewModel.getDiscoverSongSample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), music -> { - if (music != null) { - homeViewModel.getGridSongSample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), chronologies -> { - if (chronologies == null || chronologies.isEmpty()) { - if (bind != null) bind.homeGridTracksSector.setVisibility(View.GONE); - if (bind != null) bind.afterGridDivider.setVisibility(View.GONE); - } else { - if (bind != null) bind.homeGridTracksSector.setVisibility(View.VISIBLE); - if (bind != null) bind.afterGridDivider.setVisibility(View.VISIBLE); - gridTrackAdapter.setItems(chronologies); - } - }); + List topSongs = chronologies.stream() + .map(cronologia -> (Child) cronologia) + .collect(Collectors.toList()); + + topSongAdapter.setItems(topSongs); } }); + + SnapHelper topTrackSnapHelper = new PagerSnapHelper(); + topTrackSnapHelper.attachToRecyclerView(bind.topSongsRecyclerView); + + bind.topSongsRecyclerView.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 initStarredTracksView() { @@ -784,6 +799,31 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback { } } + private void showPopupMenu(View view, int menuResource) { + PopupMenu popup = new PopupMenu(requireContext(), view); + popup.getMenuInflater().inflate(menuResource, popup.getMenu()); + + popup.setOnMenuItemClickListener(menuItem -> { + if (menuItem.getItemId() == R.id.menu_last_week_name) { + homeViewModel.changeChronologyPeriod(getViewLifecycleOwner(), 0); + bind.gridTracksPreTextView.setText(getString(R.string.home_title_last_week)); + return true; + } else if (menuItem.getItemId() == R.id.menu_last_month_name) { + homeViewModel.changeChronologyPeriod(getViewLifecycleOwner(), 1); + bind.gridTracksPreTextView.setText(getString(R.string.home_title_last_month)); + return true; + } else if (menuItem.getItemId() == R.id.menu_last_year_name) { + homeViewModel.changeChronologyPeriod(getViewLifecycleOwner(), 2); + bind.gridTracksPreTextView.setText(getString(R.string.home_title_last_year)); + return true; + } + + return false; + }); + + popup.show(); + } + private void initializeMediaBrowser() { mediaBrowserListenableFuture = new MediaBrowser.Builder(requireContext(), new SessionToken(requireContext(), new ComponentName(requireContext(), MediaService.class))).buildAsync(); } diff --git a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/HomeViewModel.java b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/HomeViewModel.java index a9408df8..fb933e9f 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/HomeViewModel.java @@ -91,9 +91,17 @@ public class HomeViewModel extends AndroidViewModel { return songRepository.getRandomSample(100, null, null); } - public LiveData> getGridSongSample(LifecycleOwner owner) { + public LiveData> getChronologySample(LifecycleOwner owner) { + Calendar cal = Calendar.getInstance(); String server = Preferences.getServerId(); - chronologyRepository.getLastWeek(server).observe(owner, thisGridTopSong::postValue); + + int currentWeek = cal.get(Calendar.WEEK_OF_YEAR); + long start = cal.getTimeInMillis(); + + cal.set(Calendar.WEEK_OF_YEAR, currentWeek - 1); + long end = cal.getTimeInMillis(); + + chronologyRepository.getChronology(server, start, end).observe(owner, thisGridTopSong::postValue); return thisGridTopSong; } @@ -228,6 +236,31 @@ public class HomeViewModel extends AndroidViewModel { return songRepository.getStarredSongs(false, -1); } + public void changeChronologyPeriod(LifecycleOwner owner, int period) { + Calendar cal = Calendar.getInstance(); + String server = Preferences.getServerId(); + int currentWeek = cal.get(Calendar.WEEK_OF_YEAR); + + long start = 0; + long end = 0; + + if (period == 0) { + start = cal.getTimeInMillis(); + cal.set(Calendar.WEEK_OF_YEAR, currentWeek - 1); + end = cal.getTimeInMillis(); + } else if (period == 1) { + start = cal.getTimeInMillis(); + cal.set(Calendar.WEEK_OF_YEAR, currentWeek - 4); + end = cal.getTimeInMillis(); + } else if (period == 2) { + start = cal.getTimeInMillis(); + cal.set(Calendar.WEEK_OF_YEAR, currentWeek - 52); + end = cal.getTimeInMillis(); + } + + chronologyRepository.getChronology(server, start, end).observe(owner, thisGridTopSong::postValue); + } + public void refreshDiscoverySongSample(LifecycleOwner owner) { songRepository.getRandomSample(10, null, null).observe(owner, dicoverSongSample::postValue); } diff --git a/app/src/main/res/layout/fragment_home_tab_music.xml b/app/src/main/res/layout/fragment_home_tab_music.xml index 02c6d35e..b50b4199 100644 --- a/app/src/main/res/layout/fragment_home_tab_music.xml +++ b/app/src/main/res/layout/fragment_home_tab_music.xml @@ -311,16 +311,15 @@ android:text="@string/home_title_top_songs" /> + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9bbafd15..546ad228 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -110,6 +110,8 @@ Last played See all Last week + Last month + Last year Made for you Most played See all @@ -155,6 +157,9 @@ Track Year Home + Last week + Last month + Last year Library Search Settings