mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 17:43:32 +00:00
Add artist page
This commit is contained in:
parent
8b7e383dc2
commit
c2be2711b9
44 changed files with 1028 additions and 191 deletions
|
|
@ -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<AlbumArtistPageAdapter.ViewHolder> {
|
||||
private static final String TAG = "RecentMusicAdapter";
|
||||
private List<Album> albums;
|
||||
private LayoutInflater mInflater;
|
||||
private Context context;
|
||||
private ItemClickListener itemClickListener;
|
||||
|
||||
public AlbumArtistPageAdapter(Context context, List<Album> 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<Album> albums) {
|
||||
this.albums = albums;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setClickListener(ItemClickListener itemClickListener) {
|
||||
this.itemClickListener = itemClickListener;
|
||||
}
|
||||
|
||||
public interface ItemClickListener {
|
||||
void onItemClick(View view, int position);
|
||||
}
|
||||
}
|
||||
|
|
@ -61,6 +61,10 @@ public class ArtistCatalogueAdapter extends RecyclerView.Adapter<ArtistCatalogue
|
|||
}
|
||||
}
|
||||
|
||||
public Artist getItem(int position) {
|
||||
return artists.get(position);
|
||||
}
|
||||
|
||||
public void setItems(List<Artist> artists) {
|
||||
this.artists = artists;
|
||||
notifyDataSetChanged();
|
||||
|
|
|
|||
|
|
@ -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<Song> songs;
|
||||
private LayoutInflater layoutInflater;
|
||||
private Context context;
|
||||
private View view;
|
||||
|
||||
public DiscoverSongAdapter(Context context, List<Song> models) {
|
||||
public DiscoverSongAdapter(Context context, List<Song> 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<Song> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<RecentMusicAdapter.
|
|||
private List<Song> songs;
|
||||
private LayoutInflater mInflater;
|
||||
private Context context;
|
||||
private ItemClickListener itemClickListener;
|
||||
|
||||
public RecentMusicAdapter(Context context, List<Song> songs) {
|
||||
this.context = context;
|
||||
|
|
@ -65,7 +66,8 @@ public class RecentMusicAdapter extends RecyclerView.Adapter<RecentMusicAdapter.
|
|||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (itemClickListener != null) itemClickListener.onItemClick(view, getAdapterPosition());
|
||||
SongRepository songRepository = new SongRepository(App.getInstance());
|
||||
songRepository.update(songs.get(getAdapterPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,12 +75,4 @@ public class RecentMusicAdapter extends RecyclerView.Adapter<RecentMusicAdapter.
|
|||
this.songs = songs;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setClickListener(ItemClickListener itemClickListener) {
|
||||
this.itemClickListener = itemClickListener;
|
||||
}
|
||||
|
||||
public interface ItemClickListener {
|
||||
void onItemClick(View view, int position);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ import android.widget.TextView;
|
|||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
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;
|
||||
|
|
@ -22,7 +24,6 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter<SongResultSear
|
|||
private List<Song> songs;
|
||||
private LayoutInflater mInflater;
|
||||
private Context context;
|
||||
private ItemClickListener itemClickListener;
|
||||
|
||||
public SongResultSearchAdapter(Context context, List<Song> songs) {
|
||||
this.context = context;
|
||||
|
|
@ -67,8 +68,8 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter<SongResultSear
|
|||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (itemClickListener != null)
|
||||
itemClickListener.onItemClick(view, getAdapterPosition());
|
||||
SongRepository songRepository = new SongRepository(App.getInstance());
|
||||
songRepository.update(songs.get(getAdapterPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,12 +81,4 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter<SongResultSear
|
|||
public Song getItem(int id) {
|
||||
return songs.get(id);
|
||||
}
|
||||
|
||||
public void setClickListener(ItemClickListener itemClickListener) {
|
||||
this.itemClickListener = itemClickListener;
|
||||
}
|
||||
|
||||
public interface ItemClickListener {
|
||||
void onItemClick(View view, int position);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import com.cappielloantonio.play.model.Playlist;
|
|||
import com.cappielloantonio.play.model.RecentSearch;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
|
||||
@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class}, version = 3, exportSchema = false)
|
||||
@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class}, version = 4, exportSchema = false)
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
private static final String TAG = "AppDatabase";
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import androidx.room.OnConflictStrategy;
|
|||
import androidx.room.Query;
|
||||
|
||||
import com.cappielloantonio.play.model.Album;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -17,9 +16,15 @@ public interface AlbumDao {
|
|||
@Query("SELECT * FROM album")
|
||||
LiveData<List<Album>> getAll();
|
||||
|
||||
@Query("SELECT * FROM album WHERE artistId = :artistId;")
|
||||
LiveData<List<Album>> getArtistAlbums(String artistId);
|
||||
|
||||
@Query("SELECT * FROM album ORDER BY RANDOM() LIMIT :number;")
|
||||
LiveData<List<Album>> getSample(int number);
|
||||
|
||||
@Query("SELECT * FROM album WHERE title LIKE '%' || :name || '%'")
|
||||
LiveData<List<Album>> searchAlbum(String name);
|
||||
|
||||
@Query("SELECT EXISTS(SELECT * FROM album WHERE id = :id)")
|
||||
boolean exist(String id);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<List<Artist>> getSample(int number);
|
||||
|
||||
@Query("SELECT * FROM artist WHERE name LIKE '%' || :name || '%'")
|
||||
LiveData<List<Artist>> searchArtist(String name);
|
||||
|
||||
@Query("SELECT EXISTS(SELECT * FROM artist WHERE id = :id)")
|
||||
boolean exist(String id);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<List<Song>> getDiscoverSample(int number);
|
||||
|
||||
@Query("SELECT * FROM song ORDER BY RANDOM() LIMIT :number")
|
||||
@Query("SELECT * FROM song ORDER BY added DESC LIMIT :number")
|
||||
LiveData<List<Song>> 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<List<Song>> 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<List<Song>> getMostPlayedSample(int number);
|
||||
|
||||
@Query("SELECT * FROM song WHERE play_count != 0 AND artistId = :artistID ORDER BY play_count DESC LIMIT :number")
|
||||
LiveData<List<Song>> 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<Song> random(int number);
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Artist> CREATOR = new Parcelable.Creator<Artist>() {
|
||||
|
|
|
|||
|
|
@ -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<Song> CREATOR = new Creator<Song>() {
|
||||
|
|
|
|||
|
|
@ -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<List<Album>> listLiveAlbums;
|
||||
private LiveData<List<Album>> artistListLiveAlbums;
|
||||
private LiveData<List<Album>> listLiveSampleAlbum;
|
||||
private LiveData<List<Album>> searchListLiveAlbum;
|
||||
|
||||
|
||||
public AlbumRepository(Application application) {
|
||||
AppDatabase database = AppDatabase.getInstance(application);
|
||||
|
|
@ -26,11 +31,21 @@ public class AlbumRepository {
|
|||
return listLiveAlbums;
|
||||
}
|
||||
|
||||
public LiveData<List<Album>> getArtistListLiveAlbums(String artistId) {
|
||||
artistListLiveAlbums = albumDao.getArtistAlbums(artistId);
|
||||
return artistListLiveAlbums;
|
||||
}
|
||||
|
||||
public LiveData<List<Album>> getListLiveSampleAlbum() {
|
||||
listLiveSampleAlbum = albumDao.getSample(10);
|
||||
return listLiveSampleAlbum;
|
||||
}
|
||||
|
||||
public LiveData<List<Album>> searchListLiveAlbum(String name) {
|
||||
searchListLiveAlbum = albumDao.searchAlbum(name);
|
||||
return searchListLiveAlbum;
|
||||
}
|
||||
|
||||
public boolean exist(Album album) {
|
||||
boolean exist = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<List<Artist>> listLiveArtists;
|
||||
private LiveData<List<Artist>> listLiveSampleArtist;
|
||||
private LiveData<List<Artist>> searchListLiveArtist;
|
||||
|
||||
|
||||
public ArtistRepository(Application application) {
|
||||
AppDatabase database = AppDatabase.getInstance(application);
|
||||
|
|
@ -32,6 +35,11 @@ public class ArtistRepository {
|
|||
return listLiveSampleArtist;
|
||||
}
|
||||
|
||||
public LiveData<List<Artist>> searchListLiveArtist(String name) {
|
||||
searchListLiveArtist = artistDao.searchArtist(name);
|
||||
return searchListLiveArtist;
|
||||
}
|
||||
|
||||
public boolean exist(Artist artist) {
|
||||
boolean exist = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,11 @@ import java.util.List;
|
|||
|
||||
public class SongRepository {
|
||||
private SongDao songDao;
|
||||
private LiveData<List<Song>> listLiveSongs;
|
||||
private LiveData<List<Song>> searchListLiveSongs;
|
||||
private LiveData<List<Song>> listLiveSampleDiscoverSongs;
|
||||
private LiveData<List<Song>> listLiveSampleRecentlyAddedSongs;
|
||||
private LiveData<List<Song>> listLiveSampleRecentlyPlayedSongs;
|
||||
private LiveData<List<Song>> listLiveSampleMostPlayedSongs;
|
||||
private LiveData<List<Song>> listLiveSampleArtistTopSongs;
|
||||
|
||||
|
||||
public SongRepository(Application application) {
|
||||
|
|
@ -32,11 +31,6 @@ public class SongRepository {
|
|||
return searchListLiveSongs;
|
||||
}
|
||||
|
||||
public LiveData<List<Song>> getListLiveDiscoverSampleSong() {
|
||||
listLiveSampleDiscoverSongs = songDao.getDiscoverSample(5);
|
||||
return listLiveSampleDiscoverSongs;
|
||||
}
|
||||
|
||||
public LiveData<List<Song>> getListLiveRecentlyAddedSampleSong() {
|
||||
listLiveSampleRecentlyAddedSongs = songDao.getRecentlyAddedSample(20);
|
||||
return listLiveSampleRecentlyAddedSongs;
|
||||
|
|
@ -52,6 +46,11 @@ public class SongRepository {
|
|||
return listLiveSampleMostPlayedSongs;
|
||||
}
|
||||
|
||||
public LiveData<List<Song>> 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<Song> getRandomSample(int number) {
|
||||
List<Song> 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<Song> sample;
|
||||
|
||||
public PickRandomThreadSafe(SongDao songDao, int number) {
|
||||
this.songDao = songDao;
|
||||
this.elementNumber = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
sample = songDao.random(elementNumber);
|
||||
}
|
||||
|
||||
public List<Song> getSample() {
|
||||
return sample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<>());
|
||||
|
|
|
|||
|
|
@ -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<>());
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,11 +22,10 @@ public class AlbumCatalogueViewModel extends AndroidViewModel {
|
|||
super(application);
|
||||
|
||||
albumRepository = new AlbumRepository(application);
|
||||
|
||||
albumList = albumRepository.getListLiveAlbums();
|
||||
}
|
||||
|
||||
public LiveData<List<Album>> getAlbumList() {
|
||||
albumList = albumRepository.getListLiveAlbums();
|
||||
return albumList;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,10 @@ public class ArtistCatalogueViewModel extends AndroidViewModel {
|
|||
super(application);
|
||||
|
||||
artistRepository = new ArtistRepository(application);
|
||||
|
||||
artistList = artistRepository.getListLiveArtists();
|
||||
}
|
||||
|
||||
public LiveData<List<Artist>> getArtistList() {
|
||||
artistList = artistRepository.getListLiveArtists();
|
||||
return artistList;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<List<Song>> songList;
|
||||
private LiveData<List<Album>> albumList;
|
||||
|
||||
public ArtistPageViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
|
||||
songRepository = new SongRepository(application);
|
||||
albumRepository = new AlbumRepository(application);
|
||||
}
|
||||
|
||||
public LiveData<List<Album>> getAlbumList(String artistID) {
|
||||
albumList = albumRepository.getArtistListLiveAlbums(artistID);
|
||||
return albumList;
|
||||
}
|
||||
|
||||
public LiveData<List<Song>> getArtistTopSongList(String artistID) {
|
||||
songList = songRepository.getArtistListLiveTopSong(artistID);
|
||||
return songList;
|
||||
}
|
||||
}
|
||||
|
|
@ -22,11 +22,10 @@ public class GenreCatalogueViewModel extends AndroidViewModel {
|
|||
super(application);
|
||||
|
||||
genreRepository = new GenreRepository(application);
|
||||
|
||||
genreList = genreRepository.getListLiveGenres();
|
||||
}
|
||||
|
||||
public LiveData<List<Genre>> getGenreList() {
|
||||
genreList = genreRepository.getListLiveGenres();
|
||||
return genreList;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<List<Song>> dicoverSongSample;
|
||||
private List<Song> dicoverSongSample;
|
||||
private LiveData<List<Song>> recentlyPlayedSongSample;
|
||||
private LiveData<List<Song>> recentlyAddedSongSample;
|
||||
private LiveData<List<Song>> 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<List<Song>> getDiscoverSongList() {
|
||||
public List<Song> getDiscoverSongList() {
|
||||
return dicoverSongSample;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<List<Album>> sampleAlbum;
|
||||
private LiveData<List<Artist>> sampleArtist;
|
||||
private LiveData<List<Genre>> sampleGenres;
|
||||
|
||||
private LiveData<List<Genre>> allGenres;
|
||||
private LiveData<List<Playlist>> 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<List<Playlist>> getPlaylistList() {
|
||||
allPlaylist = playlistRepository.getListLivePlaylists();
|
||||
return allPlaylist;
|
||||
}
|
||||
|
||||
public LiveData<List<Album>> getAlbumSample() {
|
||||
return sampleAlbum;
|
||||
}
|
||||
|
|
@ -58,19 +67,4 @@ public class LibraryViewModel extends AndroidViewModel {
|
|||
public LiveData<List<Genre>> getGenreSample() {
|
||||
return sampleGenres;
|
||||
}
|
||||
|
||||
public ArrayList<Playlist> getPlaylist() {
|
||||
ArrayList<Playlist> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<List<Song>> searchSong;
|
||||
private LiveData<List<Genre>> allGenres;
|
||||
private LiveData<List<Album>> searchAlbum;
|
||||
private LiveData<List<Artist>> searchArtist;
|
||||
private LiveData<List<RecentSearch>> 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<List<Genre>> getGenreList() {
|
||||
allGenres = genreRepository.getListLiveGenres();
|
||||
return allGenres;
|
||||
public LiveData<List<Album>> searchAlbum(String name) {
|
||||
searchAlbum = albumRepository.searchListLiveAlbum(name);
|
||||
return searchAlbum;
|
||||
}
|
||||
|
||||
public LiveData<List<Artist>> searchArtist(String name) {
|
||||
searchArtist = artistRepository.searchListLiveArtist(name);
|
||||
return searchArtist;
|
||||
}
|
||||
|
||||
public LiveData<List<RecentSearch>> getSearchList() {
|
||||
|
|
|
|||
BIN
app/src/main/res/font/extra_bold.ttf
Normal file
BIN
app/src/main/res/font/extra_bold.ttf
Normal file
Binary file not shown.
|
|
@ -3,4 +3,5 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<font app:font="@font/regular" app:fontStyle="normal" app:fontWeight="400" />
|
||||
<font app:font="@font/bold" app:fontStyle="normal" app:fontWeight="700" />
|
||||
<font app:font="@font/extra_bold" app:fontStyle="normal" app:fontWeight="900" />
|
||||
</font-family>
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
|
|
|
|||
120
app/src/main/res/layout/fragment_artist_page.xml
Normal file
120
app/src/main/res/layout/fragment_artist_page.xml
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:backgroundTint="@color/cardColor"
|
||||
app:layout_constraintDimensionRatio="W, 4:5"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:text="Green Day"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="40sp"
|
||||
android:textStyle="bold"
|
||||
android:textFontWeight="900"
|
||||
android:paddingBottom="32dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- Label and button -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Most Streamed Songs"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/album_catalogue_text_view_clickable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="See all"
|
||||
android:textColor="@color/subtitleTextColor"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/most_streamed_song_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:text="Albums"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/albums_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="8dp" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
|
@ -1,38 +1,53 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/loading_progress_bar"
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:minWidth="128dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
android:layout_centerInParent="true"/>
|
||||
|
||||
<ScrollView
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/filter_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="8dp">
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"
|
||||
android:visibility="gone"
|
||||
android:paddingTop="8dp">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/filters_chips_group"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:singleSelection="false" />
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:text="Filter"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/filters_chips_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:singleSelection="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"/>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</RelativeLayout>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,38 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:text="Discover Music"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- slideview -->
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/discover_song_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="152dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="8dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Recently added tracks -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Label and button -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -34,7 +66,7 @@
|
|||
android:paddingStart="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Discover Music"
|
||||
android:text="Recently added tracks"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
|
@ -53,17 +85,16 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- slideview -->
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/discover_song_view_pager"
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recently_added_tracks_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="152dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="8dp" />
|
||||
</LinearLayout>
|
||||
|
||||
|
|
@ -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" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
|
|
|||
|
|
@ -90,37 +90,104 @@
|
|||
android:paddingEnd="8dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Search result -->
|
||||
<LinearLayout
|
||||
android:id="@+id/search_result_layout"
|
||||
<!-- Label -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Search results"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/search_result_nested_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:visibility="gone">
|
||||
|
||||
<!-- Label -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Search results"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/search_result_tracks_recycler_view"
|
||||
<!-- Search result -->
|
||||
<LinearLayout
|
||||
android:id="@+id/search_result_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="4dp"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="56dp" />
|
||||
</LinearLayout>
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Songs"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/search_result_tracks_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="24dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Albums"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/search_result_album_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="16dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:text="Artists"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/search_result_artist_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="56dp" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
32
app/src/main/res/layout/item_artist_page_album.xml
Normal file
32
app/src/main/res/layout/item_artist_page_album.xml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/card_view"
|
||||
android:layout_width="256dp"
|
||||
android:layout_height="256dp"
|
||||
android:layout_gravity="center"
|
||||
android:backgroundTint="@color/cardColor"
|
||||
card_view:cardCornerRadius="4dp"
|
||||
card_view:cardElevation="2dp"
|
||||
card_view:cardPreventCornerOverlap="false"
|
||||
card_view:cardUseCompatPadding="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/album_name_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:maxWidth="172dp"
|
||||
android:paddingStart="2dp"
|
||||
android:paddingTop="8dp"
|
||||
android:singleLine="false"
|
||||
android:text="@string/label_placeholder"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -16,8 +15,8 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:text="@string/label_placeholder"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="20sp" />
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="54dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="4dp">
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/card_view"
|
||||
|
|
|
|||
68
app/src/main/res/layout/item_library_song.xml
Normal file
68
app/src/main/res/layout/item_library_song.xml
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingEnd="4dp">
|
||||
|
||||
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_gravity="center"
|
||||
android:backgroundTint="@color/cardColor"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="@color/subtitleTextColor"
|
||||
card_view:cardCornerRadius="4dp"
|
||||
card_view:cardElevation="2dp"
|
||||
card_view:cardPreventCornerOverlap="false"
|
||||
card_view:cardUseCompatPadding="false"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_title_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:text="@string/label_placeholder"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toEndOf="@+id/imageView"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/song_album_text_view"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_album_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:text="@string/label_placeholder"
|
||||
android:textColor="@color/subtitleTextColor"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/imageView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/song_title_text_view" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_duration_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="@string/label_placeholder"
|
||||
android:textColor="@color/subtitleTextColor"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -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">
|
||||
|
||||
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_margin="2dp"
|
||||
android:layout_gravity="center"
|
||||
android:backgroundTint="@color/colorAccent"
|
||||
android:backgroundTint="@color/cardColor"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
|
|
|||
|
|
@ -81,6 +81,13 @@
|
|||
<action
|
||||
android:id="@+id/action_libraryFragment_to_genreCatalogueFragment"
|
||||
app:destination="@id/genreCatalogueFragment" />
|
||||
<action
|
||||
android:id="@+id/action_libraryFragment_to_artistPageFragment"
|
||||
app:destination="@id/artistPageFragment">
|
||||
<argument
|
||||
android:name="artistID"
|
||||
app:argType="string"/>
|
||||
</action>
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/settingsFragment"
|
||||
|
|
@ -95,6 +102,13 @@
|
|||
<action
|
||||
android:id="@+id/action_searchFragment_to_filterFragment"
|
||||
app:destination="@id/filterFragment" />
|
||||
<action
|
||||
android:id="@+id/action_searchFragment_to_artistPageFragment"
|
||||
app:destination="@id/artistPageFragment">
|
||||
<argument
|
||||
android:name="artistID"
|
||||
app:argType="string"/>
|
||||
</action>
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/filterFragment"
|
||||
|
|
@ -105,7 +119,15 @@
|
|||
android:id="@+id/artistCatalogueFragment"
|
||||
android:name="com.cappielloantonio.play.ui.fragment.ArtistCatalogueFragment"
|
||||
android:label="ArtistCatalogueFragment"
|
||||
tools:layout="@layout/fragment_artist_catalogue"/>
|
||||
tools:layout="@layout/fragment_artist_catalogue">
|
||||
<action
|
||||
android:id="@+id/action_artistCatalogueFragment_to_artistPageFragment"
|
||||
app:destination="@id/artistPageFragment">
|
||||
<argument
|
||||
android:name="artistID"
|
||||
app:argType="string"/>
|
||||
</action>
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/albumCatalogueFragment"
|
||||
android:name="com.cappielloantonio.play.ui.fragment.AlbumCatalogueFragment"
|
||||
|
|
@ -116,4 +138,10 @@
|
|||
android:name="com.cappielloantonio.play.ui.fragment.GenreCatalogueFragment"
|
||||
android:label="GenreCatalogueFragment"
|
||||
tools:layout="@layout/fragment_genre_catalogue"/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/artistPageFragment"
|
||||
android:name="com.cappielloantonio.play.ui.fragment.ArtistPageFragment"
|
||||
android:label="ArtistPageFragment"
|
||||
tools:layout="@layout/fragment_artist_page"/>
|
||||
</navigation>
|
||||
Loading…
Add table
Add a link
Reference in a new issue