diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 89e292aa..03e07a5f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -21,10 +21,8 @@ android:windowSoftInputMode="adjustPan|adjustResize"> - - \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/App.java b/app/src/main/java/com/cappielloantonio/play/App.java index 80c65746..6b837813 100644 --- a/app/src/main/java/com/cappielloantonio/play/App.java +++ b/app/src/main/java/com/cappielloantonio/play/App.java @@ -2,12 +2,7 @@ package com.cappielloantonio.play; import android.app.Application; import android.content.Context; -import android.content.SharedPreferences; -import androidx.preference.PreferenceManager; - -import com.android.volley.RequestQueue; -import com.android.volley.toolbox.Volley; import com.cappielloantonio.play.helper.ThemeHelper; import com.cappielloantonio.play.util.PreferenceUtil; @@ -46,10 +41,6 @@ public class App extends Application { return apiClient; } - public RequestQueue getRequestQueue(Context context) { - return Volley.newRequestQueue(context); - } - private static ApiClient getApiClient(Context context) { String server = PreferenceUtil.getInstance(context).getServer(); diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/DiscoverSongAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/DiscoverSongAdapter.java index 32683664..c759750f 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/DiscoverSongAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/DiscoverSongAdapter.java @@ -1,20 +1,20 @@ package com.cappielloantonio.play.adapter; import android.content.Context; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager.widget.PagerAdapter; import com.cappielloantonio.play.App; import com.cappielloantonio.play.R; import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.repository.SongRepository; +import com.cappielloantonio.play.util.Util; import java.util.List; @@ -29,8 +29,6 @@ public class DiscoverSongAdapter extends PagerAdapter { public DiscoverSongAdapter(Context context, List songs) { this.context = context; this.songs = songs; - - Log.d(TAG, "DiscoverSongAdapter: " + songs.toString()); } @Override @@ -50,7 +48,7 @@ public class DiscoverSongAdapter extends PagerAdapter { view = layoutInflater.inflate(R.layout.item_home_discover_song, container, false); TextView title = view.findViewById(R.id.title_discover_song_label); - TextView desc = view.findViewById(R.id.artist_discover_song_label); + TextView desc = view.findViewById(R.id.album_discover_song_label); title.setText(songs.get(position).getTitle()); desc.setText(songs.get(position).getAlbumName()); @@ -64,8 +62,6 @@ public class DiscoverSongAdapter extends PagerAdapter { } public void setItems(List songs) { - Log.d(TAG, "setItems: CHANGING"); - this.songs = songs; notifyDataSetChanged(); } diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/GenreAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/GenreAdapter.java index 50a0366a..c17e9fe5 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/GenreAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/GenreAdapter.java @@ -62,6 +62,10 @@ public class GenreAdapter extends RecyclerView.Adapter } } + public Genre getItem(int position) { + return genres.get(position); + } + public void setItems(List genres) { this.genres = genres; notifyDataSetChanged(); diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/GenreCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/GenreCatalogueAdapter.java index 24bf0a8c..2ceeb69d 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/GenreCatalogueAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/GenreCatalogueAdapter.java @@ -1,6 +1,7 @@ package com.cappielloantonio.play.adapter; import android.content.Context; +import android.os.Parcelable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -45,6 +46,7 @@ public class GenreCatalogueAdapter extends RecyclerView.Adapter genres) { this.genres = genres; notifyDataSetChanged(); diff --git a/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java b/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java index f843abc2..8040f356 100644 --- a/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java +++ b/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java @@ -12,14 +12,16 @@ import com.cappielloantonio.play.database.dao.GenreDao; import com.cappielloantonio.play.database.dao.PlaylistDao; import com.cappielloantonio.play.database.dao.RecentSearchDao; import com.cappielloantonio.play.database.dao.SongDao; +import com.cappielloantonio.play.database.dao.SongGenreCrossDao; 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.RecentSearch; import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.model.SongGenreCross; -@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class}, version = 4, exportSchema = false) +@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class, SongGenreCross.class}, version = 5, exportSchema = false) public abstract class AppDatabase extends RoomDatabase { private static final String TAG = "AppDatabase"; @@ -47,4 +49,6 @@ public abstract class AppDatabase extends RoomDatabase { public abstract SongDao songDao(); public abstract RecentSearchDao recentSearchDao(); + + public abstract SongGenreCrossDao songGenreCrossDao(); } 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 ada403b6..8db179e0 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 @@ -18,6 +18,9 @@ public interface GenreDao { @Query("SELECT * FROM genre") LiveData> getAll(); + @Query("SELECT * FROM genre") + List getGenreList(); + @Query("SELECT * FROM genre ORDER BY RANDOM() LIMIT :number;") LiveData> getSample(int number); 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 744456dd..f5e8fa01 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 @@ -35,9 +35,15 @@ public interface SongDao { @Query("SELECT * FROM song WHERE play_count != 0 AND artistId = :artistID ORDER BY play_count DESC LIMIT :number") LiveData> getArtistTopSongsSample(String artistID, int number); + @Query("SELECT * FROM song WHERE artistId = :artistID ORDER BY play_count DESC") + LiveData> getArtistTopSongs(String artistID); + @Query("SELECT * FROM song WHERE albumId = :albumID ORDER BY trackNumber ASC") LiveData> getAlbumSong(String albumID); + @Query("SELECT * FROM song INNER Join song_genre_cross ON song.id = song_genre_cross.song_id AND song_genre_cross.genre_id = :genreID") + LiveData> getSongByGenre(String genreID); + @Query("SELECT EXISTS(SELECT * FROM song WHERE id = :id)") boolean exist(String id); 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 new file mode 100644 index 00000000..c3dd8898 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/database/dao/SongGenreCrossDao.java @@ -0,0 +1,35 @@ +package com.cappielloantonio.play.database.dao; + +import androidx.lifecycle.LiveData; +import androidx.room.Dao; +import androidx.room.Delete; +import androidx.room.Insert; +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; + +@Dao +public interface SongGenreCrossDao { + @Query("SELECT * FROM song_genre_cross") + LiveData> getAll(); + + @Query("SELECT EXISTS(SELECT * FROM song_genre_cross WHERE id = :id)") + boolean exist(String id); + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(SongGenreCross songGenreCross); + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insertAll(List songGenreCrosses); + + @Delete + void delete(SongGenreCross songGenreCross); + + @Update + void update(SongGenreCross songGenreCross); +} \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/interfaces/MediaCallback.java b/app/src/main/java/com/cappielloantonio/play/interfaces/MediaCallback.java index 67417917..0204d2d2 100644 --- a/app/src/main/java/com/cappielloantonio/play/interfaces/MediaCallback.java +++ b/app/src/main/java/com/cappielloantonio/play/interfaces/MediaCallback.java @@ -1,10 +1,9 @@ package com.cappielloantonio.play.interfaces; -import com.android.volley.VolleyError; - import java.util.List; public interface MediaCallback { void onError(Exception exception); + void onLoadMedia(List media); } \ No newline at end of file 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 57463016..9e713806 100644 --- a/app/src/main/java/com/cappielloantonio/play/model/Song.java +++ b/app/src/main/java/com/cappielloantonio/play/model/Song.java @@ -19,6 +19,21 @@ import java.util.UUID; @Entity(tableName = "song") public class Song implements Parcelable { + @Ignore + public static final String RECENTLY_PLAYED = "RECENTLY_PLAYED"; + + @Ignore + public static final String MOST_PLAYED = "MOST_PLAYED"; + + @Ignore + public static final String RECENTLY_ADDED = "RECENTLY_ADDED"; + + @Ignore + public static final String BY_GENRE = "BY_GENRE"; + + @Ignore + public static final String BY_ARTIST = "BY_ARTIST"; + @NonNull @PrimaryKey @ColumnInfo(name = "id") diff --git a/app/src/main/java/com/cappielloantonio/play/model/SongGenreCross.java b/app/src/main/java/com/cappielloantonio/play/model/SongGenreCross.java new file mode 100644 index 00000000..ff43c8b7 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/model/SongGenreCross.java @@ -0,0 +1,91 @@ +package com.cappielloantonio.play.model; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; +import androidx.room.Entity; +import androidx.room.Ignore; +import androidx.room.PrimaryKey; + +import org.jellyfin.apiclient.model.dto.BaseItemDto; +import org.jellyfin.apiclient.model.dto.MediaSourceInfo; +import org.jellyfin.apiclient.model.entities.ImageType; +import org.jellyfin.apiclient.model.entities.MediaStream; + +import java.time.Instant; +import java.util.UUID; + +@Entity(tableName = "song_genre_cross") +public class SongGenreCross implements Parcelable { + @NonNull + @PrimaryKey(autoGenerate = true) + @ColumnInfo(name = "id") + private int id; + + @ColumnInfo(name = "song_id") + private String songId; + + @ColumnInfo(name = "genre_id") + private String genreId; + + public SongGenreCross(String songId, String genreId) { + this.songId = songId; + this.genreId = genreId; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getSongId() { + return songId; + } + + public void setSongId(String songId) { + this.songId = songId; + } + + public String getGenreId() { + return genreId; + } + + public void setGenreId(String genreId) { + this.genreId = genreId; + } + + protected SongGenreCross(Parcel in) { + id = in.readInt(); + songId = in.readString(); + genreId = in.readString(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(id); + dest.writeString(songId); + dest.writeString(genreId); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator CREATOR = new Creator() { + @Override + public SongGenreCross createFromParcel(Parcel in) { + return new SongGenreCross(in); + } + + @Override + public SongGenreCross[] newArray(int size) { + return new SongGenreCross[size]; + } + }; +} 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 7eaf156b..40df3c44 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/GenreRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/GenreRepository.java @@ -6,20 +6,24 @@ 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; public class GenreRepository { private GenreDao genreDao; + private SongGenreCrossDao songGenreCrossDao; private LiveData> listLiveGenres; private LiveData> listLiveAlbumGenre; public GenreRepository(Application application) { AppDatabase database = AppDatabase.getInstance(application); genreDao = database.genreDao(); + songGenreCrossDao = database.songGenreCrossDao(); } public LiveData> getListLiveGenres() { @@ -32,6 +36,24 @@ public class GenreRepository { return listLiveAlbumGenre; } + public List getListGenre() { + List list = null; + + GetGenreListThreadSafe getGenreListThread = new GetGenreListThreadSafe(genreDao); + Thread thread = new Thread(getGenreListThread); + thread.start(); + + try { + thread.join(); + list = getGenreListThread.getList(); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + + return list; + } + public boolean exist(Genre genre) { boolean exist = false; @@ -62,12 +84,36 @@ public class GenreRepository { thread.start(); } + public void insertPerGenre(ArrayList songGenreCrosses) { + InsertPerGenreThreadSafe insertPerGenre = new InsertPerGenreThreadSafe(songGenreCrossDao, songGenreCrosses); + Thread thread = new Thread(insertPerGenre); + thread.start(); + } + public void delete(Genre genre) { DeleteThreadSafe delete = new DeleteThreadSafe(genreDao, genre); Thread thread = new Thread(delete); thread.start(); } + private static class GetGenreListThreadSafe implements Runnable { + private GenreDao genreDao; + private List list = null; + + public GetGenreListThreadSafe(GenreDao genreDao) { + this.genreDao = genreDao; + } + + @Override + public void run() { + list = genreDao.getGenreList(); + } + + public List getList() { + return list; + } + } + private static class ExistThreadSafe implements Runnable { private GenreDao genreDao; private Genre genre; @@ -118,6 +164,21 @@ public class GenreRepository { } } + 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; 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 75287189..0a5c9e0d 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java @@ -20,6 +20,7 @@ public class SongRepository { private LiveData> listLiveSampleMostPlayedSongs; private LiveData> listLiveSampleArtistTopSongs; private LiveData> listLiveAlbumSongs; + private LiveData> listLiveSongByGenre; public SongRepository(Application application) { @@ -32,26 +33,36 @@ public class SongRepository { return searchListLiveSongs; } - public LiveData> getListLiveRecentlyAddedSampleSong() { - listLiveSampleRecentlyAddedSongs = songDao.getRecentlyAddedSample(20); + public LiveData> getListLiveRecentlyAddedSampleSong(int number) { + listLiveSampleRecentlyAddedSongs = songDao.getRecentlyAddedSample(number); return listLiveSampleRecentlyAddedSongs; } - public LiveData> getListLiveRecentlyPlayedSampleSong() { - listLiveSampleRecentlyPlayedSongs = songDao.getRecentlyPlayedSample(20); + public LiveData> getListLiveRecentlyPlayedSampleSong(int number) { + listLiveSampleRecentlyPlayedSongs = songDao.getRecentlyPlayedSample(number); return listLiveSampleRecentlyPlayedSongs; } - public LiveData> getListLiveMostPlayedSampleSong() { - listLiveSampleMostPlayedSongs = songDao.getMostPlayedSample(20); + public LiveData> getListLiveMostPlayedSampleSong(int number) { + listLiveSampleMostPlayedSongs = songDao.getMostPlayedSample(number); return listLiveSampleMostPlayedSongs; } - public LiveData> getArtistListLiveTopSong(String artistID) { + public LiveData> getListLiveSongByGenre(String genreID) { + listLiveSongByGenre = songDao.getSongByGenre(genreID); + return listLiveSongByGenre; + } + + public LiveData> getArtistListLiveTopSongSample(String artistID) { listLiveSampleArtistTopSongs = songDao.getArtistTopSongsSample(artistID, 5); return listLiveSampleArtistTopSongs; } + public LiveData> getArtistListLiveTopSong(String artistID) { + listLiveSampleArtistTopSongs = songDao.getArtistTopSongs(artistID); + return listLiveSampleArtistTopSongs; + } + public LiveData> getAlbumListLiveSong(String albumID) { listLiveAlbumSongs = songDao.getAlbumSong(albumID); return listLiveAlbumSongs; diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumCatalogueFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumCatalogueFragment.java index 9f46575e..1b9ac1d5 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumCatalogueFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumCatalogueFragment.java @@ -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 -> { 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 09e45311..9fbca863 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 @@ -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() { 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 f3b844a5..999a997e 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 @@ -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 -> { diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java index 74da1a53..09da26ed 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java @@ -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() { diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java index f432cc74..1d5a9303 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java @@ -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 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) media); + } + }, genre.id); + } + + PreferenceUtil.getInstance(requireContext()).setSongGenreSync(true); + } } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java index 9b7a9907..893809f8 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java @@ -143,7 +143,7 @@ public class SearchFragment extends Fragment { bind.persistentSearchView.collapse(); bind.persistentSearchView.setInputQuery(query); - performSearch(query); + performSearch(query.trim()); } } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SongListPageFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SongListPageFragment.java new file mode 100644 index 00000000..75e8345e --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SongListPageFragment.java @@ -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)); + } +} \ No newline at end of file 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 b217d277..6d76268f 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,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 progressing; + private List 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) 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) 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) 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) 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) 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() { diff --git a/app/src/main/java/com/cappielloantonio/play/util/PreferenceUtil.java b/app/src/main/java/com/cappielloantonio/play/util/PreferenceUtil.java index c4bce9f3..6248469f 100644 --- a/app/src/main/java/com/cappielloantonio/play/util/PreferenceUtil.java +++ b/app/src/main/java/com/cappielloantonio/play/util/PreferenceUtil.java @@ -11,8 +11,10 @@ public class PreferenceUtil { public static final String SERVER = "server"; public static final String USER = "user"; public static final String TOKEN = "token"; + public static final String MUSIC_LIBRARY_ID = "music_library_id"; public static final String SYNC = "sync"; + public static final String SONG_GENRE_SYNC = "song_genre_sync"; public static final String HOST_URL = "host"; public static final String IMAGE_CACHE_SIZE = "image_cache_size"; @@ -75,6 +77,26 @@ public class PreferenceUtil { editor.apply(); } + public Boolean getSongGenreSync() { + return mPreferences.getBoolean(SONG_GENRE_SYNC, false); + } + + public void setSongGenreSync(Boolean sync) { + final SharedPreferences.Editor editor = mPreferences.edit(); + editor.putBoolean(SONG_GENRE_SYNC, sync); + editor.apply(); + } + + public String getMusicLibraryID() { + return mPreferences.getString(MUSIC_LIBRARY_ID, ""); + } + + public void setMusicLibraryID(String musicLibraryID) { + final SharedPreferences.Editor editor = mPreferences.edit(); + editor.putString(MUSIC_LIBRARY_ID, musicLibraryID); + editor.apply(); + } + public final String getHostUrl() { return mPreferences.getString(HOST_URL, "undefined"); } 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 9f0b1d98..67d520c4 100644 --- a/app/src/main/java/com/cappielloantonio/play/util/SyncUtil.java +++ b/app/src/main/java/com/cappielloantonio/play/util/SyncUtil.java @@ -9,6 +9,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 org.jellyfin.apiclient.interaction.Response; import org.jellyfin.apiclient.model.dto.BaseItemDto; @@ -23,8 +24,6 @@ import java.util.Arrays; import java.util.List; public class SyncUtil { - public static BaseItemDto musicLibrary; - public static void getLibraries(Context context, MediaCallback callback) { String id = App.getApiClientInstance(context).getCurrentUserId(); @@ -51,7 +50,7 @@ public class SyncUtil { query.setFields(new ItemFields[]{ItemFields.MediaSources}); query.setUserId(App.getApiClientInstance(context).getCurrentUserId()); query.setRecursive(true); - query.setParentId(musicLibrary.getId()); + query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID()); App.getApiClientInstance(context).GetItemsAsync(query, new Response() { @Override @@ -78,7 +77,7 @@ public class SyncUtil { query.setIncludeItemTypes(new String[]{"MusicAlbum"}); query.setUserId(App.getApiClientInstance(context).getCurrentUserId()); query.setRecursive(true); - query.setParentId(musicLibrary.getId()); + query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID()); App.getApiClientInstance(context).GetItemsAsync(query, new Response() { @Override @@ -104,7 +103,7 @@ public class SyncUtil { query.setFields(new ItemFields[]{ItemFields.Genres}); query.setUserId(App.getApiClientInstance(context).getCurrentUserId()); query.setRecursive(true); - query.setParentId(musicLibrary.getId()); + query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID()); App.getApiClientInstance(context).GetAlbumArtistsAsync(query, new Response() { @Override @@ -130,7 +129,7 @@ public class SyncUtil { query.setIncludeItemTypes(new String[]{"Playlist"}); query.setUserId(App.getApiClientInstance(context).getCurrentUserId()); query.setRecursive(true); - query.setParentId(musicLibrary.getId()); + query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID()); App.getApiClientInstance(context).GetItemsAsync(query, new Response() { @Override @@ -155,7 +154,7 @@ public class SyncUtil { query.setUserId(App.getApiClientInstance(context).getCurrentUserId()); query.setRecursive(true); - query.setParentId(musicLibrary.getId()); + query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID()); App.getApiClientInstance(context).GetGenresAsync(query, new Response() { @Override @@ -174,4 +173,33 @@ public class SyncUtil { } }); } + + public static void getSongsPerGenre(Context context, MediaCallback callback, String genreId) { + ItemQuery query = new ItemQuery(); + + query.setIncludeItemTypes(new String[]{"Audio"}); + query.setFields(new ItemFields[]{ItemFields.MediaSources}); + query.setUserId(App.getApiClientInstance(context).getCurrentUserId()); + query.setRecursive(true); + query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID()); + query.setGenreIds(new String[]{genreId}); + + App.getApiClientInstance(context).GetItemsAsync(query, new Response() { + @Override + public void onResponse(ItemsResult result) { + ArrayList crosses = new ArrayList<>(); + + for (BaseItemDto itemDto : result.getItems()) { + crosses.add(new SongGenreCross(itemDto.getId(), genreId)); + } + + callback.onLoadMedia(crosses); + } + + @Override + public void onError(Exception exception) { + callback.onError(exception); + } + }); + } } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistPageViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistPageViewModel.java index a04de724..9836150b 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistPageViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistPageViewModel.java @@ -36,7 +36,7 @@ public class ArtistPageViewModel extends AndroidViewModel { } public LiveData> getArtistTopSongList() { - songList = songRepository.getArtistListLiveTopSong(artist.id); + songList = songRepository.getArtistListLiveTopSongSample(artist.id); return songList; } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/GenreCatalogueViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/GenreCatalogueViewModel.java index a8c1e9c8..8f663d83 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/GenreCatalogueViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/GenreCatalogueViewModel.java @@ -28,4 +28,8 @@ public class GenreCatalogueViewModel extends AndroidViewModel { genreList = genreRepository.getListLiveGenres(); return genreList; } + + public List getGenres() { + return genreRepository.getListGenre(); + } } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java index e03ac4c0..658e7920 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java @@ -26,13 +26,17 @@ public class HomeViewModel extends AndroidViewModel { songRepository = new SongRepository(application); dicoverSongSample = songRepository.getRandomSample(5); - recentlyPlayedSongSample = songRepository.getListLiveRecentlyPlayedSampleSong(); - recentlyAddedSongSample = songRepository.getListLiveRecentlyAddedSampleSong(); - mostPlayedSongSample = songRepository.getListLiveMostPlayedSampleSong(); + recentlyPlayedSongSample = songRepository.getListLiveRecentlyPlayedSampleSong(20); + recentlyAddedSongSample = songRepository.getListLiveRecentlyAddedSampleSong(20); + mostPlayedSongSample = songRepository.getListLiveMostPlayedSampleSong(20); } public List getDiscoverSongList() { + if(dicoverSongSample.isEmpty()) { + dicoverSongSample = songRepository.getRandomSample(5); + } + return dicoverSongSample; } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/LibraryViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/LibraryViewModel.java index da6383b5..e0332b0d 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/LibraryViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/LibraryViewModel.java @@ -46,16 +46,15 @@ public class LibraryViewModel extends AndroidViewModel { sampleGenres = genreRepository.getListLiveSampleGenre(); } - public LiveData> getGenreList() { - allGenres = genreRepository.getListLiveGenres(); - return allGenres; - } - public LiveData> getPlaylistList() { allPlaylist = playlistRepository.getListLivePlaylists(); return allPlaylist; } + public List getGenreList() { + return genreRepository.getListGenre(); + } + public LiveData> getAlbumSample() { return sampleAlbum; } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/SongListPageViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/SongListPageViewModel.java new file mode 100644 index 00000000..907423aa --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/SongListPageViewModel.java @@ -0,0 +1,52 @@ +package com.cappielloantonio.play.viewmodel; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; + +import com.cappielloantonio.play.model.Artist; +import com.cappielloantonio.play.model.Genre; +import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.repository.SongRepository; + +import java.util.List; + +public class SongListPageViewModel extends AndroidViewModel { + private SongRepository songRepository; + + private LiveData> songList; + + public String title; + public Genre genre; + public Artist artist; + + public SongListPageViewModel(@NonNull Application application) { + super(application); + + songRepository = new SongRepository(application); + } + + public LiveData> getSongList() { + switch (title) { + case Song.RECENTLY_PLAYED: + songList = songRepository.getListLiveRecentlyPlayedSampleSong(100); + break; + case Song.MOST_PLAYED: + songList = songRepository.getListLiveMostPlayedSampleSong(100); + break; + case Song.RECENTLY_ADDED: + songList = songRepository.getListLiveRecentlyAddedSampleSong(100); + break; + case Song.BY_GENRE: + songList = songRepository.getListLiveSongByGenre(genre.getId()); + break; + case Song.BY_ARTIST: + songList = songRepository.getArtistListLiveTopSong(artist.getId()); + break; + } + + return songList; + } +} diff --git a/app/src/main/res/layout/fragment_artist_page.xml b/app/src/main/res/layout/fragment_artist_page.xml index 3a999399..79b205d7 100644 --- a/app/src/main/res/layout/fragment_artist_page.xml +++ b/app/src/main/res/layout/fragment_artist_page.xml @@ -72,7 +72,7 @@ + + + + + + + + + + + + @@ -73,6 +85,7 @@ - - - - + + + + + + + + + + + + + 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 cc1d7b3f..0a2cc39f 100644 --- a/app/src/main/res/layout/item_home_discover_song.xml +++ b/app/src/main/res/layout/item_home_discover_song.xml @@ -22,7 +22,7 @@ android:textSize="20sp" /> + app:destination="@id/syncFragment" /> + + + tools:layout="@layout/fragment_genre_catalogue"> + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0b6ac8e5..23f8ec3b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,7 +7,7 @@ Settings General - Search title, artists or albums + Search Home Settings Download