Add song/genre sync

This commit is contained in:
Antonio Cappiello 2020-11-24 10:52:00 +01:00
parent b2c269a051
commit 76037e487b
47 changed files with 703 additions and 89 deletions

View file

@ -56,7 +56,7 @@ public class AlbumCatalogueFragment extends Fragment {
albumAdapter.setClickListener((view, position) -> {
Bundle bundle = new Bundle();
bundle.putParcelable("album_object", albumAdapter.getItem(position));
activity.navController.navigate(R.id.action_libraryFragment_to_albumPageFragment, bundle);
activity.navController.navigate(R.id.action_albumCatalogueFragment_to_albumPageFragment, bundle);
});
bind.albumCatalogueRecyclerView.setAdapter(albumAdapter);
albumCatalogueViewModel.getAlbumList().observe(requireActivity(), albums -> {

View file

@ -16,6 +16,7 @@ import com.cappielloantonio.play.adapter.RecentMusicAdapter;
import com.cappielloantonio.play.adapter.SongResultSearchAdapter;
import com.cappielloantonio.play.databinding.FragmentArtistPageBinding;
import com.cappielloantonio.play.databinding.FragmentHomeBinding;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.ui.activities.MainActivity;
import com.cappielloantonio.play.viewmodel.ArtistPageViewModel;
import com.cappielloantonio.play.viewmodel.HomeViewModel;
@ -54,8 +55,17 @@ public class ArtistPageFragment extends Fragment {
private void init() {
artistPageViewModel.setArtist(getArguments().getParcelable("artist_object"));
bind.artistNameLabel.setText(artistPageViewModel.getArtist().getName());
bind.mostStreamedSongTextViewClickable.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putString(Song.BY_ARTIST, Song.BY_ARTIST);
bundle.putParcelable("artist_object", artistPageViewModel.getArtist());
activity.navController.navigate(R.id.action_artistPageFragment_to_songListPageFragment, bundle);
}
});
}
private void initTopSongsView() {

View file

@ -1,36 +1,54 @@
package com.cappielloantonio.play.ui.fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import com.cappielloantonio.play.App;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.adapter.ArtistCatalogueAdapter;
import com.cappielloantonio.play.adapter.GenreAdapter;
import com.cappielloantonio.play.adapter.GenreCatalogueAdapter;
import com.cappielloantonio.play.databinding.FragmentArtistCatalogueBinding;
import com.cappielloantonio.play.databinding.FragmentGenreCatalogueBinding;
import com.cappielloantonio.play.helper.recyclerview.ItemlDecoration;
import com.cappielloantonio.play.interfaces.MediaCallback;
import com.cappielloantonio.play.model.Genre;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.model.SongGenreCross;
import com.cappielloantonio.play.repository.GenreRepository;
import com.cappielloantonio.play.ui.activities.MainActivity;
import com.cappielloantonio.play.util.PreferenceUtil;
import com.cappielloantonio.play.util.SyncUtil;
import com.cappielloantonio.play.viewmodel.ArtistCatalogueViewModel;
import com.cappielloantonio.play.viewmodel.GenreCatalogueViewModel;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayList;
import java.util.List;
public class GenreCatalogueFragment extends Fragment {
private static final String TAG = "GenreCatalogueFragment";;
private FragmentGenreCatalogueBinding bind;
private MainActivity activity;
private GenreCatalogueViewModel genreCatalogueViewModel;
private GenreCatalogueAdapter genreCatalogueAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
activity = (MainActivity) getActivity();
bind = FragmentGenreCatalogueBinding.inflate(inflater, container, false);
View view = bind.getRoot();
genreCatalogueViewModel = new ViewModelProvider(requireActivity()).get(GenreCatalogueViewModel.class);
@ -52,7 +70,15 @@ public class GenreCatalogueFragment extends Fragment {
bind.genreCatalogueRecyclerView.setHasFixedSize(true);
genreCatalogueAdapter = new GenreCatalogueAdapter(requireContext(), new ArrayList<>());
genreCatalogueAdapter.setClickListener((view, position) -> Toast.makeText(requireContext(), "Click: " + position, Toast.LENGTH_SHORT).show());
genreCatalogueAdapter.setClickListener(new GenreCatalogueAdapter.ItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Bundle bundle = new Bundle();
bundle.putString(Song.BY_GENRE, Song.BY_GENRE);
bundle.putParcelable("genre_object", genreCatalogueAdapter.getItem(position));
activity.navController.navigate(R.id.action_genreCatalogueFragment_to_songListPageFragment, bundle);
}
});
bind.genreCatalogueRecyclerView.setAdapter(genreCatalogueAdapter);
genreCatalogueViewModel.getGenreList().observe(requireActivity(), genres -> {

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.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -12,9 +11,11 @@ import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.adapter.DiscoverSongAdapter;
import com.cappielloantonio.play.adapter.RecentMusicAdapter;
import com.cappielloantonio.play.databinding.FragmentHomeBinding;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.ui.activities.MainActivity;
import com.cappielloantonio.play.util.PreferenceUtil;
import com.cappielloantonio.play.viewmodel.HomeViewModel;
@ -60,8 +61,27 @@ 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);
activity.navController.navigate(R.id.action_homeFragment_to_songListPageFragment, bundle);
});
bind.recentlyPlayedTracksTextViewClickable.setOnClickListener(v -> {
Bundle bundle = new Bundle();
bundle.putString(Song.RECENTLY_PLAYED, Song.RECENTLY_PLAYED);
activity.navController.navigate(R.id.action_homeFragment_to_songListPageFragment, bundle);
});
bind.mostPlayedTracksTextViewClickable.setOnClickListener(v -> {
Bundle bundle = new Bundle();
bundle.putString(Song.MOST_PLAYED, Song.MOST_PLAYED);
activity.navController.navigate(R.id.action_homeFragment_to_songListPageFragment, bundle);
});
}
private void initDiscoverSongSlideView() {

View file

@ -9,24 +9,35 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.cappielloantonio.play.App;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.adapter.AlbumAdapter;
import com.cappielloantonio.play.adapter.ArtistAdapter;
import com.cappielloantonio.play.adapter.GenreAdapter;
import com.cappielloantonio.play.adapter.PlaylistAdapter;
import com.cappielloantonio.play.databinding.FragmentLibraryBinding;
import com.cappielloantonio.play.interfaces.MediaCallback;
import com.cappielloantonio.play.model.Album;
import com.cappielloantonio.play.model.Artist;
import com.cappielloantonio.play.model.Genre;
import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.model.SongGenreCross;
import com.cappielloantonio.play.repository.GenreRepository;
import com.cappielloantonio.play.ui.activities.MainActivity;
import com.cappielloantonio.play.util.PreferenceUtil;
import com.cappielloantonio.play.util.SyncUtil;
import com.cappielloantonio.play.viewmodel.LibraryViewModel;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayList;
import java.util.List;
@ -57,6 +68,7 @@ public class LibraryFragment extends Fragment {
initArtistView();
initGenreView();
initPlaylistView();
initCatalogueSyncCheck();
return view;
}
@ -106,7 +118,15 @@ public class LibraryFragment extends Fragment {
bind.genreRecyclerView.setHasFixedSize(true);
genreAdapter = new GenreAdapter(requireContext(), new ArrayList<>());
genreAdapter.setClickListener((view, position) -> Toast.makeText(requireContext(), "Genre: " + position, Toast.LENGTH_SHORT).show());
genreAdapter.setClickListener(new GenreAdapter.ItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Bundle bundle = new Bundle();
bundle.putString(Song.BY_GENRE, Song.BY_GENRE);
bundle.putParcelable("genre_object", genreAdapter.getItem(position));
activity.navController.navigate(R.id.action_libraryFragment_to_songListPageFragment, bundle);
}
});
bind.genreRecyclerView.setAdapter(genreAdapter);
libraryViewModel.getGenreSample().observe(requireActivity(), genres -> genreAdapter.setItems(genres));
}
@ -120,4 +140,39 @@ public class LibraryFragment extends Fragment {
bind.playlistRecyclerView.setAdapter(playlistAdapter);
libraryViewModel.getPlaylistList().observe(requireActivity(), playlists -> playlistAdapter.setItems(playlists));
}
private void initCatalogueSyncCheck() {
if (!PreferenceUtil.getInstance(requireContext()).getSongGenreSync()) {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
builder.setMessage("Sync song's genres otherwise nothing will be shown in each genre category")
.setTitle("Song's genres not synchronized")
.setNegativeButton(R.string.ignore, null)
.setPositiveButton("Sync", (dialog, id) -> syncSongsPerGenre(libraryViewModel.getGenreList()))
.show();
}
}
private void syncSongsPerGenre(List<Genre> genres) {
Snackbar.make(requireView(), "This may take a while...", BaseTransientBottomBar.LENGTH_LONG)
.setBackgroundTint(ContextCompat.getColor(requireContext(), R.color.cardColor))
.setTextColor(ContextCompat.getColor(requireContext(), R.color.titleTextColor))
.show();
for (Genre genre : genres) {
SyncUtil.getSongsPerGenre(requireContext(), new MediaCallback() {
@Override
public void onError(Exception exception) {
Log.e(TAG, "onError: " + exception.getMessage());
}
@Override
public void onLoadMedia(List<?> media) {
GenreRepository repository = new GenreRepository(App.getInstance());
repository.insertPerGenre((ArrayList<SongGenreCross>) media);
}
}, genre.id);
}
PreferenceUtil.getInstance(requireContext()).setSongGenreSync(true);
}
}

