Add favorite view

This commit is contained in:
Antonio Cappiello 2020-11-30 20:54:05 +01:00
parent ae23d268cd
commit 01bdbf49b2
52 changed files with 1064 additions and 317 deletions

View file

@ -13,6 +13,7 @@ import com.cappielloantonio.play.R;
import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Album;
import java.util.ArrayList;
import java.util.List;
public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder> {
@ -26,6 +27,7 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
public AlbumAdapter(Context context) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.albums = new ArrayList<>();
}
@Override

View file

@ -13,6 +13,7 @@ import com.cappielloantonio.play.R;
import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Album;
import java.util.ArrayList;
import java.util.List;
public class AlbumArtistPageAdapter extends RecyclerView.Adapter<AlbumArtistPageAdapter.ViewHolder> {
@ -26,6 +27,7 @@ public class AlbumArtistPageAdapter extends RecyclerView.Adapter<AlbumArtistPage
public AlbumArtistPageAdapter(Context context) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.albums = new ArrayList<>();
}
@Override

View file

@ -13,6 +13,7 @@ import com.cappielloantonio.play.R;
import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Album;
import java.util.ArrayList;
import java.util.List;
public class AlbumCatalogueAdapter extends RecyclerView.Adapter<AlbumCatalogueAdapter.ViewHolder> {
@ -26,6 +27,7 @@ public class AlbumCatalogueAdapter extends RecyclerView.Adapter<AlbumCatalogueAd
public AlbumCatalogueAdapter(Context context) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.albums = new ArrayList<>();
}
@Override

View file

@ -13,6 +13,7 @@ import com.cappielloantonio.play.R;
import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Artist;
import java.util.ArrayList;
import java.util.List;
public class ArtistAdapter extends RecyclerView.Adapter<ArtistAdapter.ViewHolder> {
@ -26,6 +27,7 @@ public class ArtistAdapter extends RecyclerView.Adapter<ArtistAdapter.ViewHolder
public ArtistAdapter(Context context) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.artists = new ArrayList<>();
}
@Override

View file

@ -13,6 +13,7 @@ import com.cappielloantonio.play.R;
import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Artist;
import java.util.ArrayList;
import java.util.List;
public class ArtistCatalogueAdapter extends RecyclerView.Adapter<ArtistCatalogueAdapter.ViewHolder> {
@ -26,6 +27,7 @@ public class ArtistCatalogueAdapter extends RecyclerView.Adapter<ArtistCatalogue
public ArtistCatalogueAdapter(Context context) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.artists = new ArrayList<>();
}
@Override

View file

@ -72,7 +72,7 @@ public class DiscoverSongAdapter extends RecyclerView.Adapter<DiscoverSongAdapte
@Override
public void onClick(View view) {
SongRepository songRepository = new SongRepository(App.getInstance());
songRepository.update(songs.get(getAdapterPosition()));
songRepository.increasePlayCount(songs.get(getAdapterPosition()));
}
}

View file

