diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/AlbumAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/AlbumAdapter.java index 199b6789..d7ffb1b2 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/AlbumAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/AlbumAdapter.java @@ -42,7 +42,7 @@ public class AlbumAdapter extends RecyclerView.Adapter holder.textArtistName.setText(album.getArtistName()); CustomGlideRequest.Builder - .from(context, album.getPrimary(), album.getBlurHash(), CustomGlideRequest.PRIMARY) + .from(context, album.getPrimary(), album.getBlurHash(), CustomGlideRequest.PRIMARY, CustomGlideRequest.TOP_QUALITY) .build() .into(holder.cover); } diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/AlbumArtistPageAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/AlbumArtistPageAdapter.java index 91e0a1cb..f8ae179b 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/AlbumArtistPageAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/AlbumArtistPageAdapter.java @@ -41,7 +41,7 @@ public class AlbumArtistPageAdapter extends RecyclerView.Adapter searchSuggestions(String query, int number); + + @Query("DELETE FROM album") + void deleteAll(); } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/database/dao/ArtistDao.java b/app/src/main/java/com/cappielloantonio/play/database/dao/ArtistDao.java index 77a207f7..ab60f273 100644 --- a/app/src/main/java/com/cappielloantonio/play/database/dao/ArtistDao.java +++ b/app/src/main/java/com/cappielloantonio/play/database/dao/ArtistDao.java @@ -34,6 +34,9 @@ public interface ArtistDao { @Delete void delete(Artist artist); - @Query("SELECT name FROM artist WHERE name LIKE :query || '%' GROUP BY name LIMIT :number") + @Query("SELECT name FROM artist WHERE name LIKE :query || '%' OR name like '% ' || :query || '%' GROUP BY name LIMIT :number") List searchSuggestions(String query, int number); + + @Query("DELETE FROM artist") + void deleteAll(); } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/database/dao/GenreDao.java b/app/src/main/java/com/cappielloantonio/play/database/dao/GenreDao.java index 8db179e0..c6836c8b 100644 --- a/app/src/main/java/com/cappielloantonio/play/database/dao/GenreDao.java +++ b/app/src/main/java/com/cappielloantonio/play/database/dao/GenreDao.java @@ -7,8 +7,6 @@ import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Query; -import com.cappielloantonio.play.model.Album; -import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.model.Genre; import java.util.List; @@ -35,4 +33,7 @@ public interface GenreDao { @Delete void delete(Genre genre); + + @Query("DELETE FROM genre") + void deleteAll(); } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/database/dao/PlaylistDao.java b/app/src/main/java/com/cappielloantonio/play/database/dao/PlaylistDao.java index 499ca1e9..486d9d5e 100644 --- a/app/src/main/java/com/cappielloantonio/play/database/dao/PlaylistDao.java +++ b/app/src/main/java/com/cappielloantonio/play/database/dao/PlaylistDao.java @@ -7,7 +7,6 @@ import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Query; -import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.model.Playlist; import java.util.List; @@ -28,4 +27,7 @@ public interface PlaylistDao { @Delete void delete(Playlist playlist); + + @Query("DELETE FROM playlist") + void deleteAll(); } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/database/dao/SongDao.java b/app/src/main/java/com/cappielloantonio/play/database/dao/SongDao.java index 028c14c0..4c497cb7 100644 --- a/app/src/main/java/com/cappielloantonio/play/database/dao/SongDao.java +++ b/app/src/main/java/com/cappielloantonio/play/database/dao/SongDao.java @@ -18,6 +18,9 @@ public interface SongDao { @Query("SELECT * FROM song") LiveData> getAll(); + @Query("SELECT * FROM song") + List getAllList(); + @Query("SELECT * FROM song WHERE title LIKE '%' || :title || '%'") LiveData> searchSong(String title); @@ -60,12 +63,15 @@ public interface SongDao { @Delete void delete(Song song); + @Query("DELETE FROM song") + void deleteAll(); + @Update public void update(Song song); @Query("SELECT * FROM song ORDER BY RANDOM() LIMIT :number") List random(int number); - @Query("SELECT title FROM song WHERE title LIKE :query || '%' GROUP BY title LIMIT :number") + @Query("SELECT title FROM song WHERE title LIKE :query || '%' OR title like '% ' || :query || '%' GROUP BY title LIMIT :number") List searchSuggestions(String query, int number); } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/database/dao/SongGenreCrossDao.java b/app/src/main/java/com/cappielloantonio/play/database/dao/SongGenreCrossDao.java index c3dd8898..70cb0b90 100644 --- a/app/src/main/java/com/cappielloantonio/play/database/dao/SongGenreCrossDao.java +++ b/app/src/main/java/com/cappielloantonio/play/database/dao/SongGenreCrossDao.java @@ -8,7 +8,6 @@ import androidx.room.OnConflictStrategy; import androidx.room.Query; import androidx.room.Update; -import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.model.SongGenreCross; import java.util.List; @@ -32,4 +31,7 @@ public interface SongGenreCrossDao { @Update void update(SongGenreCross songGenreCross); + + @Query("DELETE FROM song_genre_cross") + void deleteAll(); } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/glide/CustomGlideRequest.java b/app/src/main/java/com/cappielloantonio/play/glide/CustomGlideRequest.java index 4bc7520b..19d8082a 100644 --- a/app/src/main/java/com/cappielloantonio/play/glide/CustomGlideRequest.java +++ b/app/src/main/java/com/cappielloantonio/play/glide/CustomGlideRequest.java @@ -24,6 +24,10 @@ public class CustomGlideRequest { public static final String PRIMARY = "PRIMARY"; public static final String BACKDROP = "BACKDROP"; + public static final String TOP_QUALITY = "TOP"; + public static final String MEDIUM_QUALITY = "MEDIUM"; + public static final String LOW_QUALITY = "LOW"; + public static final DiskCacheStrategy DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.ALL; public static final int DEFAULT_IMAGE = R.drawable.ic_launcher_background; @@ -32,9 +36,9 @@ public class CustomGlideRequest { private final Object item; private final Context context; - private Builder(Context context, String item, String placeholder, String itemType) { + private Builder(Context context, String item, String placeholder, String itemType, String quality) { this.requestManager = Glide.with(context); - this.item = item != null ? createUrl(item, itemType) : DEFAULT_IMAGE; + this.item = item != null ? createUrl(item, itemType, quality) : DEFAULT_IMAGE; this.context = context; if (placeholder != null) { @@ -47,8 +51,8 @@ public class CustomGlideRequest { } } - public static Builder from(Context context, String item, String placeholder, String itemType) { - return new Builder(context, item, placeholder, itemType); + public static Builder from(Context context, String item, String placeholder, String itemType, String quality) { + return new Builder(context, item, placeholder, itemType, quality); } public RequestBuilder build() { @@ -67,8 +71,9 @@ public class CustomGlideRequest { return options; } - public static String createUrl(String item, String itemType) { + public static String createUrl(String item, String itemType, String quality) { ImageOptions options = new ImageOptions(); + switch(itemType) { case PRIMARY: { options.setImageType(ImageType.Primary); @@ -79,9 +84,27 @@ public class CustomGlideRequest { break; } } - options.setQuality(100); - options.setMaxHeight(500); - options.setEnableImageEnhancers(true); + + switch(quality) { + case TOP_QUALITY: { + options.setQuality(100); + options.setMaxHeight(800); + options.setEnableImageEnhancers(true); + break; + } + case MEDIUM_QUALITY: { + options.setQuality(80); + options.setMaxHeight(500); + options.setEnableImageEnhancers(true); + break; + } + case LOW_QUALITY: { + options.setQuality(60); + options.setMaxHeight(300); + options.setEnableImageEnhancers(true); + break; + } + } return App.getApiClientInstance(App.getInstance()).GetImageUrl(item, options); } diff --git a/app/src/main/java/com/cappielloantonio/play/model/Song.java b/app/src/main/java/com/cappielloantonio/play/model/Song.java index cbd04913..8444678e 100644 --- a/app/src/main/java/com/cappielloantonio/play/model/Song.java +++ b/app/src/main/java/com/cappielloantonio/play/model/Song.java @@ -381,14 +381,14 @@ public class Song implements Parcelable { this.added = added; } - public void setAdded(int playCount) { - this.playCount = playCount; - } - public void setLastPlay(long lastPlay) { this.lastPlay = lastPlay; } + public void setPlayCount(int playCount) { + this.playCount = playCount; + } + public void nowPlaying() { this.playCount++; this.lastPlay = Instant.now().toEpochMilli(); diff --git a/app/src/main/java/com/cappielloantonio/play/repository/AlbumRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/AlbumRepository.java index 5783abf1..93752562 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/AlbumRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/AlbumRepository.java @@ -1,17 +1,12 @@ package com.cappielloantonio.play.repository; import android.app.Application; -import android.util.Log; import androidx.lifecycle.LiveData; import com.cappielloantonio.play.database.AppDatabase; import com.cappielloantonio.play.database.dao.AlbumDao; -import com.cappielloantonio.play.database.dao.SongDao; import com.cappielloantonio.play.model.Album; -import com.cappielloantonio.play.model.Artist; -import com.cappielloantonio.play.model.Song; -import com.paulrybitskyi.persistentsearchview.adapters.model.SuggestionItem; import java.util.ArrayList; import java.util.List; @@ -103,6 +98,12 @@ public class AlbumRepository { thread.start(); } + public void deleteAll() { + DeleteAllThreadSafe delete = new DeleteAllThreadSafe(albumDao); + Thread thread = new Thread(delete); + thread.start(); + } + private static class ExistThreadSafe implements Runnable { private AlbumDao albumDao; private Album album; @@ -149,6 +150,7 @@ public class AlbumRepository { @Override public void run() { + albumDao.deleteAll(); albumDao.insertAll(albums); } } @@ -189,4 +191,17 @@ public class AlbumRepository { return suggestions; } } + + private static class DeleteAllThreadSafe implements Runnable { + private AlbumDao albumDao; + + public DeleteAllThreadSafe(AlbumDao albumDao) { + this.albumDao = albumDao; + } + + @Override + public void run() { + albumDao.deleteAll(); + } + } } diff --git a/app/src/main/java/com/cappielloantonio/play/repository/ArtistRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/ArtistRepository.java index b3f1ebee..31977f9d 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/ArtistRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/ArtistRepository.java @@ -5,14 +5,10 @@ import android.app.Application; import androidx.lifecycle.LiveData; import com.cappielloantonio.play.database.AppDatabase; -import com.cappielloantonio.play.database.dao.AlbumDao; import com.cappielloantonio.play.database.dao.ArtistDao; -import com.cappielloantonio.play.model.Album; import com.cappielloantonio.play.model.Artist; -import com.cappielloantonio.play.model.Song; import java.util.ArrayList; -import java.util.Collection; import java.util.List; public class ArtistRepository { @@ -95,6 +91,12 @@ public class ArtistRepository { thread.start(); } + public void deleteAll() { + DeleteAllThreadSafe delete = new DeleteAllThreadSafe(artistDao); + Thread thread = new Thread(delete); + thread.start(); + } + private static class ExistThreadSafe implements Runnable { private ArtistDao artistDao; private Artist artist; @@ -141,6 +143,7 @@ public class ArtistRepository { @Override public void run() { + artistDao.deleteAll(); artistDao.insertAll(artists); } } @@ -181,4 +184,17 @@ public class ArtistRepository { return suggestions; } } + + private static class DeleteAllThreadSafe implements Runnable { + private ArtistDao artistDao; + + public DeleteAllThreadSafe(ArtistDao artistDao) { + this.artistDao = artistDao; + } + + @Override + public void run() { + artistDao.deleteAll(); + } + } } diff --git a/app/src/main/java/com/cappielloantonio/play/repository/GenreRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/GenreRepository.java index 40df3c44..61ee90b3 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/GenreRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/GenreRepository.java @@ -7,9 +7,7 @@ import androidx.lifecycle.LiveData; import com.cappielloantonio.play.database.AppDatabase; import com.cappielloantonio.play.database.dao.GenreDao; import com.cappielloantonio.play.database.dao.SongGenreCrossDao; -import com.cappielloantonio.play.model.Album; import com.cappielloantonio.play.model.Genre; -import com.cappielloantonio.play.model.SongGenreCross; import java.util.ArrayList; import java.util.List; @@ -84,14 +82,20 @@ public class GenreRepository { thread.start(); } - public void insertPerGenre(ArrayList songGenreCrosses) { - InsertPerGenreThreadSafe insertPerGenre = new InsertPerGenreThreadSafe(songGenreCrossDao, songGenreCrosses); - Thread thread = new Thread(insertPerGenre); + public void delete(Genre genre) { + DeleteThreadSafe delete = new DeleteThreadSafe(genreDao, genre); + Thread thread = new Thread(delete); thread.start(); } - public void delete(Genre genre) { - DeleteThreadSafe delete = new DeleteThreadSafe(genreDao, genre); + public void deleteAll() { + DeleteAllGenreThreadSafe delete = new DeleteAllGenreThreadSafe(genreDao); + Thread thread = new Thread(delete); + thread.start(); + } + + public void deleteAllSongGenreCross() { + DeleteAllSongGenreCrossThreadSafe delete = new DeleteAllSongGenreCrossThreadSafe(songGenreCrossDao); Thread thread = new Thread(delete); thread.start(); } @@ -160,25 +164,11 @@ public class GenreRepository { @Override public void run() { + genreDao.deleteAll(); genreDao.insertAll(genres); } } - private static class InsertPerGenreThreadSafe implements Runnable { - private SongGenreCrossDao songGenreCrossDao; - private ArrayList cross; - - public InsertPerGenreThreadSafe(SongGenreCrossDao songGenreCrossDao, ArrayList cross) { - this.songGenreCrossDao = songGenreCrossDao; - this.cross = cross; - } - - @Override - public void run() { - songGenreCrossDao.insertAll(cross); - } - } - private static class DeleteThreadSafe implements Runnable { private GenreDao genreDao; private Genre genre; @@ -193,4 +183,30 @@ public class GenreRepository { genreDao.delete(genre); } } + + private static class DeleteAllGenreThreadSafe implements Runnable { + private GenreDao genreDao; + + public DeleteAllGenreThreadSafe(GenreDao genreDao) { + this.genreDao = genreDao; + } + + @Override + public void run() { + genreDao.deleteAll(); + } + } + + private static class DeleteAllSongGenreCrossThreadSafe implements Runnable { + private SongGenreCrossDao songGenreCrossDao; + + public DeleteAllSongGenreCrossThreadSafe(SongGenreCrossDao songGenreCrossDao) { + this.songGenreCrossDao = songGenreCrossDao; + } + + @Override + public void run() { + songGenreCrossDao.deleteAll(); + } + } } diff --git a/app/src/main/java/com/cappielloantonio/play/repository/PlaylistRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/PlaylistRepository.java index b76e9ca9..b64c9294 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/PlaylistRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/PlaylistRepository.java @@ -61,6 +61,12 @@ public class PlaylistRepository { thread.start(); } + public void deleteAll() { + DeleteAllThreadSafe delete = new DeleteAllThreadSafe(playlistDao); + Thread thread = new Thread(delete); + thread.start(); + } + private static class ExistThreadSafe implements Runnable { private PlaylistDao playlistDao; private Playlist playlist; @@ -107,6 +113,7 @@ public class PlaylistRepository { @Override public void run() { + playlistDao.deleteAll(); playlistDao.insertAll(playlists); } } @@ -125,4 +132,17 @@ public class PlaylistRepository { playlistDao.delete(playlist); } } + + private static class DeleteAllThreadSafe implements Runnable { + private PlaylistDao playlistDao; + + public DeleteAllThreadSafe(PlaylistDao playlistDao) { + this.playlistDao = playlistDao; + } + + @Override + public void run() { + playlistDao.deleteAll(); + } + } } diff --git a/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java index 319ece74..4fe2cbcc 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java @@ -5,17 +5,17 @@ import android.app.Application; import androidx.lifecycle.LiveData; import com.cappielloantonio.play.database.AppDatabase; -import com.cappielloantonio.play.database.dao.AlbumDao; import com.cappielloantonio.play.database.dao.SongDao; -import com.cappielloantonio.play.model.Album; +import com.cappielloantonio.play.database.dao.SongGenreCrossDao; import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.model.SongGenreCross; import java.util.ArrayList; -import java.util.Collection; import java.util.List; public class SongRepository { private SongDao songDao; + private SongGenreCrossDao songGenreCrossDao; private LiveData> searchListLiveSongs; private LiveData> listLiveSampleRecentlyAddedSongs; private LiveData> listLiveSampleRecentlyPlayedSongs; @@ -29,6 +29,7 @@ public class SongRepository { public SongRepository(Application application) { AppDatabase database = AppDatabase.getInstance(application); songDao = database.songDao(); + songGenreCrossDao = database.songGenreCrossDao(); } public LiveData> searchListLiveSong(String title) { @@ -93,6 +94,27 @@ public class SongRepository { return suggestions; } + /* + * Funzione che ritorna l'intero set di canzoni. + * Utilizzato per l'aggiornamento del catalogo. + */ + public List getCatalogue() { + List catalogue = new ArrayList<>(); + + GetCatalogueThreadSafe getCatalogueThread = new GetCatalogueThreadSafe(songDao); + Thread thread = new Thread(getCatalogueThread); + thread.start(); + + try { + thread.join(); + catalogue = getCatalogueThread.getCatalogue(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + return catalogue; + } + public boolean exist(Song song) { boolean exist = false; @@ -117,7 +139,7 @@ public class SongRepository { } public void insertAll(ArrayList songs) { - InsertAllThreadSafe insertAll = new InsertAllThreadSafe(songDao, songs); + InsertAllThreadSafe insertAll = new InsertAllThreadSafe(songDao, songGenreCrossDao, songs); Thread thread = new Thread(insertAll); thread.start(); } @@ -136,6 +158,30 @@ public class SongRepository { thread.start(); } + public void getAll() { + GetCatalogueThreadSafe catalogue = new GetCatalogueThreadSafe(songDao); + Thread thread = new Thread(catalogue); + thread.start(); + } + + public void insertSongPerGenre(ArrayList songGenreCrosses) { + InsertPerGenreThreadSafe insertPerGenre = new InsertPerGenreThreadSafe(songGenreCrossDao, songGenreCrosses); + Thread thread = new Thread(insertPerGenre); + thread.start(); + } + + public void deleteAllSong() { + DeleteAllSongThreadSafe delete = new DeleteAllSongThreadSafe(songDao); + Thread thread = new Thread(delete); + thread.start(); + } + + public void deleteAllSongGenreCross() { + DeleteAllSongGenreCrossThreadSafe delete = new DeleteAllSongGenreCrossThreadSafe(songGenreCrossDao); + Thread thread = new Thread(delete); + thread.start(); + } + public List getRandomSample(int number) { List sample = new ArrayList<>(); @@ -190,15 +236,19 @@ public class SongRepository { private static class InsertAllThreadSafe implements Runnable { private SongDao songDao; + private SongGenreCrossDao songGenreCrossDao; private ArrayList songs; - public InsertAllThreadSafe(SongDao songDao, ArrayList songs) { + public InsertAllThreadSafe(SongDao songDao, SongGenreCrossDao songGenreCrossDao, ArrayList songs) { this.songDao = songDao; + this.songGenreCrossDao = songGenreCrossDao; this.songs = songs; } @Override public void run() { + songDao.deleteAll(); + songGenreCrossDao.deleteAll(); songDao.insertAll(songs); } } @@ -274,4 +324,63 @@ public class SongRepository { return suggestions; } } + + private static class GetCatalogueThreadSafe implements Runnable { + private SongDao songDao; + private List catalogue = new ArrayList<>(); + + public GetCatalogueThreadSafe(SongDao songDao) { + this.songDao = songDao; + } + + @Override + public void run() { + catalogue = songDao.getAllList(); + } + + public List getCatalogue() { + return catalogue; + } + } + + private static class InsertPerGenreThreadSafe implements Runnable { + private SongGenreCrossDao songGenreCrossDao; + private ArrayList cross; + + public InsertPerGenreThreadSafe(SongGenreCrossDao songGenreCrossDao, ArrayList cross) { + this.songGenreCrossDao = songGenreCrossDao; + this.cross = cross; + } + + @Override + public void run() { + songGenreCrossDao.insertAll(cross); + } + } + + private static class DeleteAllSongThreadSafe implements Runnable { + private SongDao songDao; + + public DeleteAllSongThreadSafe(SongDao songDao) { + this.songDao = songDao; + } + + @Override + public void run() { + songDao.deleteAll(); + } + } + + private static class DeleteAllSongGenreCrossThreadSafe implements Runnable { + private SongGenreCrossDao songGenreCrossDao; + + public DeleteAllSongGenreCrossThreadSafe(SongGenreCrossDao songGenreCrossDao) { + this.songGenreCrossDao = songGenreCrossDao; + } + + @Override + public void run() { + songGenreCrossDao.deleteAll(); + } + } } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/activities/MainActivity.java b/app/src/main/java/com/cappielloantonio/play/ui/activities/MainActivity.java index 893afea6..b45360e5 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/activities/MainActivity.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/activities/MainActivity.java @@ -81,6 +81,16 @@ public class MainActivity extends BaseActivity { }); } + // True: VISIBLE + // False: GONE + public void setBottomNavigationBarVisibility(boolean visibility) { + if (visibility) { + bottomNavigationView.setVisibility(View.VISIBLE); + } else { + bottomNavigationView.setVisibility(View.GONE); + } + } + public void goToLogin() { if (Objects.requireNonNull(navController.getCurrentDestination()).getId() == R.id.landingFragment) navController.navigate(R.id.action_landingFragment_to_loginFragment); @@ -89,10 +99,7 @@ public class MainActivity extends BaseActivity { public void goToSync() { bottomNavigationView.setVisibility(View.GONE); - if (Objects.requireNonNull(navController.getCurrentDestination()).getId() == R.id.landingFragment) { - Bundle bundle = SyncUtil.getSyncBundle(true, true, true, true, true, false); - navController.navigate(R.id.action_landingFragment_to_syncFragment, bundle); - } else if (Objects.requireNonNull(navController.getCurrentDestination()).getId() == R.id.loginFragment) { + if (Objects.requireNonNull(navController.getCurrentDestination()).getId() == R.id.loginFragment) { Bundle bundle = SyncUtil.getSyncBundle(true, true, true, true, true, false); navController.navigate(R.id.action_loginFragment_to_syncFragment, bundle); } else if (Objects.requireNonNull(navController.getCurrentDestination()).getId() == R.id.homeFragment) { diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumPageFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumPageFragment.java index 14f318b6..6fc02575 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumPageFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumPageFragment.java @@ -48,7 +48,7 @@ public class AlbumPageFragment extends Fragment { private void initBackCover() { CustomGlideRequest.Builder - .from(requireContext(), albumPageViewModel.getAlbum().getPrimary(), albumPageViewModel.getAlbum().getBlurHash(), CustomGlideRequest.PRIMARY) + .from(requireContext(), albumPageViewModel.getAlbum().getPrimary(), albumPageViewModel.getAlbum().getBlurHash(), CustomGlideRequest.PRIMARY, CustomGlideRequest.TOP_QUALITY) .build() .into(bind.albumBackCoverImageView); } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistPageFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistPageFragment.java index b770f2f3..8ce15aa2 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistPageFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistPageFragment.java @@ -55,20 +55,17 @@ public class ArtistPageFragment extends Fragment { 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); - } + bind.mostStreamedSongTextViewClickable.setOnClickListener(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 initBackdrop() { CustomGlideRequest.Builder - .from(requireContext(), artistPageViewModel.getArtist().getBackdrop(), artistPageViewModel.getArtist().getBackdropBlurHash(), CustomGlideRequest.BACKDROP) + .from(requireContext(), artistPageViewModel.getArtist().getBackdrop(), artistPageViewModel.getArtist().getBackdropBlurHash(), CustomGlideRequest.BACKDROP, CustomGlideRequest.TOP_QUALITY) .build() .into(bind.artistBackdropImageView); } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/GenreCatalogueFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/GenreCatalogueFragment.java index 41d64f2e..d8e72435 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/GenreCatalogueFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/GenreCatalogueFragment.java @@ -58,14 +58,11 @@ public class GenreCatalogueFragment extends Fragment { bind.genreCatalogueRecyclerView.setHasFixedSize(true); genreCatalogueAdapter = new GenreCatalogueAdapter(requireContext(), new ArrayList<>()); - 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); - } + genreCatalogueAdapter.setClickListener((view, 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); diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SyncFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SyncFragment.java index dfef32af..0f463b02 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SyncFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SyncFragment.java @@ -1,8 +1,6 @@ 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; @@ -11,12 +9,10 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; 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; @@ -34,8 +30,6 @@ import com.cappielloantonio.play.ui.activities.MainActivity; import com.cappielloantonio.play.util.PreferenceUtil; import com.cappielloantonio.play.util.SyncUtil; import com.cappielloantonio.play.viewmodel.SyncViewModel; -import com.google.android.material.snackbar.BaseTransientBottomBar; -import com.google.android.material.snackbar.Snackbar; import org.jellyfin.apiclient.model.dto.BaseItemDto; @@ -181,7 +175,7 @@ public class SyncFragment extends Fragment { private void syncSongs() { Log.d(TAG, "syncSongs"); - SyncUtil.getSongs(requireContext(), new MediaCallback() { + SyncUtil.getSongs(requireContext(), syncViewModel.getCatalogue(), new MediaCallback() { @Override public void onError(Exception exception) { Log.e(TAG, "onError: " + exception.getMessage()); @@ -191,6 +185,7 @@ public class SyncFragment extends Fragment { @Override public void onLoadMedia(List media) { SongRepository repository = new SongRepository(activity.getApplication()); + repository.deleteAllSongGenreCross(); repository.insertAll((ArrayList) media); animateProgressBar(true); } @@ -198,6 +193,8 @@ public class SyncFragment extends Fragment { } private void syncSongsPerGenre(List genres) { + Log.d(TAG, "syncSongsPerGenre"); + for (Genre genre : genres) { SyncUtil.getSongsPerGenre(requireContext(), new MediaCallback() { @Override @@ -207,24 +204,30 @@ public class SyncFragment extends Fragment { @Override public void onLoadMedia(List media) { - GenreRepository repository = new GenreRepository(App.getInstance()); - repository.insertPerGenre((ArrayList) media); + SongRepository repository = new SongRepository(App.getInstance()); + repository.insertSongPerGenre((ArrayList) media); } }, 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(); diff --git a/app/src/main/java/com/cappielloantonio/play/util/SyncUtil.java b/app/src/main/java/com/cappielloantonio/play/util/SyncUtil.java index b2fc535f..fdf51524 100644 --- a/app/src/main/java/com/cappielloantonio/play/util/SyncUtil.java +++ b/app/src/main/java/com/cappielloantonio/play/util/SyncUtil.java @@ -2,6 +2,7 @@ package com.cappielloantonio.play.util; import android.content.Context; import android.os.Bundle; +import android.util.Log; import com.cappielloantonio.play.App; import com.cappielloantonio.play.interfaces.MediaCallback; @@ -23,8 +24,11 @@ import org.jellyfin.apiclient.model.querying.ItemsResult; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; public class SyncUtil { + private static final String TAG = "SyncUtil"; + public static void getLibraries(Context context, MediaCallback callback) { String id = App.getApiClientInstance(context).getCurrentUserId(); @@ -44,7 +48,7 @@ public class SyncUtil { }); } - public static void getSongs(Context context, MediaCallback callback) { + public static void getSongs(Context context, Map currentCatalogue, MediaCallback callback) { ItemQuery query = new ItemQuery(); query.setIncludeItemTypes(new String[]{"Audio"}); @@ -59,7 +63,7 @@ public class SyncUtil { ArrayList songs = new ArrayList<>(); for (BaseItemDto itemDto : result.getItems()) { - songs.add(new Song(itemDto)); + songs.add(updateSongData(currentCatalogue, new Song(itemDto))); } callback.onLoadMedia(songs); @@ -215,4 +219,18 @@ public class SyncUtil { return bundle; } + + private static Song updateSongData(Map library, Song newSong) { + if(library.containsKey(newSong.hashCode())) { + Log.d(TAG, "updateSongData: " + newSong.getTitle()); + + Song oldSong = library.get(newSong.hashCode()); + newSong.setFavorite(oldSong.isFavorite()); + newSong.setAdded(oldSong.getAdded()); + newSong.setLastPlay(oldSong.getLastPlay()); + newSong.setPlayCount(oldSong.getPlayCount()); + } + + return newSong; + } } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/SyncViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/SyncViewModel.java index 127a209a..64c5c9ee 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/SyncViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/SyncViewModel.java @@ -2,20 +2,21 @@ package com.cappielloantonio.play.viewmodel; import android.app.Application; import android.os.Bundle; -import android.util.Log; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; -import androidx.lifecycle.LiveData; import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.repository.SongRepository; -import java.util.List; +import java.util.HashMap; +import java.util.Map; public class SyncViewModel extends AndroidViewModel { private static final String TAG = "SyncViewModel"; + private SongRepository songRepository; + private boolean syncAlbum = false; private boolean syncArtist = false; private boolean syncGenres = false; @@ -29,9 +30,14 @@ public class SyncViewModel extends AndroidViewModel { public SyncViewModel(@NonNull Application application) { super(application); + + songRepository = new SongRepository(application); } public void setArguemnts(Bundle bundle) { + step = 0; + progress = 0; + syncAlbum = bundle.getBoolean("sync_album", false); syncArtist = bundle.getBoolean("sync_artist", false); syncGenres = bundle.getBoolean("sync_genres", false); @@ -90,4 +96,14 @@ public class SyncViewModel extends AndroidViewModel { public int getProgressBarInfo() { return progress * (100 / step); } + + public Map getCatalogue() { + Map map = new HashMap<>(); + + for(Song song: songRepository.getCatalogue()){ + map.put(song.hashCode(), song); + } + + return map; + } } diff --git a/app/src/main/res/drawable/gradient_background_image.xml b/app/src/main/res/drawable/gradient_backdrop_background_image.xml similarity index 100% rename from app/src/main/res/drawable/gradient_background_image.xml rename to app/src/main/res/drawable/gradient_backdrop_background_image.xml diff --git a/app/src/main/res/drawable/gradient_backdrop_fading_down_background_image.xml b/app/src/main/res/drawable/gradient_backdrop_fading_down_background_image.xml new file mode 100644 index 00000000..b16aca3a --- /dev/null +++ b/app/src/main/res/drawable/gradient_backdrop_fading_down_background_image.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/discover_background_image.xml b/app/src/main/res/drawable/gradient_discover_background_image.xml similarity index 100% rename from app/src/main/res/drawable/discover_background_image.xml rename to app/src/main/res/drawable/gradient_discover_background_image.xml diff --git a/app/src/main/res/layout/fragment_album_page.xml b/app/src/main/res/layout/fragment_album_page.xml index fa5cc033..04dd4116 100644 --- a/app/src/main/res/layout/fragment_album_page.xml +++ b/app/src/main/res/layout/fragment_album_page.xml @@ -1,6 +1,5 @@ - @@ -32,43 +31,53 @@ android:id="@+id/album_back_cover_image_view" android:layout_width="match_parent" android:layout_height="match_parent" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent"/> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - - + android:background="@drawable/gradient_backdrop_background_image" /> + + + + - @@ -32,43 +31,53 @@ android:id="@+id/artist_backdrop_image_view" android:layout_width="match_parent" android:layout_height="match_parent" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent"/> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - - + android:background="@drawable/gradient_backdrop_background_image" /> + + + + diff --git a/app/src/main/res/layout/item_home_discover_song.xml b/app/src/main/res/layout/item_home_discover_song.xml index aa6c1b0e..27eba077 100644 --- a/app/src/main/res/layout/item_home_discover_song.xml +++ b/app/src/main/res/layout/item_home_discover_song.xml @@ -18,7 +18,7 @@ + android:background="@drawable/gradient_discover_background_image" /> + app:destination="@id/syncFragment" + app:popUpTo="@id/homeFragment" + app:popUpToInclusive="true" />