View file

@ -143,7 +143,7 @@ public class SearchFragment extends Fragment {
bind.persistentSearchView.collapse();
bind.persistentSearchView.setInputQuery(query);
performSearch(query);
performSearch(query.trim());
}
}

View file

@ -0,0 +1,82 @@
package com.cappielloantonio.play.ui.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.cappielloantonio.play.adapter.AlbumArtistPageAdapter;
import com.cappielloantonio.play.adapter.SongResultSearchAdapter;
import com.cappielloantonio.play.databinding.FragmentSongListPageBinding;
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;
private MainActivity activity;
private SongListPageViewModel songListPageViewModel;
private SongResultSearchAdapter songResultSearchAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
activity = (MainActivity) getActivity();
bind = FragmentSongListPageBinding.inflate(inflater, container, false);
View view = bind.getRoot();
songListPageViewModel = new ViewModelProvider(requireActivity()).get(SongListPageViewModel.class);
init();
initSongListView();
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
bind = null;
}
private void init() {
if(getArguments().getString(Song.RECENTLY_PLAYED) != null) {
songListPageViewModel.title = Song.RECENTLY_PLAYED;
bind.pageTitleLabel.setText(Song.RECENTLY_PLAYED);
}
else if(getArguments().getString(Song.MOST_PLAYED) != null) {
songListPageViewModel.title = Song.MOST_PLAYED;
bind.pageTitleLabel.setText(Song.MOST_PLAYED);
}
else if(getArguments().getString(Song.RECENTLY_ADDED) != null) {
songListPageViewModel.title = Song.RECENTLY_ADDED;
bind.pageTitleLabel.setText(Song.RECENTLY_ADDED);
}
else if(getArguments().getString(Song.BY_GENRE) != null) {
songListPageViewModel.title = Song.BY_GENRE;
songListPageViewModel.genre = getArguments().getParcelable("genre_object");
bind.pageTitleLabel.setText(Song.BY_GENRE);
}
else if(getArguments().getString(Song.BY_ARTIST) != null) {
songListPageViewModel.title = Song.BY_ARTIST;
songListPageViewModel.artist = getArguments().getParcelable("artist_object");
bind.pageTitleLabel.setText(Song.BY_ARTIST);
}
}
private void initSongListView() {
bind.songListRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
bind.songListRecyclerView.setHasFixedSize(true);
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), new ArrayList<>());
bind.songListRecyclerView.setAdapter(songResultSearchAdapter);
songListPageViewModel.getSongList().observe(requireActivity(), songs -> songResultSearchAdapter.setItems(songs));
}
}