@ -11,6 +11,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.model.Genre;
import java.util.ArrayList;
import java.util.List;
public class GenreAdapter extends RecyclerView.Adapter<GenreAdapter.ViewHolder> {
@ -24,6 +25,7 @@ public class GenreAdapter extends RecyclerView.Adapter<GenreAdapter.ViewHolder>
public GenreAdapter(Context context) {
this.context = context;
this.mInflater = LayoutInflater.from(context);
this.genres = new ArrayList<>();
}
@Override

View file

@ -11,6 +11,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.model.Genre;
import java.util.ArrayList;
import java.util.List;
public class GenreCatalogueAdapter extends RecyclerView.Adapter<GenreCatalogueAdapter.ViewHolder> {
@ -24,6 +25,7 @@ public class GenreCatalogueAdapter extends RecyclerView.Adapter<GenreCatalogueAd
public GenreCatalogueAdapter(Context context) {
this.context = context;
this.mInflater = LayoutInflater.from(context);
this.genres = new ArrayList<>();
}
// inflates the row layout from xml when needed

View file

@ -11,6 +11,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.model.Playlist;
import java.util.ArrayList;
import java.util.List;
public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHolder> {
@ -24,6 +25,7 @@ public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHo
public PlaylistAdapter(Context context) {
this.context = context;
this.mInflater = LayoutInflater.from(context);
this.playlists = new ArrayList<>();
}
@Override

View file

@ -15,6 +15,7 @@ import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.repository.SongRepository;
import java.util.ArrayList;
import java.util.List;
/**
@ -30,6 +31,7 @@ public class RecentMusicAdapter extends RecyclerView.Adapter<RecentMusicAdapter.
public RecentMusicAdapter(Context context) {
this.context = context;
this.mInflater = LayoutInflater.from(context);
this.songs = new ArrayList<>();
}
@Override
@ -74,7 +76,7 @@ public class RecentMusicAdapter extends RecyclerView.Adapter<RecentMusicAdapter.
@Override
public void onClick(View view) {
SongRepository songRepository = new SongRepository(App.getInstance());
songRepository.update(songs.get(getAdapterPosition()));
songRepository.increasePlayCount(songs.get(getAdapterPosition()));
}
}

View file

@ -11,6 +11,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.model.RecentSearch;
import java.util.ArrayList;
import java.util.List;
public class RecentSearchAdapter extends RecyclerView.Adapter<RecentSearchAdapter.ViewHolder> {
@ -24,6 +25,7 @@ public class RecentSearchAdapter extends RecyclerView.Adapter<RecentSearchAdapte
public RecentSearchAdapter(Context context) {
this.context = context;
this.mInflater = LayoutInflater.from(context);
this.searches = new ArrayList<>();
}
@Override

View file

@ -7,6 +7,7 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import com.cappielloantonio.play.App;
@ -14,8 +15,10 @@ import com.cappielloantonio.play.R;
import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.repository.SongRepository;
import com.cappielloantonio.play.ui.fragment.bottomsheetdialog.SongBottomSheetDialog;
import com.cappielloantonio.play.util.Util;
import java.util.ArrayList;
import java.util.List;
/**
@ -27,10 +30,13 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter<SongResultSear
private List<Song> songs;
private LayoutInflater mInflater;
private Context context;
private FragmentManager fragmentManager;
public SongResultSearchAdapter(Context context) {
public SongResultSearchAdapter(Context context, FragmentManager fragmentManager) {
this.context = context;
this.fragmentManager = fragmentManager;
this.mInflater = LayoutInflater.from(context);
this.songs = new ArrayList<>();
}
@Override
@ -58,7 +64,7 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter<SongResultSear
return songs.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView songTitle;
TextView songArtist;
TextView songDuration;
@ -73,12 +79,20 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter<SongResultSear
cover = itemView.findViewById(R.id.song_cover_image_view);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
@Override
public void onClick(View view) {
SongRepository songRepository = new SongRepository(App.getInstance());
songRepository.update(songs.get(getAdapterPosition()));
songRepository.increasePlayCount(songs.get(getAdapterPosition()));
}
@Override
public boolean onLongClick(View v) {
SongBottomSheetDialog songBottomSheetDialog = new SongBottomSheetDialog(songs.get(getAdapterPosition()));
songBottomSheetDialog.show(fragmentManager, null);
return true;
}
}
@ -90,4 +104,5 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter<SongResultSear
public Song getItem(int id) {
return songs.get(id);
}
}

View file

@ -0,0 +1,30 @@
package com.cappielloantonio.play.broadcast.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.view.View;
import com.cappielloantonio.play.ui.activities.MainActivity;
public class ConnectivityStatusBroadcastReceiver extends BroadcastReceiver {
private MainActivity activity;
public ConnectivityStatusBroadcastReceiver(MainActivity activity) {
this.activity = activity;
}
@Override
public void onReceive(Context context, Intent intent) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (noConnectivity) {
activity.activityMainBinding.offlineModeLinearLayout.setVisibility(View.VISIBLE);
} else {
activity.activityMainBinding.offlineModeLinearLayout.setVisibility(View.GONE);
}
}
}
}

View file

@ -18,6 +18,9 @@ public interface SongDao {
@Query("SELECT * FROM song")
LiveData<List<Song>> getAll();
@Query("SELECT * FROM song WHERE id = :id")
LiveData<Song> getOne(String id);
@Query("SELECT * FROM song")
List<Song> getAllList();
@ -33,7 +36,7 @@ public interface SongDao {
@Query("SELECT * FROM song WHERE play_count != 0 ORDER BY play_count DESC LIMIT :number")
LiveData<List<Song>> getMostPlayedSample(int number);
@Query("SELECT * FROM song WHERE play_count != 0 AND artistId = :artistID ORDER BY play_count DESC LIMIT :number")
@Query("SELECT * FROM song WHERE artistId = :artistID ORDER BY play_count DESC LIMIT :number")
LiveData<List<Song>> getArtistTopSongsSample(String artistID, int number);
@Query("SELECT * FROM song WHERE artistId = :artistID ORDER BY play_count DESC")
@ -48,6 +51,12 @@ public interface SongDao {
@Query("SELECT * FROM song INNER Join song_genre_cross ON song.id = song_genre_cross.song_id AND song_genre_cross.genre_id IN (:filters) GROUP BY song.id")
LiveData<List<Song>> getFilteredSong(ArrayList<String> filters);
@Query("SELECT * FROM song WHERE favorite = 1 ORDER BY play_count DESC LIMIT :number")
LiveData<List<Song>> getFavoriteSongSample(int number);
@Query("SELECT * FROM song WHERE favorite = 1 ORDER BY play_count DESC")
LiveData<List<Song>> getFavoriteSong();
@Query("SELECT EXISTS(SELECT * FROM song WHERE id = :id)")
boolean exist(String id);

View file

@ -40,6 +40,9 @@ public class Song implements Parcelable {
@Ignore
public static final String BY_YEAR = "BY_YEAR";
@Ignore
public static final String IS_FAVORITE = "IS_FAVORITE";
@NonNull
@PrimaryKey
@ColumnInfo(name = "id")

View file

@ -17,6 +17,7 @@ public class SongRepository {
private SongDao songDao;
private SongGenreCrossDao songGenreCrossDao;
private LiveData<List<Song>> searchListLiveSongs;
private LiveData<Song> liveDataSong;
private LiveData<List<Song>> listLiveSampleRecentlyAddedSongs;
private LiveData<List<Song>> listLiveSampleRecentlyPlayedSongs;
private LiveData<List<Song>> listLiveSampleMostPlayedSongs;
@ -25,6 +26,8 @@ public class SongRepository {
private LiveData<List<Song>> listLiveSongByGenre;
private LiveData<List<Song>> listLiveFilteredSongs;
private LiveData<List<Song>> listLiveSongByYear;
private LiveData<List<Song>> listLiveSampleFavoritesSong;
private LiveData<List<Song>> listLiveFavoritesSong;
public SongRepository(Application application) {
@ -38,6 +41,11 @@ public class SongRepository {
return searchListLiveSongs;
}
public LiveData<Song> getLiveDataSong(String id) {
liveDataSong = songDao.getOne(id);
return liveDataSong;
}
public LiveData<List<Song>> getListLiveRecentlyAddedSampleSong(int number) {
listLiveSampleRecentlyAddedSongs = songDao.getRecentlyAddedSample(number);
return listLiveSampleRecentlyAddedSongs;
@ -138,6 +146,16 @@ public class SongRepository {
return listLiveSongByYear;
}
public LiveData<List<Song>> getListLiveFavoritesSampleSong(int number) {
listLiveSampleFavoritesSong = songDao.getFavoriteSongSample(number);
return listLiveSampleFavoritesSong;
}
public LiveData<List<Song>> getListLiveFavoritesSong() {
listLiveFavoritesSong = songDao.getFavoriteSong();
return listLiveFavoritesSong;
}
public boolean exist(Song song) {
boolean exist = false;
@ -173,7 +191,7 @@ public class SongRepository {
thread.start();
}
public void update(Song song) {
public void increasePlayCount(Song song) {
song.nowPlaying();
UpdateThreadSafe update = new UpdateThreadSafe(songDao, song);
@ -181,6 +199,12 @@ public class SongRepository {
thread.start();
}
public void setFavoriteStatus(Song song) {
UpdateThreadSafe update = new UpdateThreadSafe(songDao, song);
Thread thread = new Thread(update);
thread.start();
}
public void getAll() {
GetCatalogueThreadSafe catalogue = new GetCatalogueThreadSafe(songDao);
Thread thread = new Thread(catalogue);

View file

@ -1,5 +1,7 @@
package com.cappielloantonio.play.ui.activities;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.view.View;
@ -10,6 +12,7 @@ import androidx.navigation.ui.NavigationUI;
import com.cappielloantonio.play.App;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.broadcast.receiver.ConnectivityStatusBroadcastReceiver;
import com.cappielloantonio.play.databinding.ActivityMainBinding;
import com.cappielloantonio.play.ui.activities.base.BaseActivity;
import com.cappielloantonio.play.util.PreferenceUtil;
@ -26,23 +29,33 @@ import java.util.Objects;
public class MainActivity extends BaseActivity {
private static final String TAG = "MainActivity";
private ActivityMainBinding activityMainBinding;
public ActivityMainBinding activityMainBinding;
private FragmentManager fragmentManager;
private NavHostFragment navHostFragment;
private BottomNavigationView bottomNavigationView;
public NavController navController;
ConnectivityStatusBroadcastReceiver connectivityStatusBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
View view = activityMainBinding.getRoot();
setContentView(view);
connectivityStatusBroadcastReceiver = new ConnectivityStatusBroadcastReceiver(this);
connectivityStatusReceiverManager(true);
init();
}
@Override
protected void onDestroy() {
super.onDestroy();
connectivityStatusReceiverManager(false);
}
public void init() {
fragmentManager = getSupportFragmentManager();
bottomNavigationView = findViewById(R.id.bottom_navigation);
@ -76,7 +89,7 @@ public class MainActivity extends BaseActivity {
@Override
public void onError(Exception exception) {
goToLogin();
goFromLogin();
}
});
}
@ -130,4 +143,14 @@ public class MainActivity extends BaseActivity {
goToSync();
}
}
private void connectivityStatusReceiverManager(boolean isActive) {
if(isActive) {
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(connectivityStatusBroadcastReceiver, filter);
}
else {
unregisterReceiver(connectivityStatusBroadcastReceiver);
}
}
}

View file

@ -38,6 +38,12 @@ public class AlbumCatalogueFragment extends Fragment {
return view;
}
@Override
public void onStart() {
super.onStart();
activity.setBottomNavigationBarVisibility(false);
}
@Override
public void onDestroyView() {
super.onDestroyView();

View file

@ -13,10 +13,9 @@ import com.cappielloantonio.play.adapter.SongResultSearchAdapter;
import com.cappielloantonio.play.databinding.FragmentAlbumPageBinding;
import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.ui.activities.MainActivity;
import com.cappielloantonio.play.ui.fragment.bottomsheetdialog.AlbumBottomSheetDialog;
import com.cappielloantonio.play.viewmodel.AlbumPageViewModel;
import java.util.ArrayList;
public class AlbumPageFragment extends Fragment {
private FragmentAlbumPageBinding bind;
@ -26,7 +25,7 @@ public class AlbumPageFragment extends Fragment {
private SongResultSearchAdapter songResultSearchAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
activity = (MainActivity) getActivity();
bind = FragmentAlbumPageBinding.inflate(inflater, container, false);
@ -34,12 +33,19 @@ public class AlbumPageFragment extends Fragment {
albumPageViewModel = new ViewModelProvider(requireActivity()).get(AlbumPageViewModel.class);
init();
initBottomSheetDialog();
initBackCover();
initSongsView();
return view;
}
@Override
public void onStart() {
super.onStart();
activity.setBottomNavigationBarVisibility(false);
}
@Override
public void onDestroyView() {
super.onDestroyView();
@ -59,11 +65,18 @@ public class AlbumPageFragment extends Fragment {
bind.albumTitleLabel.setText(albumPageViewModel.getAlbum().getTitle());
}
private void initBottomSheetDialog() {
bind.albumSettingsImageButton.setOnClickListener(v -> {
AlbumBottomSheetDialog albumBottomSheetDialog = new AlbumBottomSheetDialog(albumPageViewModel.getAlbum());
albumBottomSheetDialog.show(this.getChildFragmentManager(), null);
});
}
private void initSongsView() {
bind.songRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
bind.songRecyclerView.setHasFixedSize(true);
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), new ArrayList<>());
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), getChildFragmentManager());
bind.songRecyclerView.setAdapter(songResultSearchAdapter);
albumPageViewModel.getAlbumSongList().observe(requireActivity(), songs -> songResultSearchAdapter.setItems(songs));
}

View file

@ -38,6 +38,12 @@ public class ArtistCatalogueFragment extends Fragment {
return view;
}
@Override
public void onStart() {
super.onStart();
activity.setBottomNavigationBarVisibility(false);
}
@Override
public void onDestroyView() {
super.onDestroyView();

View file

@ -18,8 +18,6 @@ import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.ui.activities.MainActivity;
import com.cappielloantonio.play.viewmodel.ArtistPageViewModel;
import java.util.ArrayList;
public class ArtistPageFragment extends Fragment {
private FragmentArtistPageBinding bind;
@ -45,6 +43,13 @@ public class ArtistPageFragment extends Fragment {
return view;
}
@Override
public void onStart() {
super.onStart();
activity.setBottomNavigationBarVisibility(false);
}
@Override
public void onDestroyView() {
super.onDestroyView();
@ -74,7 +79,7 @@ public class ArtistPageFragment extends Fragment {
bind.mostStreamedSongRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
bind.mostStreamedSongRecyclerView.setHasFixedSize(true);
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), new ArrayList<>());
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), getChildFragmentManager());
bind.mostStreamedSongRecyclerView.setAdapter(songResultSearchAdapter);
artistPageViewModel.getArtistTopSongList().observe(requireActivity(), songs -> songResultSearchAdapter.setItems(songs));
}

View file

@ -4,7 +4,6 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Toast;
import androidx.annotation.NonNull;
@ -41,6 +40,12 @@ public class FilterFragment extends Fragment {
return view;
}
@Override
public void onStart() {
super.onStart();
activity.setBottomNavigationBarVisibility(false);
}
@Override
public void onDestroyView() {
super.onDestroyView();

View file

@ -40,6 +40,12 @@ public class GenreCatalogueFragment extends Fragment {
return view;
}
@Override
public void onStart() {
super.onStart();
activity.setBottomNavigationBarVisibility(false);
}
@Override
public void onDestroyView() {
super.onDestroyView();

View file

@ -7,15 +7,18 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.viewpager2.widget.ViewPager2;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.adapter.DiscoverSongAdapter;
import com.cappielloantonio.play.adapter.RecentMusicAdapter;
import com.cappielloantonio.play.adapter.SongResultSearchAdapter;
import com.cappielloantonio.play.adapter.YearAdapter;
import com.cappielloantonio.play.databinding.FragmentHomeBinding;
import com.cappielloantonio.play.model.Song;
@ -33,6 +36,7 @@ public class HomeFragment extends Fragment {
private DiscoverSongAdapter discoverSongAdapter;
private RecentMusicAdapter recentlyAddedMusicAdapter;
private YearAdapter yearAdapter;
private SongResultSearchAdapter favoriteSongAdapter;
private RecentMusicAdapter recentlyPlayedMusicAdapter;
private RecentMusicAdapter mostPlayedMusicAdapter;
@ -46,15 +50,23 @@ public class HomeFragment extends Fragment {
homeViewModel = new ViewModelProvider(requireActivity()).get(HomeViewModel.class);
init();
initSwipeToRefresh();
initDiscoverSongSlideView();
initRecentAddedSongView();
initFavoritesSongView();
initYearSongView();
initRecentPlayedSongView();
initMostPlayedSongView();
initRecentPlayedSongView();
return view;
}
@Override
public void onStart() {
super.onStart();
activity.setBottomNavigationBarVisibility(true);
}
@Override
public void onDestroyView() {
super.onDestroyView();
@ -62,12 +74,6 @@ public class HomeFragment extends Fragment {
}
private void init() {
bind.resyncButton.setOnClickListener(v -> {
PreferenceUtil.getInstance(requireContext()).setSync(false);
PreferenceUtil.getInstance(requireContext()).setSongGenreSync(false);
activity.goToSync();
});
bind.recentlyAddedTracksTextViewClickable.setOnClickListener(v -> {
Bundle bundle = new Bundle();
bundle.putString(Song.RECENTLY_ADDED, Song.RECENTLY_ADDED);
@ -85,6 +91,29 @@ public class HomeFragment extends Fragment {
bundle.putString(Song.MOST_PLAYED, Song.MOST_PLAYED);
activity.navController.navigate(R.id.action_homeFragment_to_songListPageFragment, bundle);
});
bind.favoritesTracksTextViewClickable.setOnClickListener(v -> {
Bundle bundle = new Bundle();
bundle.putString(Song.IS_FAVORITE, Song.IS_FAVORITE);
activity.navController.navigate(R.id.action_homeFragment_to_songListPageFragment, bundle);
});
}
private void initSwipeToRefresh() {
bind.pullToRefreshLayout.setOnRefreshListener(() -> {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
builder.setMessage("Force reload your entire music library")
.setTitle("Force sync")
.setNegativeButton(R.string.ignore, null)
.setPositiveButton("Sync", (dialog, id) -> {
PreferenceUtil.getInstance(requireContext()).setSync(false);
PreferenceUtil.getInstance(requireContext()).setSongGenreSync(false);
activity.goToSync();
})
.show();
bind.pullToRefreshLayout.setRefreshing(false);
});
}
private void initDiscoverSongSlideView() {
@ -119,13 +148,13 @@ public class HomeFragment extends Fragment {
bind.yearsRecyclerView.setAdapter(yearAdapter);
}
private void initRecentPlayedSongView() {
bind.recentlyPlayedTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
bind.recentlyPlayedTracksRecyclerView.setHasFixedSize(true);
private void initFavoritesSongView() {
bind.favoritesTracksRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 3, GridLayoutManager.HORIZONTAL, false));
bind.favoritesTracksRecyclerView.setHasFixedSize(true);
recentlyPlayedMusicAdapter = new RecentMusicAdapter(requireContext());
bind.recentlyPlayedTracksRecyclerView.setAdapter(recentlyPlayedMusicAdapter);
homeViewModel.getRecentlyPlayedSongList().observe(requireActivity(), songs -> recentlyPlayedMusicAdapter.setItems(songs));
favoriteSongAdapter = new SongResultSearchAdapter(requireContext(), getChildFragmentManager());
bind.favoritesTracksRecyclerView.setAdapter(favoriteSongAdapter);
homeViewModel.getFavorites().observe(requireActivity(), songs -> favoriteSongAdapter.setItems(songs));
}
private void initMostPlayedSongView() {
@ -137,6 +166,15 @@ public class HomeFragment extends Fragment {
homeViewModel.getMostPlayedSongList().observe(requireActivity(), songs -> mostPlayedMusicAdapter.setItems(songs));
}
private void initRecentPlayedSongView() {
bind.recentlyPlayedTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
bind.recentlyPlayedTracksRecyclerView.setHasFixedSize(true);
recentlyPlayedMusicAdapter = new RecentMusicAdapter(requireContext());
bind.recentlyPlayedTracksRecyclerView.setAdapter(recentlyPlayedMusicAdapter);
homeViewModel.getRecentlyPlayedSongList().observe(requireActivity(), songs -> recentlyPlayedMusicAdapter.setItems(songs));
}
private void settDiscoverSongSlideViewOffset(float pageOffset, float pageMargin) {
bind.discoverSongViewPager.setPageTransformer((page, position) -> {
float myOffset = position * -(2 * pageOffset + pageMargin);

View file

@ -56,6 +56,12 @@ public class LibraryFragment extends Fragment {
return view;
}
@Override
public void onStart() {
super.onStart();
activity.setBottomNavigationBarVisibility(true);
}
@Override
public void onDestroyView() {
super.onDestroyView();
@ -66,7 +72,6 @@ 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.syncGenreButton.setOnClickListener(v -> syncSongsPerGenre());
}
private void initAlbumView() {

View file

@ -58,6 +58,12 @@ public class SearchFragment extends Fragment {
return view;
}
@Override
public void onStart() {
super.onStart();
activity.setBottomNavigationBarVisibility(true);
}
@Override
public void onDestroyView() {
super.onDestroyView();
@ -87,7 +93,7 @@ public class SearchFragment extends Fragment {
bind.searchResultTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
bind.searchResultTracksRecyclerView.setHasFixedSize(true);
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), new ArrayList<>());
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), getChildFragmentManager());
bind.searchResultTracksRecyclerView.setAdapter(songResultSearchAdapter);
// Albums

View file

@ -15,8 +15,6 @@ import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.ui.activities.MainActivity;
import com.cappielloantonio.play.viewmodel.SongListPageViewModel;
import java.util.ArrayList;
public class SongListPageFragment extends Fragment {
private FragmentSongListPageBinding bind;
@ -39,6 +37,12 @@ public class SongListPageFragment extends Fragment {
return view;
}
@Override
public void onStart() {
super.onStart();
activity.setBottomNavigationBarVisibility(false);
}
@Override
public void onDestroyView() {
super.onDestroyView();
@ -79,13 +83,17 @@ public class SongListPageFragment extends Fragment {
songListPageViewModel.year = getArguments().getInt("year_object");
bind.pageTitleLabel.setText("Year " + songListPageViewModel.year);
}
else if(getArguments().getString(Song.IS_FAVORITE) != null) {
songListPageViewModel.title = Song.IS_FAVORITE;
bind.pageTitleLabel.setText("Favourite song");
}
}
private void initSongListView() {
bind.songListRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
bind.songListRecyclerView.setHasFixedSize(true);
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), new ArrayList<>());
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), getChildFragmentManager());
bind.songListRecyclerView.setAdapter(songResultSearchAdapter);
songListPageViewModel.getSongList().observe(requireActivity(), songs -> songResultSearchAdapter.setItems(songs));
}

View file

@ -99,7 +99,6 @@ public class SyncFragment extends Fragment {
}
private void syncAlbums() {
Log.d(TAG, "syncAlbums");
SyncUtil.getAlbums(requireContext(), new MediaCallback() {
@Override
public void onError(Exception exception) {
@ -117,7 +116,6 @@ public class SyncFragment extends Fragment {
}
private void syncArtists() {
Log.d(TAG, "syncArtists");
SyncUtil.getArtists(requireContext(), new MediaCallback() {
@Override
public void onError(Exception exception) {
@ -135,7 +133,6 @@ public class SyncFragment extends Fragment {
}
private void syncGenres() {
Log.d(TAG, "syncGenres");
SyncUtil.getGenres(requireContext(), new MediaCallback() {
@Override
public void onError(Exception exception) {
@ -156,7 +153,6 @@ public class SyncFragment extends Fragment {
}
private void syncPlaylist() {
Log.d(TAG, "syncPlaylist");
SyncUtil.getPlaylists(requireContext(), new MediaCallback() {
@Override
public void onError(Exception exception) {
@ -174,7 +170,6 @@ public class SyncFragment extends Fragment {
}
private void syncSongs() {
Log.d(TAG, "syncSongs");
SyncUtil.getSongs(requireContext(), syncViewModel.getCatalogue(), new MediaCallback() {
@Override
public void onError(Exception exception) {
@ -193,8 +188,6 @@ public class SyncFragment extends Fragment {
}
private void syncSongsPerGenre(List<Genre> genres) {
Log.d(TAG, "syncSongsPerGenre");
for (Genre genre : genres) {
SyncUtil.getSongsPerGenre(requireContext(), new MediaCallback() {
@Override
@ -210,29 +203,23 @@ public class SyncFragment extends Fragment {
}, genre.id);
}
Log.d(TAG, "syncSongsPerGenre: set progress");
animateProgressBar(true);
PreferenceUtil.getInstance(requireContext()).setSongGenreSync(true);
}
private void animateProgressBar(boolean step) {
Log.d(TAG, "animateProgressBar: PROGRESS " + step);
syncViewModel.setProgress(step);
bind.loadingProgressBar.setProgress(syncViewModel.getProgressBarInfo(), true);
countProgress();
}
private void countProgress() {
Log.d(TAG, "countProgress = " + syncViewModel.getProgress());
Log.d(TAG, "progressbar = " + syncViewModel.getProgressBarInfo());
if (syncViewModel.getProgress() == syncViewModel.getStep()) {
if (syncViewModel.getProgressBarInfo() >= 100)
terminate();
else
if (syncViewModel.getProgressBarInfo() < 100)
Toast.makeText(requireContext(), "Sync error", Toast.LENGTH_SHORT).show();
terminate();
}
}

View file

@ -0,0 +1,54 @@
package com.cappielloantonio.play.ui.fragment.bottomsheetdialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.model.Album;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements View.OnClickListener {
private static final String TAG = "AlbumBottomSheetDialog";
private Album album;
public AlbumBottomSheetDialog(Album album) {
this.album = album;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet_album_dialog, container, false);
init(view);
return view;
}
private void init(View view) {
Button button1 = view.findViewById(R.id.button1);
Button button2 = view.findViewById(R.id.button2);
button1.setOnClickListener(v -> {
Toast.makeText(requireContext(), album.getTitle(), Toast.LENGTH_SHORT).show();
dismiss();
});
button2.setOnClickListener(v -> {
Toast.makeText(requireContext(), album.getArtistName(), Toast.LENGTH_SHORT).show();
dismiss();
});
}
@Override
public void onClick(View v) {
dismiss();
}
}

View file

@ -0,0 +1,121 @@
package com.cappielloantonio.play.ui.fragment.bottomsheetdialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.viewmodel.AlbumBottomSheetViewModel;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
public class SongBottomSheetDialog extends BottomSheetDialogFragment implements View.OnClickListener {
private static final String TAG = "AlbumBottomSheetDialog";
private AlbumBottomSheetViewModel albumBottomSheetViewModel;
private Song song;
private ImageView coverSong;
private TextView titleSong;
private TextView artistSong;
private ToggleButton thumbToggle;
private TextView playRadio;
private TextView playNext;
private TextView addToQueue;
private TextView Download;
private TextView addToPlaylist;
private TextView goToArtist;
public SongBottomSheetDialog(Song song) {
this.song = song;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet_song_dialog, container, false);
albumBottomSheetViewModel = new ViewModelProvider(requireActivity()).get(AlbumBottomSheetViewModel.class);
albumBottomSheetViewModel.setSong(song);
init(view);
return view;
}
private void init(View view) {
coverSong = view.findViewById(R.id.song_cover_image_view);
CustomGlideRequest.Builder
.from(requireContext(), albumBottomSheetViewModel.getSong().getPrimary(), albumBottomSheetViewModel.getSong().getBlurHash(), CustomGlideRequest.PRIMARY, CustomGlideRequest.TOP_QUALITY)
.build()
.into(coverSong);
titleSong = view.findViewById(R.id.song_title_text_view);
titleSong.setText(albumBottomSheetViewModel.getSong().getTitle());
artistSong = view.findViewById(R.id.song_artist_text_view);
artistSong.setText(albumBottomSheetViewModel.getSong().getArtistName());
thumbToggle = view.findViewById(R.id.button_favorite);
thumbToggle.setChecked(albumBottomSheetViewModel.getSong().isFavorite());
thumbToggle.setOnClickListener(v -> {
albumBottomSheetViewModel.setFavorite();
dismissBottomSheet();
});
playRadio = view.findViewById(R.id.play_radio_text_view);
playRadio.setOnClickListener(v -> {
Toast.makeText(requireContext(), "Play radio", Toast.LENGTH_SHORT).show();
dismissBottomSheet();
});
playNext = view.findViewById(R.id.play_next_text_view);
playNext.setOnClickListener(v -> {
Toast.makeText(requireContext(), "Play next", Toast.LENGTH_SHORT).show();
dismissBottomSheet();
});
addToQueue = view.findViewById(R.id.add_to_queue_text_view);
addToQueue.setOnClickListener(v -> {
Toast.makeText(requireContext(), "Add to queue", Toast.LENGTH_SHORT).show();
dismissBottomSheet();
});
Download = view.findViewById(R.id.download_text_view);
Download.setOnClickListener(v -> {
Toast.makeText(requireContext(), "Download", Toast.LENGTH_SHORT).show();
dismissBottomSheet();
});
addToPlaylist = view.findViewById(R.id.add_to_playlist_text_view);
addToPlaylist.setOnClickListener(v -> {
Toast.makeText(requireContext(), "Add to playlist", Toast.LENGTH_SHORT).show();
dismissBottomSheet();
});
goToArtist = view.findViewById(R.id.go_to_artist_text_view);
goToArtist.setOnClickListener(v -> {
Toast.makeText(requireContext(), "Go to artist", Toast.LENGTH_SHORT).show();
dismissBottomSheet();
});
}
@Override
public void onClick(View v) {
dismissBottomSheet();
}
private void dismissBottomSheet() {
dismiss();
}
}

View file

@ -0,0 +1,39 @@
package com.cappielloantonio.play.viewmodel;
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.repository.SongRepository;
public class AlbumBottomSheetViewModel extends AndroidViewModel {
private SongRepository songRepository;
private Song song;
public AlbumBottomSheetViewModel(@NonNull Application application) {
super(application);
songRepository = new SongRepository(application);
}
public void setSong(Song song) {
this.song = song;
}
public Song getSong() {
return song;
}
public void setFavorite() {
if(song.isFavorite()) {
song.setFavorite(false);
}
else {
song.setFavorite(true);
}
songRepository.setFavoriteStatus(song);
}
}

View file

@ -1,7 +1,6 @@
package com.cappielloantonio.play.viewmodel;
import android.app.Application;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
@ -20,6 +19,7 @@ public class HomeViewModel extends AndroidViewModel {
private LiveData<List<Song>> recentlyPlayedSongSample;
private LiveData<List<Song>> recentlyAddedSongSample;
private LiveData<List<Song>> mostPlayedSongSample;
private LiveData<List<Song>> favoritesSongSample;
private List<Integer> years;
public HomeViewModel(@NonNull Application application) {
@ -31,6 +31,7 @@ public class HomeViewModel extends AndroidViewModel {
recentlyPlayedSongSample = songRepository.getListLiveRecentlyPlayedSampleSong(20);
recentlyAddedSongSample = songRepository.getListLiveRecentlyAddedSampleSong(20);
mostPlayedSongSample = songRepository.getListLiveMostPlayedSampleSong(20);
favoritesSongSample = songRepository.getListLiveFavoritesSampleSong(20);
years = songRepository.getYearList();
}
@ -56,7 +57,10 @@ public class HomeViewModel extends AndroidViewModel {
}
public List<Integer> getYearList() {
Log.d(TAG, "getYearList: " + years.toString());
return years;
}
public LiveData<List<Song>> getFavorites() {
return favoritesSongSample;
}
}

View file

@ -56,6 +56,9 @@ public class SongListPageViewModel extends AndroidViewModel {
case Song.BY_YEAR:
songList = songRepository.getSongByYearListLive(year);
break;
case Song.IS_FAVORITE:
songList = songRepository.getListLiveFavoritesSong();
break;
}
return songList;