diff --git a/app/build.gradle b/app/build.gradle index 847cef5b..c0c15a65 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -36,27 +36,40 @@ android { dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) - implementation 'androidx.core:core-ktx:1.3.2' + // Jellyfin + implementation 'com.github.jellyfin.jellyfin-apiclient-java:android:0.7.7' + + // Kotlin implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.4.10' + // AndroidX + implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0" - implementation 'pub.devrel:easypermissions:3.0.0' implementation 'androidx.preference:preference-ktx:1.1.1' - implementation 'com.android.volley:volley:1.1.1' - implementation "com.paulrybitskyi.persistentsearchview:persistentsearchview:1.1.3" - implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1' implementation 'androidx.navigation:navigation-ui-ktx:2.3.1' implementation 'androidx.recyclerview:recyclerview:1.1.0' - implementation 'com.github.bumptech.glide:glide:4.11.0' implementation "androidx.room:room-runtime:2.2.5" - implementation 'com.github.jellyfin.jellyfin-apiclient-java:android:0.7.7' implementation "androidx.cardview:cardview:1.0.0" - - implementation 'org.apache.commons:commons-lang3:3.11' implementation 'androidx.legacy:legacy-support-v4:1.0.0' + + // Android Material + implementation 'com.google.android.material:material:1.2.1' + + // VolleyRequest + implementation 'com.android.volley:volley:1.1.1' + + // SearchBar + implementation "com.paulrybitskyi.persistentsearchview:persistentsearchview:1.1.3" + + // Permission + implementation 'pub.devrel:easypermissions:3.0.0' + + // Glide + implementation 'com.github.bumptech.glide:glide:4.11.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' annotationProcessor "androidx.room:room-compiler:2.2.5" testImplementation 'junit:junit:4.13.1' diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/AlbumArtistPageAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/AlbumArtistPageAdapter.java new file mode 100644 index 00000000..01b3f372 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/adapter/AlbumArtistPageAdapter.java @@ -0,0 +1,76 @@ +package com.cappielloantonio.play.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.cappielloantonio.play.R; +import com.cappielloantonio.play.model.Album; + +import java.util.List; + +public class AlbumArtistPageAdapter extends RecyclerView.Adapter { + private static final String TAG = "RecentMusicAdapter"; + private List albums; + private LayoutInflater mInflater; + private Context context; + private ItemClickListener itemClickListener; + + public AlbumArtistPageAdapter(Context context, List albums) { + this.context = context; + this.mInflater = LayoutInflater.from(context); + this.albums = albums; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = mInflater.inflate(R.layout.item_artist_page_album, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + Album album = albums.get(position); + + holder.textAlbumName.setText(album.getTitle()); + } + + @Override + public int getItemCount() { + return albums.size(); + } + + public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView textAlbumName; + + ViewHolder(View itemView) { + super(itemView); + + textAlbumName = itemView.findViewById(R.id.album_name_label); + + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + if (itemClickListener != null) itemClickListener.onItemClick(view, getAdapterPosition()); + } + } + + public void setItems(List albums) { + this.albums = albums; + notifyDataSetChanged(); + } + + public void setClickListener(ItemClickListener itemClickListener) { + this.itemClickListener = itemClickListener; + } + + public interface ItemClickListener { + void onItemClick(View view, int position); + } +} diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/ArtistCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/ArtistCatalogueAdapter.java index a13d6279..6fbd6b5b 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/ArtistCatalogueAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/ArtistCatalogueAdapter.java @@ -61,6 +61,10 @@ public class ArtistCatalogueAdapter extends RecyclerView.Adapter artists) { this.artists = artists; notifyDataSetChanged(); 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 5e1540ea..32683664 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/DiscoverSongAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/DiscoverSongAdapter.java @@ -1,6 +1,7 @@ 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; @@ -10,21 +11,26 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.viewpager.widget.PagerAdapter; +import com.cappielloantonio.play.App; import com.cappielloantonio.play.R; -import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.repository.SongRepository; import java.util.List; public class DiscoverSongAdapter extends PagerAdapter { + private static final String TAG = "DiscoverSongAdapter"; private List songs; private LayoutInflater layoutInflater; private Context context; + private View view; - public DiscoverSongAdapter(Context context, List models) { + public DiscoverSongAdapter(Context context, List songs) { this.context = context; - this.songs = models; + this.songs = songs; + + Log.d(TAG, "DiscoverSongAdapter: " + songs.toString()); } @Override @@ -41,30 +47,31 @@ public class DiscoverSongAdapter extends PagerAdapter { @Override public Object instantiateItem(@NonNull ViewGroup container, final int position) { layoutInflater = LayoutInflater.from(context); - View view = layoutInflater.inflate(R.layout.item_home_discover_song, container, false); - - TextView title; - TextView desc; - - title = view.findViewById(R.id.title_discover_song_label); - desc = view.findViewById(R.id.artist_discover_song_label); + 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); title.setText(songs.get(position).getTitle()); desc.setText(songs.get(position).getAlbumName()); - view.setOnClickListener(v -> Toast.makeText(context, songs.get(position).getTitle(), Toast.LENGTH_SHORT).show()); + view.setOnClickListener(v -> { + SongRepository songRepository = new SongRepository(App.getInstance()); + songRepository.update(songs.get(position)); + }); container.addView(view, 0); return view; } public void setItems(List songs) { + Log.d(TAG, "setItems: CHANGING"); + this.songs = songs; notifyDataSetChanged(); } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { - container.removeView((View)object); + container.removeView((View) object); } } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/RecentMusicAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/RecentMusicAdapter.java index e3a82141..96edf380 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/RecentMusicAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/RecentMusicAdapter.java @@ -8,9 +8,11 @@ import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; +import com.cappielloantonio.play.App; import com.cappielloantonio.play.R; import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.repository.SongRepository; import com.cappielloantonio.play.util.Util; import java.util.List; @@ -23,7 +25,6 @@ public class RecentMusicAdapter extends RecyclerView.Adapter songs; private LayoutInflater mInflater; private Context context; - private ItemClickListener itemClickListener; public RecentMusicAdapter(Context context, List songs) { this.context = context; @@ -65,7 +66,8 @@ public class RecentMusicAdapter extends RecyclerView.Adapter songs; private LayoutInflater mInflater; private Context context; - private ItemClickListener itemClickListener; public SongResultSearchAdapter(Context context, List songs) { this.context = context; @@ -67,8 +68,8 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter> getAll(); + @Query("SELECT * FROM album WHERE artistId = :artistId;") + LiveData> getArtistAlbums(String artistId); + @Query("SELECT * FROM album ORDER BY RANDOM() LIMIT :number;") LiveData> getSample(int number); + @Query("SELECT * FROM album WHERE title LIKE '%' || :name || '%'") + LiveData> searchAlbum(String name); + @Query("SELECT EXISTS(SELECT * FROM album WHERE id = :id)") boolean exist(String id); 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 ffb96e11..44bc669f 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 @@ -7,7 +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 java.util.List; @@ -20,6 +19,9 @@ public interface ArtistDao { @Query("SELECT * FROM artist ORDER BY RANDOM() LIMIT :number;") LiveData> getSample(int number); + @Query("SELECT * FROM artist WHERE name LIKE '%' || :name || '%'") + LiveData> searchArtist(String name); + @Query("SELECT EXISTS(SELECT * FROM artist WHERE id = :id)") boolean exist(String id); 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 66075692..be90252e 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 @@ -6,6 +6,7 @@ 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; @@ -22,15 +23,18 @@ public interface SongDao { @Query("SELECT * FROM song ORDER BY RANDOM() LIMIT :number") LiveData> getDiscoverSample(int number); - @Query("SELECT * FROM song ORDER BY RANDOM() LIMIT :number") + @Query("SELECT * FROM song ORDER BY added DESC LIMIT :number") LiveData> getRecentlyAddedSample(int number); - @Query("SELECT * FROM song ORDER BY RANDOM() LIMIT :number") + @Query("SELECT * FROM song WHERE last_play != 0 ORDER BY last_play DESC LIMIT :number") LiveData> getRecentlyPlayedSample(int number); - @Query("SELECT * FROM song ORDER BY RANDOM() LIMIT :number") + @Query("SELECT * FROM song WHERE play_count != 0 ORDER BY play_count DESC LIMIT :number") LiveData> getMostPlayedSample(int number); + @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 EXISTS(SELECT * FROM song WHERE id = :id)") boolean exist(String id); @@ -42,4 +46,10 @@ public interface SongDao { @Delete void delete(Song song); + + @Update + public void update(Song song); + + @Query("SELECT * FROM song ORDER BY RANDOM() LIMIT :number") + List random(int number); } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/helper/recyclerview/ItemlDecoration.java b/app/src/main/java/com/cappielloantonio/play/helper/recyclerview/ItemlDecoration.java new file mode 100644 index 00000000..a0d61672 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/helper/recyclerview/ItemlDecoration.java @@ -0,0 +1,40 @@ +package com.cappielloantonio.play.helper.recyclerview; + +import android.graphics.Rect; +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +public class ItemlDecoration extends RecyclerView.ItemDecoration { + private int spanCount; + private int spacing; + private boolean includeEdge; + + public ItemlDecoration(int spanCount, int spacing, boolean includeEdge) { + this.spanCount = spanCount; + this.spacing = spacing; + this.includeEdge = includeEdge; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + int position = parent.getChildAdapterPosition(view); // item position + int column = position % spanCount; // item column + + if (includeEdge) { + outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing) + outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing) + + if (position < spanCount) { // top edge + outRect.top = spacing; + } + outRect.bottom = spacing; // item bottom + } else { + outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing) + outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing) + if (position >= spanCount) { + outRect.top = spacing; // item top + } + } + } +} diff --git a/app/src/main/java/com/cappielloantonio/play/model/Artist.java b/app/src/main/java/com/cappielloantonio/play/model/Artist.java index 7c318c32..2b363a5d 100644 --- a/app/src/main/java/com/cappielloantonio/play/model/Artist.java +++ b/app/src/main/java/com/cappielloantonio/play/model/Artist.java @@ -36,14 +36,22 @@ public class Artist implements Parcelable { @ColumnInfo(name = "primary") public String primary; - @ColumnInfo(name = "blurHash") - public String blurHash; + @ColumnInfo(name = "primary_blurHash") + public String primaryBlurHash; - public Artist(@NonNull String id, String name, String primary, String blurHash) { + @ColumnInfo(name = "backdrop") + public String backdrop; + + @ColumnInfo(name = "backdrop_blurHash") + public String backdropBlurHash; + + public Artist(@NonNull String id, String name, String primary, String primaryBlurHash, String backdrop, String backdropBlurHash) { this.id = id; this.name = name; this.primary = primary; - this.blurHash = blurHash; + this.primaryBlurHash = primaryBlurHash; + this.backdrop = backdrop; + this.backdropBlurHash = backdropBlurHash; } @Ignore @@ -51,11 +59,23 @@ public class Artist implements Parcelable { this.id = itemDto.getId(); this.name = itemDto.getName(); - this.primary = itemDto.getImageTags().containsKey(ImageType.Primary) ? id : null; + this.primary = itemDto.getImageTags().getOrDefault(ImageType.Primary, null); if (itemDto.getImageBlurHashes() != null && itemDto.getImageBlurHashes().get(ImageType.Primary) != null) { - this.blurHash = (String) itemDto.getImageBlurHashes().get(ImageType.Primary).values().toArray()[0]; + this.primaryBlurHash = (String) itemDto.getImageBlurHashes().get(ImageType.Primary).values().toArray()[0]; } + try { + this.backdrop = itemDto.getBackdropImageTags().get(0); + if (itemDto.getImageBlurHashes() != null && itemDto.getBackdropImageTags().get(0) != null) { + this.backdropBlurHash = (String) itemDto.getImageBlurHashes().get(ImageType.Backdrop).values().toArray()[0]; + } + } + catch (IndexOutOfBoundsException exception) { + this.backdrop = null; + this.backdropBlurHash = null; + } + + this.genres = new ArrayList<>(); this.albums = new ArrayList<>(); this.songs = new ArrayList<>(); @@ -92,12 +112,28 @@ public class Artist implements Parcelable { this.primary = primary; } - public String getBlurHash() { - return blurHash; + public String getPrimaryBlurHash() { + return primaryBlurHash; } - public void setBlurHash(String blurHash) { - this.blurHash = blurHash; + public void setPrimaryBlurHash(String primaryBlurHash) { + this.primaryBlurHash = primaryBlurHash; + } + + public String getBackdrop() { + return backdrop; + } + + public void setBackdrop(String backdrop) { + this.backdrop = backdrop; + } + + public String getBackdropBlurHash() { + return backdropBlurHash; + } + + public void setBackdropBlurHash(String backdropBlurHash) { + this.backdropBlurHash = backdropBlurHash; } @Override @@ -130,7 +166,9 @@ public class Artist implements Parcelable { dest.writeString(id); dest.writeString(name); dest.writeString(primary); - dest.writeString(blurHash); + dest.writeString(primaryBlurHash); + dest.writeString(backdrop); + dest.writeString(backdropBlurHash); } protected Artist(Parcel in) { @@ -140,7 +178,9 @@ public class Artist implements Parcelable { this.id = in.readString(); this.name = in.readString(); this.primary = in.readString(); - this.blurHash = in.readString(); + this.primaryBlurHash = in.readString(); + this.backdrop = in.readString(); + this.backdropBlurHash = in.readString(); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 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 94f04380..57463016 100644 --- a/app/src/main/java/com/cappielloantonio/play/model/Song.java +++ b/app/src/main/java/com/cappielloantonio/play/model/Song.java @@ -14,6 +14,7 @@ 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") @@ -83,7 +84,16 @@ public class Song implements Parcelable { @ColumnInfo(name = "channels") private int channels; - public Song(@NonNull String id, String title, int trackNumber, int discNumber, int year, long duration, String albumId, String albumName, String artistId, String artistName, String primary, String blurHash, boolean favorite, String path, long size, String container, String codec, int sampleRate, int bitRate, int bitDepth, int channels) { + @ColumnInfo(name = "added") + private long added; + + @ColumnInfo(name = "play_count") + private int playCount; + + @ColumnInfo(name = "last_play") + private long lastPlay; + + public Song(@NonNull String id, String title, int trackNumber, int discNumber, int year, long duration, String albumId, String albumName, String artistId, String artistName, String primary, String blurHash, boolean favorite, String path, long size, String container, String codec, int sampleRate, int bitRate, int bitDepth, int channels, long added, int playCount, long lastPlay) { this.id = id; this.title = title; this.trackNumber = trackNumber; @@ -105,6 +115,9 @@ public class Song implements Parcelable { this.bitRate = bitRate; this.bitDepth = bitDepth; this.channels = channels; + this.added = added; + this.playCount = playCount; + this.lastPlay = lastPlay; } @Ignore @@ -152,6 +165,10 @@ public class Song implements Parcelable { this.channels = stream.getChannels() != null ? stream.getChannels() : 0; } } + + this.added = Instant.now().toEpochMilli(); + this.playCount = 0; + this.lastPlay = 0; } @Ignore @@ -246,6 +263,18 @@ public class Song implements Parcelable { return channels; } + public long getAdded() { + return added; + } + + public int getPlayCount() { + return playCount; + } + + public long getLastPlay() { + return lastPlay; + } + public void setId(@NonNull String id) { this.id = id; } @@ -330,6 +359,23 @@ public class Song implements Parcelable { this.channels = channels; } + public void setAdded(long added) { + this.added = added; + } + + public void setAdded(int playCount) { + this.playCount = playCount; + } + + public void setLastPlay(long lastPlay) { + this.lastPlay = lastPlay; + } + + public void nowPlaying() { + this.playCount++; + this.lastPlay = Instant.now().toEpochMilli(); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -377,6 +423,9 @@ public class Song implements Parcelable { dest.writeInt(this.bitRate); dest.writeInt(this.bitDepth); dest.writeInt(this.channels); + dest.writeLong(this.added); + dest.writeInt(this.playCount); + dest.writeLong(this.lastPlay); } protected Song(Parcel in) { @@ -401,6 +450,9 @@ public class Song implements Parcelable { this.bitRate = in.readInt(); this.bitDepth = in.readInt(); this.channels = in.readInt(); + this.added = in.readLong(); + this.playCount = in.readInt(); + this.lastPlay = in.readLong(); } public static final Creator CREATOR = new Creator() { 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 c916510e..94c9106d 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/AlbumRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/AlbumRepository.java @@ -7,6 +7,8 @@ import androidx.lifecycle.LiveData; import com.cappielloantonio.play.database.AppDatabase; import com.cappielloantonio.play.database.dao.AlbumDao; 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.List; @@ -14,7 +16,10 @@ import java.util.List; public class AlbumRepository { private AlbumDao albumDao; private LiveData> listLiveAlbums; + private LiveData> artistListLiveAlbums; private LiveData> listLiveSampleAlbum; + private LiveData> searchListLiveAlbum; + public AlbumRepository(Application application) { AppDatabase database = AppDatabase.getInstance(application); @@ -26,11 +31,21 @@ public class AlbumRepository { return listLiveAlbums; } + public LiveData> getArtistListLiveAlbums(String artistId) { + artistListLiveAlbums = albumDao.getArtistAlbums(artistId); + return artistListLiveAlbums; + } + public LiveData> getListLiveSampleAlbum() { listLiveSampleAlbum = albumDao.getSample(10); return listLiveSampleAlbum; } + public LiveData> searchListLiveAlbum(String name) { + searchListLiveAlbum = albumDao.searchAlbum(name); + return searchListLiveAlbum; + } + public boolean exist(Album album) { boolean exist = false; 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 41bc5c59..60aec4ec 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/ArtistRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/ArtistRepository.java @@ -8,6 +8,7 @@ import com.cappielloantonio.play.database.AppDatabase; 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.List; @@ -16,6 +17,8 @@ public class ArtistRepository { private ArtistDao artistDao; private LiveData> listLiveArtists; private LiveData> listLiveSampleArtist; + private LiveData> searchListLiveArtist; + public ArtistRepository(Application application) { AppDatabase database = AppDatabase.getInstance(application); @@ -32,6 +35,11 @@ public class ArtistRepository { return listLiveSampleArtist; } + public LiveData> searchListLiveArtist(String name) { + searchListLiveArtist = artistDao.searchArtist(name); + return searchListLiveArtist; + } + public boolean exist(Artist artist) { boolean exist = false; 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 4181120c..ba8d6602 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/SongRepository.java @@ -14,12 +14,11 @@ import java.util.List; public class SongRepository { private SongDao songDao; - private LiveData> listLiveSongs; private LiveData> searchListLiveSongs; - private LiveData> listLiveSampleDiscoverSongs; private LiveData> listLiveSampleRecentlyAddedSongs; private LiveData> listLiveSampleRecentlyPlayedSongs; private LiveData> listLiveSampleMostPlayedSongs; + private LiveData> listLiveSampleArtistTopSongs; public SongRepository(Application application) { @@ -32,11 +31,6 @@ public class SongRepository { return searchListLiveSongs; } - public LiveData> getListLiveDiscoverSampleSong() { - listLiveSampleDiscoverSongs = songDao.getDiscoverSample(5); - return listLiveSampleDiscoverSongs; - } - public LiveData> getListLiveRecentlyAddedSampleSong() { listLiveSampleRecentlyAddedSongs = songDao.getRecentlyAddedSample(20); return listLiveSampleRecentlyAddedSongs; @@ -52,6 +46,11 @@ public class SongRepository { return listLiveSampleMostPlayedSongs; } + public LiveData> getArtistListLiveTopSong(String artistID) { + listLiveSampleArtistTopSongs = songDao.getArtistTopSongsSample(artistID, 5); + return listLiveSampleArtistTopSongs; + } + public boolean exist(Song song) { boolean exist = false; @@ -87,6 +86,31 @@ public class SongRepository { thread.start(); } + public void update(Song song) { + song.nowPlaying(); + + UpdateThreadSafe update = new UpdateThreadSafe(songDao, song); + Thread thread = new Thread(update); + thread.start(); + } + + public List getRandomSample(int number) { + List sample = new ArrayList<>(); + + PickRandomThreadSafe randomThread = new PickRandomThreadSafe(songDao, number); + Thread thread = new Thread(randomThread); + thread.start(); + + try { + thread.join(); + sample = randomThread.getSample(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + return sample; + } + private static class ExistThreadSafe implements Runnable { private SongDao songDao; private Song song; @@ -151,4 +175,39 @@ public class SongRepository { songDao.delete(song); } } + + private static class UpdateThreadSafe implements Runnable { + private SongDao songDao; + private Song song; + + public UpdateThreadSafe(SongDao songDao, Song song) { + this.songDao = songDao; + this.song = song; + } + + @Override + public void run() { + songDao.update(song); + } + } + + private static class PickRandomThreadSafe implements Runnable { + private SongDao songDao; + private int elementNumber; + private List sample; + + public PickRandomThreadSafe(SongDao songDao, int number) { + this.songDao = songDao; + this.elementNumber = number; + } + + @Override + public void run() { + sample = songDao.random(elementNumber); + } + + public List getSample() { + return sample; + } + } } 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 4e200479..7d9a0457 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 @@ -11,11 +11,9 @@ import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.GridLayoutManager; import com.cappielloantonio.play.adapter.AlbumCatalogueAdapter; -import com.cappielloantonio.play.adapter.ArtistCatalogueAdapter; import com.cappielloantonio.play.databinding.FragmentAlbumCatalogueBinding; -import com.cappielloantonio.play.databinding.FragmentArtistCatalogueBinding; +import com.cappielloantonio.play.helper.recyclerview.ItemlDecoration; import com.cappielloantonio.play.viewmodel.AlbumCatalogueViewModel; -import com.cappielloantonio.play.viewmodel.ArtistCatalogueViewModel; import java.util.ArrayList; @@ -46,6 +44,7 @@ public class AlbumCatalogueFragment extends Fragment { private void initAlbumCatalogueView() { bind.albumCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2)); + bind.albumCatalogueRecyclerView.addItemDecoration(new ItemlDecoration(2, 20, false)); bind.albumCatalogueRecyclerView.setHasFixedSize(true); albumAdapter = new AlbumCatalogueAdapter(requireContext(), new ArrayList<>()); diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistCatalogueFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistCatalogueFragment.java index fc0fe413..31a71289 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistCatalogueFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistCatalogueFragment.java @@ -17,6 +17,7 @@ import com.cappielloantonio.play.adapter.ArtistAdapter; import com.cappielloantonio.play.adapter.ArtistCatalogueAdapter; import com.cappielloantonio.play.adapter.RecentMusicAdapter; import com.cappielloantonio.play.databinding.FragmentArtistCatalogueBinding; +import com.cappielloantonio.play.helper.recyclerview.ItemlDecoration; import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.ui.activities.MainActivity; import com.cappielloantonio.play.viewmodel.ArtistCatalogueViewModel; @@ -51,6 +52,7 @@ public class ArtistCatalogueFragment extends Fragment { private void initArtistCatalogueView() { bind.artistCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2)); + bind.artistCatalogueRecyclerView.addItemDecoration(new ItemlDecoration(2, 20, false)); bind.artistCatalogueRecyclerView.setHasFixedSize(true); artistAdapter = new ArtistCatalogueAdapter(requireContext(), new ArrayList<>()); 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 new file mode 100644 index 00000000..c9e3ff95 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistPageFragment.java @@ -0,0 +1,78 @@ +package com.cappielloantonio.play.ui.fragment; + +import android.os.Bundle; + +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.cappielloantonio.play.R; +import com.cappielloantonio.play.adapter.AlbumArtistPageAdapter; +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.ui.activities.MainActivity; +import com.cappielloantonio.play.viewmodel.ArtistPageViewModel; +import com.cappielloantonio.play.viewmodel.HomeViewModel; + +import java.util.ArrayList; + +public class ArtistPageFragment extends Fragment { + + private FragmentArtistPageBinding bind; + private MainActivity activity; + private ArtistPageViewModel artistPageViewModel; + + private SongResultSearchAdapter songResultSearchAdapter; + private AlbumArtistPageAdapter albumArtistPageAdapter; + + private String artistID; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + activity = (MainActivity) getActivity(); + + bind = FragmentArtistPageBinding.inflate(inflater, container, false); + View view = bind.getRoot(); + artistPageViewModel = new ViewModelProvider(requireActivity()).get(ArtistPageViewModel.class); + + init(); + initTopSongsView(); + initAlbumsView(); + + return view; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + bind = null; + } + + private void init() { + artistID = getArguments().getString("artistID"); + } + + private void initTopSongsView() { + bind.mostStreamedSongRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); + bind.mostStreamedSongRecyclerView.setHasFixedSize(true); + + songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), new ArrayList<>()); + bind.mostStreamedSongRecyclerView.setAdapter(songResultSearchAdapter); + artistPageViewModel.getArtistTopSongList(artistID).observe(requireActivity(), songs -> songResultSearchAdapter.setItems(songs)); + } + + private void initAlbumsView() { + bind.albumsRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)); + bind.albumsRecyclerView.setHasFixedSize(true); + + albumArtistPageAdapter = new AlbumArtistPageAdapter(requireContext(), new ArrayList<>()); + bind.albumsRecyclerView.setAdapter(albumArtistPageAdapter); + artistPageViewModel.getAlbumList(artistID).observe(requireActivity(), songs -> albumArtistPageAdapter.setItems(songs)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/FilterFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/FilterFragment.java index 83dc79da..e92288ca 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/FilterFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/FilterFragment.java @@ -44,6 +44,7 @@ public class FilterFragment extends Fragment { private void setFilterChips() { filterViewModel.getGenreList().observe(requireActivity(), genres -> { bind.loadingProgressBar.setVisibility(View.GONE); + bind.filterContainer.setVisibility(View.VISIBLE); for (Genre genre : genres) { Chip mChip = (Chip) requireActivity().getLayoutInflater().inflate(R.layout.chip_search_filter_genre, null, false); mChip.setText(genre.getName()); 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 5a4e9e5e..f3b844a5 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 @@ -15,6 +15,7 @@ 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.viewmodel.ArtistCatalogueViewModel; import com.cappielloantonio.play.viewmodel.GenreCatalogueViewModel; @@ -47,11 +48,13 @@ public class GenreCatalogueFragment extends Fragment { private void initArtistCatalogueView() { bind.genreCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2)); + bind.genreCatalogueRecyclerView.addItemDecoration(new ItemlDecoration(2, 20, false)); bind.genreCatalogueRecyclerView.setHasFixedSize(true); genreCatalogueAdapter = new GenreCatalogueAdapter(requireContext(), new ArrayList<>()); genreCatalogueAdapter.setClickListener((view, position) -> Toast.makeText(requireContext(), "Click: " + position, Toast.LENGTH_SHORT).show()); bind.genreCatalogueRecyclerView.setAdapter(genreCatalogueAdapter); + genreCatalogueViewModel.getGenreList().observe(requireActivity(), genres -> { bind.loadingProgressBar.setVisibility(View.GONE); bind.genreCatalogueContainer.setVisibility(View.VISIBLE); 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 84b78f36..74da1a53 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 @@ -9,22 +9,19 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; 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; import java.util.ArrayList; -import java.util.List; -public class HomeFragment extends Fragment implements RecentMusicAdapter.ItemClickListener { +public class HomeFragment extends Fragment { private static final String TAG = "CategoriesFragment"; private FragmentHomeBinding bind; @@ -33,6 +30,7 @@ public class HomeFragment extends Fragment implements RecentMusicAdapter.ItemCli private DiscoverSongAdapter discoverSongAdapter; private RecentMusicAdapter recentlyAddedMusicAdapter; + private RecentMusicAdapter recentlyPlayedMusicAdapter; private RecentMusicAdapter mostPlayedMusicAdapter; @Nullable @@ -46,6 +44,7 @@ public class HomeFragment extends Fragment implements RecentMusicAdapter.ItemCli init(); initDiscoverSongSlideView(); + initRecentAddedSongView(); initRecentPlayedSongView(); initMostPlayedSongView(); @@ -66,20 +65,27 @@ public class HomeFragment extends Fragment implements RecentMusicAdapter.ItemCli } private void initDiscoverSongSlideView() { - discoverSongAdapter = new DiscoverSongAdapter(requireContext(), new ArrayList<>()); + discoverSongAdapter = new DiscoverSongAdapter(requireContext(), homeViewModel.getDiscoverSongList()); bind.discoverSongViewPager.setAdapter(discoverSongAdapter); bind.discoverSongViewPager.setPageMargin(20); - homeViewModel.getDiscoverSongList().observe(requireActivity(), songs -> discoverSongAdapter.setItems(songs)); + } + + private void initRecentAddedSongView() { + bind.recentlyAddedTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)); + bind.recentlyAddedTracksRecyclerView.setHasFixedSize(true); + + recentlyAddedMusicAdapter = new RecentMusicAdapter(requireContext(), new ArrayList<>()); + bind.recentlyAddedTracksRecyclerView.setAdapter(recentlyAddedMusicAdapter); + homeViewModel.getRecentlyAddedSongList().observe(requireActivity(), songs -> recentlyAddedMusicAdapter.setItems(songs)); } private void initRecentPlayedSongView() { bind.recentlyPlayedTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)); bind.recentlyPlayedTracksRecyclerView.setHasFixedSize(true); - recentlyAddedMusicAdapter = new RecentMusicAdapter(requireContext(), new ArrayList<>()); - recentlyAddedMusicAdapter.setClickListener(this); - bind.recentlyPlayedTracksRecyclerView.setAdapter(recentlyAddedMusicAdapter); - homeViewModel.getRecentlyAddedSongList().observe(requireActivity(), songs -> recentlyAddedMusicAdapter.setItems(songs)); + recentlyPlayedMusicAdapter = new RecentMusicAdapter(requireContext(), new ArrayList<>()); + bind.recentlyPlayedTracksRecyclerView.setAdapter(recentlyPlayedMusicAdapter); + homeViewModel.getRecentlyPlayedSongList().observe(requireActivity(), songs -> recentlyPlayedMusicAdapter.setItems(songs)); } private void initMostPlayedSongView() { @@ -87,13 +93,7 @@ public class HomeFragment extends Fragment implements RecentMusicAdapter.ItemCli bind.mostPlayedTracksRecyclerView.setHasFixedSize(true); mostPlayedMusicAdapter = new RecentMusicAdapter(requireContext(), new ArrayList<>()); - mostPlayedMusicAdapter.setClickListener(this); bind.mostPlayedTracksRecyclerView.setAdapter(mostPlayedMusicAdapter); homeViewModel.getMostPlayedSongList().observe(requireActivity(), songs -> mostPlayedMusicAdapter.setItems(songs)); } - - @Override - public void onItemClick(View view, int position) { - Toast.makeText(requireContext(), "Click: " + position, Toast.LENGTH_SHORT).show(); - } } 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 b66aa859..22661e2a 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 @@ -107,8 +107,9 @@ public class LibraryFragment extends Fragment { bind.playlistRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2)); bind.playlistRecyclerView.setHasFixedSize(true); - playlistAdapter = new PlaylistAdapter(requireContext(), libraryViewModel.getPlaylist()); + playlistAdapter = new PlaylistAdapter(requireContext(), new ArrayList<>()); playlistAdapter.setClickListener((view, position) -> Toast.makeText(requireContext(), "Playlist: " + position, Toast.LENGTH_SHORT).show()); bind.playlistRecyclerView.setAdapter(playlistAdapter); + libraryViewModel.getPlaylistList().observe(requireActivity(), playlists -> playlistAdapter.setItems(playlists)); } } 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 871a2f55..e69ba52f 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 @@ -12,12 +12,17 @@ import androidx.annotation.Nullable; 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.R; +import com.cappielloantonio.play.adapter.AlbumCatalogueAdapter; +import com.cappielloantonio.play.adapter.ArtistCatalogueAdapter; import com.cappielloantonio.play.adapter.RecentSearchAdapter; import com.cappielloantonio.play.adapter.SongResultSearchAdapter; import com.cappielloantonio.play.databinding.FragmentSearchBinding; +import com.cappielloantonio.play.helper.recyclerview.ItemlDecoration; +import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.model.RecentSearch; import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.ui.activities.MainActivity; @@ -35,6 +40,8 @@ public class SearchFragment extends Fragment { private RecentSearchAdapter recentSearchAdapter; private SongResultSearchAdapter songResultSearchAdapter; + private AlbumCatalogueAdapter albumResultSearchAdapter; + private ArtistCatalogueAdapter artistResultSearchAdapter; @Nullable @Override @@ -78,14 +85,37 @@ public class SearchFragment extends Fragment { } private void initSearchResultView() { + // Songs bind.searchResultTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); bind.searchResultTracksRecyclerView.setHasFixedSize(true); songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), new ArrayList<>()); - songResultSearchAdapter.setClickListener((view, position) -> { - Toast.makeText(requireContext(), "Song " + position, Toast.LENGTH_SHORT).show(); - }); bind.searchResultTracksRecyclerView.setAdapter(songResultSearchAdapter); + + // Albums + bind.searchResultAlbumRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2)); + bind.searchResultAlbumRecyclerView.addItemDecoration(new ItemlDecoration(2, 20, false)); + bind.searchResultAlbumRecyclerView.setHasFixedSize(true); + + albumResultSearchAdapter = new AlbumCatalogueAdapter(requireContext(), new ArrayList<>()); + albumResultSearchAdapter.setClickListener((view, position) -> { + Toast.makeText(requireContext(), "Album " + position, Toast.LENGTH_SHORT).show(); + }); + bind.searchResultAlbumRecyclerView.setAdapter(albumResultSearchAdapter); + + // Artist + bind.searchResultArtistRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2)); + bind.searchResultArtistRecyclerView.addItemDecoration(new ItemlDecoration(2, 20, false)); + bind.searchResultArtistRecyclerView.setHasFixedSize(true); + + artistResultSearchAdapter = new ArtistCatalogueAdapter(requireContext(), new ArrayList<>()); + artistResultSearchAdapter.setClickListener((view, position) -> { + Toast.makeText(requireContext(), "Artist " + position, Toast.LENGTH_SHORT).show(); + Bundle bundle = new Bundle(); + bundle.putString("artistID", artistResultSearchAdapter.getItem(position).id); + activity.navController.navigate(R.id.action_searchFragment_to_artistPageFragment, bundle); + }); + bind.searchResultArtistRecyclerView.setAdapter(artistResultSearchAdapter); } private void initSearchView() { @@ -118,5 +148,9 @@ public class SearchFragment extends Fragment { private void performSearch(String query) { searchViewModel.searchSong(query).observe(requireActivity(), songs -> songResultSearchAdapter.setItems(songs)); + searchViewModel.searchAlbum(query).observe(requireActivity(), albums -> albumResultSearchAdapter.setItems(albums)); + searchViewModel.searchArtist(query).observe(requireActivity(), artists -> artistResultSearchAdapter.setItems(artists)); + + bind.searchResultNestedScrollView.setVisibility(View.VISIBLE); } } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumCatalogueViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumCatalogueViewModel.java index 23a4fbd1..6217c464 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumCatalogueViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumCatalogueViewModel.java @@ -22,11 +22,10 @@ public class AlbumCatalogueViewModel extends AndroidViewModel { super(application); albumRepository = new AlbumRepository(application); - - albumList = albumRepository.getListLiveAlbums(); } public LiveData> getAlbumList() { + albumList = albumRepository.getListLiveAlbums(); return albumList; } } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistCatalogueViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistCatalogueViewModel.java index 2e1b862f..831e12ff 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistCatalogueViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistCatalogueViewModel.java @@ -20,11 +20,10 @@ public class ArtistCatalogueViewModel extends AndroidViewModel { super(application); artistRepository = new ArtistRepository(application); - - artistList = artistRepository.getListLiveArtists(); } public LiveData> getArtistList() { + artistList = artistRepository.getListLiveArtists(); return artistList; } } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistPageViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistPageViewModel.java new file mode 100644 index 00000000..bbd15099 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/ArtistPageViewModel.java @@ -0,0 +1,39 @@ +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.Album; +import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.repository.AlbumRepository; +import com.cappielloantonio.play.repository.SongRepository; + +import java.util.List; + +public class ArtistPageViewModel extends AndroidViewModel { + private SongRepository songRepository; + private AlbumRepository albumRepository; + + private LiveData> songList; + private LiveData> albumList; + + public ArtistPageViewModel(@NonNull Application application) { + super(application); + + songRepository = new SongRepository(application); + albumRepository = new AlbumRepository(application); + } + + public LiveData> getAlbumList(String artistID) { + albumList = albumRepository.getArtistListLiveAlbums(artistID); + return albumList; + } + + public LiveData> getArtistTopSongList(String artistID) { + songList = songRepository.getArtistListLiveTopSong(artistID); + 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 46e67440..a8c1e9c8 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/GenreCatalogueViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/GenreCatalogueViewModel.java @@ -22,11 +22,10 @@ public class GenreCatalogueViewModel extends AndroidViewModel { super(application); genreRepository = new GenreRepository(application); - - genreList = genreRepository.getListLiveGenres(); } public LiveData> getGenreList() { + genreList = genreRepository.getListLiveGenres(); return genreList; } } 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 6f7ca9eb..e03ac4c0 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java @@ -5,18 +5,17 @@ import android.app.Application; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; -import androidx.lifecycle.ViewModel; import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.repository.SongRepository; -import java.util.ArrayList; import java.util.List; public class HomeViewModel extends AndroidViewModel { + private static final String TAG = "HomeViewModel"; private SongRepository songRepository; - private LiveData> dicoverSongSample; + private List dicoverSongSample; private LiveData> recentlyPlayedSongSample; private LiveData> recentlyAddedSongSample; private LiveData> mostPlayedSongSample; @@ -26,14 +25,14 @@ public class HomeViewModel extends AndroidViewModel { songRepository = new SongRepository(application); - dicoverSongSample = songRepository.getListLiveDiscoverSampleSong(); + dicoverSongSample = songRepository.getRandomSample(5); recentlyPlayedSongSample = songRepository.getListLiveRecentlyPlayedSampleSong(); recentlyAddedSongSample = songRepository.getListLiveRecentlyAddedSampleSong(); mostPlayedSongSample = songRepository.getListLiveMostPlayedSampleSong(); } - public LiveData> getDiscoverSongList() { + public List getDiscoverSongList() { 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 a495ab4b..da6383b5 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/LibraryViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/LibraryViewModel.java @@ -13,6 +13,7 @@ import com.cappielloantonio.play.model.Playlist; import com.cappielloantonio.play.repository.AlbumRepository; import com.cappielloantonio.play.repository.ArtistRepository; import com.cappielloantonio.play.repository.GenreRepository; +import com.cappielloantonio.play.repository.PlaylistRepository; import java.util.ArrayList; import java.util.List; @@ -21,12 +22,14 @@ public class LibraryViewModel extends AndroidViewModel { private AlbumRepository albumRepository; private ArtistRepository artistRepository; private GenreRepository genreRepository; + private PlaylistRepository playlistRepository; private LiveData> sampleAlbum; private LiveData> sampleArtist; private LiveData> sampleGenres; private LiveData> allGenres; + private LiveData> allPlaylist; public LibraryViewModel(@NonNull Application application) { super(application); @@ -34,6 +37,7 @@ public class LibraryViewModel extends AndroidViewModel { albumRepository = new AlbumRepository(application); artistRepository = new ArtistRepository(application); genreRepository = new GenreRepository(application); + playlistRepository = new PlaylistRepository(application); // Inizializzate all'interno del costruttore, in modo da rimanere immutabili per tutto il // ciclo di vita dell'applicazione @@ -47,6 +51,11 @@ public class LibraryViewModel extends AndroidViewModel { return allGenres; } + public LiveData> getPlaylistList() { + allPlaylist = playlistRepository.getListLivePlaylists(); + return allPlaylist; + } + public LiveData> getAlbumSample() { return sampleAlbum; } @@ -58,19 +67,4 @@ public class LibraryViewModel extends AndroidViewModel { public LiveData> getGenreSample() { return sampleGenres; } - - public ArrayList getPlaylist() { - ArrayList playlists = new ArrayList<>(); - playlists.add(new Playlist("1", "sdad", "", "")); - playlists.add(new Playlist("2", "rwef", "", "")); - playlists.add(new Playlist("3", "khjf", "", "")); - playlists.add(new Playlist("4", "thfd", "", "")); - playlists.add(new Playlist("5", "jhku", "", "")); - playlists.add(new Playlist("6", "tuid", "", "")); - playlists.add(new Playlist("7", "hfrt", "", "")); - playlists.add(new Playlist("8", "qedg", "", "")); - playlists.add(new Playlist("9", "tugh", "", "")); - - return playlists; - } } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/SearchViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/SearchViewModel.java index e44cffc4..4d3fca37 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/SearchViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/SearchViewModel.java @@ -6,9 +6,13 @@ import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; +import com.cappielloantonio.play.model.Album; +import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.model.Genre; import com.cappielloantonio.play.model.RecentSearch; import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.repository.AlbumRepository; +import com.cappielloantonio.play.repository.ArtistRepository; import com.cappielloantonio.play.repository.GenreRepository; import com.cappielloantonio.play.repository.RecentSearchRepository; import com.cappielloantonio.play.repository.SongRepository; @@ -17,18 +21,21 @@ import java.util.List; public class SearchViewModel extends AndroidViewModel { private SongRepository songRepository; - private GenreRepository genreRepository; + private AlbumRepository albumRepository; + private ArtistRepository artistRepository; private RecentSearchRepository recentSearchRepository; private LiveData> searchSong; - private LiveData> allGenres; + private LiveData> searchAlbum; + private LiveData> searchArtist; private LiveData> recentSearches; public SearchViewModel(@NonNull Application application) { super(application); songRepository = new SongRepository(application); - genreRepository = new GenreRepository(application); + albumRepository = new AlbumRepository(application); + artistRepository = new ArtistRepository(application); recentSearchRepository = new RecentSearchRepository(application); } @@ -37,9 +44,14 @@ public class SearchViewModel extends AndroidViewModel { return searchSong; } - public LiveData> getGenreList() { - allGenres = genreRepository.getListLiveGenres(); - return allGenres; + public LiveData> searchAlbum(String name) { + searchAlbum = albumRepository.searchListLiveAlbum(name); + return searchAlbum; + } + + public LiveData> searchArtist(String name) { + searchArtist = artistRepository.searchListLiveArtist(name); + return searchArtist; } public LiveData> getSearchList() { diff --git a/app/src/main/res/font/extra_bold.ttf b/app/src/main/res/font/extra_bold.ttf new file mode 100644 index 00000000..67fcf0fb Binary files /dev/null and b/app/src/main/res/font/extra_bold.ttf differ diff --git a/app/src/main/res/font/open_sans_font_family.xml b/app/src/main/res/font/open_sans_font_family.xml index 4fbd1655..05d03a24 100644 --- a/app/src/main/res/font/open_sans_font_family.xml +++ b/app/src/main/res/font/open_sans_font_family.xml @@ -3,4 +3,5 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_album_catalogue.xml b/app/src/main/res/layout/fragment_album_catalogue.xml index b3a8b717..ca3ee340 100644 --- a/app/src/main/res/layout/fragment_album_catalogue.xml +++ b/app/src/main/res/layout/fragment_album_catalogue.xml @@ -1,5 +1,4 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_filter.xml b/app/src/main/res/layout/fragment_filter.xml index 9fcfa92b..770220c1 100644 --- a/app/src/main/res/layout/fragment_filter.xml +++ b/app/src/main/res/layout/fragment_filter.xml @@ -1,38 +1,53 @@ - + android:layout_height="match_parent"> + android:layout_centerInParent="true"/> - + android:layout_height="match_parent" + app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior" + android:visibility="gone" + android:paddingTop="8dp"> - - - + android:orientation="vertical" + android:paddingBottom="8dp"> + + + + + + + diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index d63c5a39..4512a479 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -17,6 +17,38 @@ android:layout_height="wrap_content" android:orientation="vertical"> + + + + + + + + + @@ -53,17 +85,16 @@ - - @@ -181,13 +212,13 @@ style="@style/Widget.MaterialComponents.Button.OutlinedButton" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="24dp" android:layout_marginStart="16dp" + android:layout_marginTop="24dp" android:layout_marginEnd="16dp" android:text="Resync" android:textAllCaps="false" android:textColor="@color/normalTextColor" - app:cornerRadius="24dp"/> + app:cornerRadius="24dp" /> diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index c1056690..b810e593 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -90,37 +90,104 @@ android:paddingEnd="8dp" /> - - + + + + android:visibility="gone"> - - - - + - + android:layout_height="wrap_content" + android:orientation="vertical"> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_artist_page_album.xml b/app/src/main/res/layout/item_artist_page_album.xml new file mode 100644 index 00000000..8cfd330d --- /dev/null +++ b/app/src/main/res/layout/item_artist_page_album.xml @@ -0,0 +1,32 @@ + + + + + + + \ No newline at end of file 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 fae8261e..cc1d7b3f 100644 --- a/app/src/main/res/layout/item_home_discover_song.xml +++ b/app/src/main/res/layout/item_home_discover_song.xml @@ -1,6 +1,5 @@ - diff --git a/app/src/main/res/layout/item_library_catalogue_genre.xml b/app/src/main/res/layout/item_library_catalogue_genre.xml index fbe37ebb..0173b7d4 100644 --- a/app/src/main/res/layout/item_library_catalogue_genre.xml +++ b/app/src/main/res/layout/item_library_catalogue_genre.xml @@ -2,8 +2,7 @@ + android:orientation="vertical"> + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_search_result_song.xml b/app/src/main/res/layout/item_search_result_song.xml index db030e54..fb082d41 100644 --- a/app/src/main/res/layout/item_search_result_song.xml +++ b/app/src/main/res/layout/item_search_result_song.xml @@ -4,16 +4,17 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:paddingTop="4dp" - android:paddingBottom="4dp" + android:paddingTop="2dp" + android:paddingBottom="2dp" android:paddingEnd="4dp"> + + + + + + + tools:layout="@layout/fragment_artist_catalogue"> + + + + + + \ No newline at end of file