View file

@ -1,6 +1,8 @@
package com.cappielloantonio.play.ui.fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@ -9,8 +11,11 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import com.cappielloantonio.play.App;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.databinding.FragmentSyncBinding;
import com.cappielloantonio.play.interfaces.MediaCallback;
import com.cappielloantonio.play.model.Album;
@ -18,6 +23,7 @@ import com.cappielloantonio.play.model.Artist;
import com.cappielloantonio.play.model.Genre;
import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.Song;
import com.cappielloantonio.play.model.SongGenreCross;
import com.cappielloantonio.play.repository.AlbumRepository;
import com.cappielloantonio.play.repository.ArtistRepository;
import com.cappielloantonio.play.repository.GenreRepository;
@ -26,6 +32,8 @@ import com.cappielloantonio.play.repository.SongRepository;
import com.cappielloantonio.play.ui.activities.MainActivity;
import com.cappielloantonio.play.util.PreferenceUtil;
import com.cappielloantonio.play.util.SyncUtil;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import org.jellyfin.apiclient.model.dto.BaseItemDto;
@ -39,6 +47,10 @@ public class SyncFragment extends Fragment {
private FragmentSyncBinding bind;
private ArrayList<Integer> progressing;
private List<Genre> genres;
private int stepMax = 5;
private int increment = 25;
@Nullable
@Override
@ -47,6 +59,8 @@ public class SyncFragment extends Fragment {
bind = FragmentSyncBinding.inflate(inflater, container, false);
View view = bind.getRoot();
init();
syncLibraries();
return view;
@ -58,11 +72,12 @@ public class SyncFragment extends Fragment {
bind = null;
}
private void showProgressBar() {
private void init() {
bind.loadingProgressBar.setVisibility(View.VISIBLE);
}
private void syncLibraries() {
Log.d(TAG, "syncLibraries");
progressing = new ArrayList<>();
SyncUtil.getLibraries(requireContext(), new MediaCallback() {
@ -77,7 +92,7 @@ public class SyncFragment extends Fragment {
for (BaseItemDto itemDto : libraries) {
if (itemDto.getCollectionType().equals("music"))
SyncUtil.musicLibrary = itemDto;
PreferenceUtil.getInstance(requireContext()).setMusicLibraryID(itemDto.getId());
}
startSyncing();
@ -86,7 +101,6 @@ public class SyncFragment extends Fragment {
}
private void startSyncing() {
showProgressBar();
syncAlbums();
syncArtists();
syncGenres();
@ -95,95 +109,103 @@ public class SyncFragment extends Fragment {
}
private void syncAlbums() {
Log.d(TAG, "syncAlbums");
SyncUtil.getAlbums(requireContext(), new MediaCallback() {
@Override
public void onError(Exception exception) {
Log.e(TAG, "onError: " + exception.getMessage());
setProgress(false);
setProgress(false, "Album");
}
@Override
public void onLoadMedia(List<?> media) {
AlbumRepository repository = new AlbumRepository(activity.getApplication());
repository.insertAll((ArrayList<Album>) media);
setProgress(true);
setProgress(true, "Album");
}
});
}
private void syncArtists() {
Log.d(TAG, "syncArtists");
SyncUtil.getArtists(requireContext(), new MediaCallback() {
@Override
public void onError(Exception exception) {
Log.e(TAG, "onError: " + exception.getMessage());
setProgress(false);
setProgress(false, "Artist");
}
@Override
public void onLoadMedia(List<?> media) {
ArtistRepository repository = new ArtistRepository(activity.getApplication());
repository.insertAll((ArrayList<Artist>) media);
setProgress(true);
setProgress(true, "Artist");
}
});
}
private void syncGenres() {
Log.d(TAG, "syncGenres");
SyncUtil.getGenres(requireContext(), new MediaCallback() {
@Override
public void onError(Exception exception) {
Log.e(TAG, "onError: " + exception.getMessage());
setProgress(false);
setProgress(false, "Genres");
}
@Override
public void onLoadMedia(List<?> media) {
GenreRepository repository = new GenreRepository(activity.getApplication());
repository.insertAll((ArrayList<Genre>) media);
setProgress(true);
setProgress(true, "Genres");
}
});
}
private void syncPlaylist() {
Log.d(TAG, "syncPlaylist");
SyncUtil.getPlaylists(requireContext(), new MediaCallback() {
@Override
public void onError(Exception exception) {
Log.e(TAG, "onError: " + exception.getMessage());
setProgress(false);
setProgress(false, "PlayList");
}
@Override
public void onLoadMedia(List<?> media) {
PlaylistRepository repository = new PlaylistRepository(activity.getApplication());
repository.insertAll((ArrayList<Playlist>) media);
setProgress(true);
setProgress(true, "PlayList");
}
});
}
private void syncSongs() {
Log.d(TAG, "syncSongs");
SyncUtil.getSongs(requireContext(), new MediaCallback() {
@Override
public void onError(Exception exception) {
Log.e(TAG, "onError: " + exception.getMessage());
setProgress(false);
setProgress(false, "Songs");
}
@Override
public void onLoadMedia(List<?> media) {
SongRepository repository = new SongRepository(activity.getApplication());
repository.insertAll((ArrayList<Song>) media);
setProgress(true);
setProgress(true, "Songs");
}
});
}
private void setProgress(boolean step) {
private void setProgress(boolean step, String who) {
if (step) {
progressing.add(25);
bind.loadingProgressBar.setProgress(bind.loadingProgressBar.getProgress() + 25, true);
Log.d(TAG, "setProgress " + who + ": adding " + increment);
progressing.add(increment);
bind.loadingProgressBar.setProgress(bind.loadingProgressBar.getProgress() + increment, true);
} else {
Log.d(TAG, "setProgress" + who + ": adding " + 0);
progressing.add(0);
}
@ -191,12 +213,14 @@ public class SyncFragment extends Fragment {
}
private void countProgress() {
if (progressing.size() == 5) {
if (progressing.size() == stepMax) {
if (bind.loadingProgressBar.getProgress() == 100)
terminate();
else
Toast.makeText(requireContext(), "Sync error", Toast.LENGTH_SHORT).show();
}
Log.d(TAG, "countProgress: SIZE: " + progressing.size() + " - SUM: " + bind.loadingProgressBar.getProgress());
}
private void terminate() {