Add song/genre sync
|
|
@ -21,10 +21,8 @@
|
||||||
android:windowSoftInputMode="adjustPan|adjustResize">
|
android:windowSoftInputMode="adjustPan|adjustResize">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
@ -2,12 +2,7 @@ package com.cappielloantonio.play;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import com.android.volley.RequestQueue;
|
|
||||||
import com.android.volley.toolbox.Volley;
|
|
||||||
import com.cappielloantonio.play.helper.ThemeHelper;
|
import com.cappielloantonio.play.helper.ThemeHelper;
|
||||||
import com.cappielloantonio.play.util.PreferenceUtil;
|
import com.cappielloantonio.play.util.PreferenceUtil;
|
||||||
|
|
||||||
|
|
@ -46,10 +41,6 @@ public class App extends Application {
|
||||||
return apiClient;
|
return apiClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RequestQueue getRequestQueue(Context context) {
|
|
||||||
return Volley.newRequestQueue(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ApiClient getApiClient(Context context) {
|
private static ApiClient getApiClient(Context context) {
|
||||||
String server = PreferenceUtil.getInstance(context).getServer();
|
String server = PreferenceUtil.getInstance(context).getServer();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
package com.cappielloantonio.play.adapter;
|
package com.cappielloantonio.play.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.viewpager.widget.PagerAdapter;
|
import androidx.viewpager.widget.PagerAdapter;
|
||||||
|
|
||||||
import com.cappielloantonio.play.App;
|
import com.cappielloantonio.play.App;
|
||||||
import com.cappielloantonio.play.R;
|
import com.cappielloantonio.play.R;
|
||||||
import com.cappielloantonio.play.model.Song;
|
import com.cappielloantonio.play.model.Song;
|
||||||
import com.cappielloantonio.play.repository.SongRepository;
|
import com.cappielloantonio.play.repository.SongRepository;
|
||||||
|
import com.cappielloantonio.play.util.Util;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -29,8 +29,6 @@ public class DiscoverSongAdapter extends PagerAdapter {
|
||||||
public DiscoverSongAdapter(Context context, List<Song> songs) {
|
public DiscoverSongAdapter(Context context, List<Song> songs) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.songs = songs;
|
this.songs = songs;
|
||||||
|
|
||||||
Log.d(TAG, "DiscoverSongAdapter: " + songs.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -50,7 +48,7 @@ public class DiscoverSongAdapter extends PagerAdapter {
|
||||||
view = layoutInflater.inflate(R.layout.item_home_discover_song, container, false);
|
view = layoutInflater.inflate(R.layout.item_home_discover_song, container, false);
|
||||||
|
|
||||||
TextView title = view.findViewById(R.id.title_discover_song_label);
|
TextView title = view.findViewById(R.id.title_discover_song_label);
|
||||||
TextView desc = view.findViewById(R.id.artist_discover_song_label);
|
TextView desc = view.findViewById(R.id.album_discover_song_label);
|
||||||
title.setText(songs.get(position).getTitle());
|
title.setText(songs.get(position).getTitle());
|
||||||
desc.setText(songs.get(position).getAlbumName());
|
desc.setText(songs.get(position).getAlbumName());
|
||||||
|
|
||||||
|
|
@ -64,8 +62,6 @@ public class DiscoverSongAdapter extends PagerAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setItems(List<Song> songs) {
|
public void setItems(List<Song> songs) {
|
||||||
Log.d(TAG, "setItems: CHANGING");
|
|
||||||
|
|
||||||
this.songs = songs;
|
this.songs = songs;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,10 @@ public class GenreAdapter extends RecyclerView.Adapter<GenreAdapter.ViewHolder>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Genre getItem(int position) {
|
||||||
|
return genres.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
public void setItems(List<Genre> genres) {
|
public void setItems(List<Genre> genres) {
|
||||||
this.genres = genres;
|
this.genres = genres;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.cappielloantonio.play.adapter;
|
package com.cappielloantonio.play.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Parcelable;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
@ -45,6 +46,7 @@ public class GenreCatalogueAdapter extends RecyclerView.Adapter<GenreCatalogueAd
|
||||||
return genres.size();
|
return genres.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||||
TextView textGenre;
|
TextView textGenre;
|
||||||
|
|
||||||
|
|
@ -62,6 +64,10 @@ public class GenreCatalogueAdapter extends RecyclerView.Adapter<GenreCatalogueAd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Genre getItem(int position) {
|
||||||
|
return genres.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
public void setItems(List<Genre> genres) {
|
public void setItems(List<Genre> genres) {
|
||||||
this.genres = genres;
|
this.genres = genres;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,16 @@ import com.cappielloantonio.play.database.dao.GenreDao;
|
||||||
import com.cappielloantonio.play.database.dao.PlaylistDao;
|
import com.cappielloantonio.play.database.dao.PlaylistDao;
|
||||||
import com.cappielloantonio.play.database.dao.RecentSearchDao;
|
import com.cappielloantonio.play.database.dao.RecentSearchDao;
|
||||||
import com.cappielloantonio.play.database.dao.SongDao;
|
import com.cappielloantonio.play.database.dao.SongDao;
|
||||||
|
import com.cappielloantonio.play.database.dao.SongGenreCrossDao;
|
||||||
import com.cappielloantonio.play.model.Album;
|
import com.cappielloantonio.play.model.Album;
|
||||||
import com.cappielloantonio.play.model.Artist;
|
import com.cappielloantonio.play.model.Artist;
|
||||||
import com.cappielloantonio.play.model.Genre;
|
import com.cappielloantonio.play.model.Genre;
|
||||||
import com.cappielloantonio.play.model.Playlist;
|
import com.cappielloantonio.play.model.Playlist;
|
||||||
import com.cappielloantonio.play.model.RecentSearch;
|
import com.cappielloantonio.play.model.RecentSearch;
|
||||||
import com.cappielloantonio.play.model.Song;
|
import com.cappielloantonio.play.model.Song;
|
||||||
|
import com.cappielloantonio.play.model.SongGenreCross;
|
||||||
|
|
||||||
@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class}, version = 4, exportSchema = false)
|
@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class, SongGenreCross.class}, version = 5, exportSchema = false)
|
||||||
public abstract class AppDatabase extends RoomDatabase {
|
public abstract class AppDatabase extends RoomDatabase {
|
||||||
private static final String TAG = "AppDatabase";
|
private static final String TAG = "AppDatabase";
|
||||||
|
|
||||||
|
|
@ -47,4 +49,6 @@ public abstract class AppDatabase extends RoomDatabase {
|
||||||
public abstract SongDao songDao();
|
public abstract SongDao songDao();
|
||||||
|
|
||||||
public abstract RecentSearchDao recentSearchDao();
|
public abstract RecentSearchDao recentSearchDao();
|
||||||
|
|
||||||
|
public abstract SongGenreCrossDao songGenreCrossDao();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ public interface GenreDao {
|
||||||
@Query("SELECT * FROM genre")
|
@Query("SELECT * FROM genre")
|
||||||
LiveData<List<Genre>> getAll();
|
LiveData<List<Genre>> getAll();
|
||||||
|
|
||||||
|
@Query("SELECT * FROM genre")
|
||||||
|
List<Genre> getGenreList();
|
||||||
|
|
||||||
@Query("SELECT * FROM genre ORDER BY RANDOM() LIMIT :number;")
|
@Query("SELECT * FROM genre ORDER BY RANDOM() LIMIT :number;")
|
||||||
LiveData<List<Genre>> getSample(int number);
|
LiveData<List<Genre>> getSample(int number);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,15 @@ public interface SongDao {
|
||||||
@Query("SELECT * FROM song WHERE play_count != 0 AND artistId = :artistID ORDER BY play_count DESC LIMIT :number")
|
@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);
|
LiveData<List<Song>> getArtistTopSongsSample(String artistID, int number);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM song WHERE artistId = :artistID ORDER BY play_count DESC")
|
||||||
|
LiveData<List<Song>> getArtistTopSongs(String artistID);
|
||||||
|
|
||||||
@Query("SELECT * FROM song WHERE albumId = :albumID ORDER BY trackNumber ASC")
|
@Query("SELECT * FROM song WHERE albumId = :albumID ORDER BY trackNumber ASC")
|
||||||
LiveData<List<Song>> getAlbumSong(String albumID);
|
LiveData<List<Song>> getAlbumSong(String albumID);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM song INNER Join song_genre_cross ON song.id = song_genre_cross.song_id AND song_genre_cross.genre_id = :genreID")
|
||||||
|
LiveData<List<Song>> getSongByGenre(String genreID);
|
||||||
|
|
||||||
@Query("SELECT EXISTS(SELECT * FROM song WHERE id = :id)")
|
@Query("SELECT EXISTS(SELECT * FROM song WHERE id = :id)")
|
||||||
boolean exist(String id);
|
boolean exist(String id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.cappielloantonio.play.database.dao;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.room.Dao;
|
||||||
|
import androidx.room.Delete;
|
||||||
|
import androidx.room.Insert;
|
||||||
|
import androidx.room.OnConflictStrategy;
|
||||||
|
import androidx.room.Query;
|
||||||
|
import androidx.room.Update;
|
||||||
|
|
||||||
|
import com.cappielloantonio.play.model.Song;
|
||||||
|
import com.cappielloantonio.play.model.SongGenreCross;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
public interface SongGenreCrossDao {
|
||||||
|
@Query("SELECT * FROM song_genre_cross")
|
||||||
|
LiveData<List<SongGenreCross>> getAll();
|
||||||
|
|
||||||
|
@Query("SELECT EXISTS(SELECT * FROM song_genre_cross WHERE id = :id)")
|
||||||
|
boolean exist(String id);
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
void insert(SongGenreCross songGenreCross);
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
void insertAll(List<SongGenreCross> songGenreCrosses);
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
void delete(SongGenreCross songGenreCross);
|
||||||
|
|
||||||
|
@Update
|
||||||
|
void update(SongGenreCross songGenreCross);
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
package com.cappielloantonio.play.interfaces;
|
package com.cappielloantonio.play.interfaces;
|
||||||
|
|
||||||
import com.android.volley.VolleyError;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface MediaCallback {
|
public interface MediaCallback {
|
||||||
void onError(Exception exception);
|
void onError(Exception exception);
|
||||||
|
|
||||||
void onLoadMedia(List<?> media);
|
void onLoadMedia(List<?> media);
|
||||||
}
|
}
|
||||||
|
|
@ -19,6 +19,21 @@ import java.util.UUID;
|
||||||
|
|
||||||
@Entity(tableName = "song")
|
@Entity(tableName = "song")
|
||||||
public class Song implements Parcelable {
|
public class Song implements Parcelable {
|
||||||
|
@Ignore
|
||||||
|
public static final String RECENTLY_PLAYED = "RECENTLY_PLAYED";
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
public static final String MOST_PLAYED = "MOST_PLAYED";
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
public static final String RECENTLY_ADDED = "RECENTLY_ADDED";
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
public static final String BY_GENRE = "BY_GENRE";
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
public static final String BY_ARTIST = "BY_ARTIST";
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@ColumnInfo(name = "id")
|
@ColumnInfo(name = "id")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
package com.cappielloantonio.play.model;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.room.ColumnInfo;
|
||||||
|
import androidx.room.Entity;
|
||||||
|
import androidx.room.Ignore;
|
||||||
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
import org.jellyfin.apiclient.model.dto.BaseItemDto;
|
||||||
|
import org.jellyfin.apiclient.model.dto.MediaSourceInfo;
|
||||||
|
import org.jellyfin.apiclient.model.entities.ImageType;
|
||||||
|
import org.jellyfin.apiclient.model.entities.MediaStream;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity(tableName = "song_genre_cross")
|
||||||
|
public class SongGenreCross implements Parcelable {
|
||||||
|
@NonNull
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ColumnInfo(name = "id")
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
@ColumnInfo(name = "song_id")
|
||||||
|
private String songId;
|
||||||
|
|
||||||
|
@ColumnInfo(name = "genre_id")
|
||||||
|
private String genreId;
|
||||||
|
|
||||||
|
public SongGenreCross(String songId, String genreId) {
|
||||||
|
this.songId = songId;
|
||||||
|
this.genreId = genreId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSongId() {
|
||||||
|
return songId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSongId(String songId) {
|
||||||
|
this.songId = songId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGenreId() {
|
||||||
|
return genreId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGenreId(String genreId) {
|
||||||
|
this.genreId = genreId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SongGenreCross(Parcel in) {
|
||||||
|
id = in.readInt();
|
||||||
|
songId = in.readString();
|
||||||
|
genreId = in.readString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeInt(id);
|
||||||
|
dest.writeString(songId);
|
||||||
|
dest.writeString(genreId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<SongGenreCross> CREATOR = new Creator<SongGenreCross>() {
|
||||||
|
@Override
|
||||||
|
public SongGenreCross createFromParcel(Parcel in) {
|
||||||
|
return new SongGenreCross(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SongGenreCross[] newArray(int size) {
|
||||||
|
return new SongGenreCross[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -6,20 +6,24 @@ import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
import com.cappielloantonio.play.database.AppDatabase;
|
import com.cappielloantonio.play.database.AppDatabase;
|
||||||
import com.cappielloantonio.play.database.dao.GenreDao;
|
import com.cappielloantonio.play.database.dao.GenreDao;
|
||||||
|
import com.cappielloantonio.play.database.dao.SongGenreCrossDao;
|
||||||
import com.cappielloantonio.play.model.Album;
|
import com.cappielloantonio.play.model.Album;
|
||||||
import com.cappielloantonio.play.model.Genre;
|
import com.cappielloantonio.play.model.Genre;
|
||||||
|
import com.cappielloantonio.play.model.SongGenreCross;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class GenreRepository {
|
public class GenreRepository {
|
||||||
private GenreDao genreDao;
|
private GenreDao genreDao;
|
||||||
|
private SongGenreCrossDao songGenreCrossDao;
|
||||||
private LiveData<List<Genre>> listLiveGenres;
|
private LiveData<List<Genre>> listLiveGenres;
|
||||||
private LiveData<List<Genre>> listLiveAlbumGenre;
|
private LiveData<List<Genre>> listLiveAlbumGenre;
|
||||||
|
|
||||||
public GenreRepository(Application application) {
|
public GenreRepository(Application application) {
|
||||||
AppDatabase database = AppDatabase.getInstance(application);
|
AppDatabase database = AppDatabase.getInstance(application);
|
||||||
genreDao = database.genreDao();
|
genreDao = database.genreDao();
|
||||||
|
songGenreCrossDao = database.songGenreCrossDao();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Genre>> getListLiveGenres() {
|
public LiveData<List<Genre>> getListLiveGenres() {
|
||||||
|
|
@ -32,6 +36,24 @@ public class GenreRepository {
|
||||||
return listLiveAlbumGenre;
|
return listLiveAlbumGenre;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Genre> getListGenre() {
|
||||||
|
List<Genre> list = null;
|
||||||
|
|
||||||
|
GetGenreListThreadSafe getGenreListThread = new GetGenreListThreadSafe(genreDao);
|
||||||
|
Thread thread = new Thread(getGenreListThread);
|
||||||
|
thread.start();
|
||||||
|
|
||||||
|
try {
|
||||||
|
thread.join();
|
||||||
|
list = getGenreListThread.getList();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean exist(Genre genre) {
|
public boolean exist(Genre genre) {
|
||||||
boolean exist = false;
|
boolean exist = false;
|
||||||
|
|
||||||
|
|
@ -62,12 +84,36 @@ public class GenreRepository {
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void insertPerGenre(ArrayList<SongGenreCross> songGenreCrosses) {
|
||||||
|
InsertPerGenreThreadSafe insertPerGenre = new InsertPerGenreThreadSafe(songGenreCrossDao, songGenreCrosses);
|
||||||
|
Thread thread = new Thread(insertPerGenre);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
public void delete(Genre genre) {
|
public void delete(Genre genre) {
|
||||||
DeleteThreadSafe delete = new DeleteThreadSafe(genreDao, genre);
|
DeleteThreadSafe delete = new DeleteThreadSafe(genreDao, genre);
|
||||||
Thread thread = new Thread(delete);
|
Thread thread = new Thread(delete);
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class GetGenreListThreadSafe implements Runnable {
|
||||||
|
private GenreDao genreDao;
|
||||||
|
private List<Genre> list = null;
|
||||||
|
|
||||||
|
public GetGenreListThreadSafe(GenreDao genreDao) {
|
||||||
|
this.genreDao = genreDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
list = genreDao.getGenreList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Genre> getList() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class ExistThreadSafe implements Runnable {
|
private static class ExistThreadSafe implements Runnable {
|
||||||
private GenreDao genreDao;
|
private GenreDao genreDao;
|
||||||
private Genre genre;
|
private Genre genre;
|
||||||
|
|
@ -118,6 +164,21 @@ public class GenreRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class InsertPerGenreThreadSafe implements Runnable {
|
||||||
|
private SongGenreCrossDao songGenreCrossDao;
|
||||||
|
private ArrayList<SongGenreCross> cross;
|
||||||
|
|
||||||
|
public InsertPerGenreThreadSafe(SongGenreCrossDao songGenreCrossDao, ArrayList<SongGenreCross> cross) {
|
||||||
|
this.songGenreCrossDao = songGenreCrossDao;
|
||||||
|
this.cross = cross;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
songGenreCrossDao.insertAll(cross);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class DeleteThreadSafe implements Runnable {
|
private static class DeleteThreadSafe implements Runnable {
|
||||||
private GenreDao genreDao;
|
private GenreDao genreDao;
|
||||||
private Genre genre;
|
private Genre genre;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ public class SongRepository {
|
||||||
private LiveData<List<Song>> listLiveSampleMostPlayedSongs;
|
private LiveData<List<Song>> listLiveSampleMostPlayedSongs;
|
||||||
private LiveData<List<Song>> listLiveSampleArtistTopSongs;
|
private LiveData<List<Song>> listLiveSampleArtistTopSongs;
|
||||||
private LiveData<List<Song>> listLiveAlbumSongs;
|
private LiveData<List<Song>> listLiveAlbumSongs;
|
||||||
|
private LiveData<List<Song>> listLiveSongByGenre;
|
||||||
|
|
||||||
|
|
||||||
public SongRepository(Application application) {
|
public SongRepository(Application application) {
|
||||||
|
|
@ -32,26 +33,36 @@ public class SongRepository {
|
||||||
return searchListLiveSongs;
|
return searchListLiveSongs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Song>> getListLiveRecentlyAddedSampleSong() {
|
public LiveData<List<Song>> getListLiveRecentlyAddedSampleSong(int number) {
|
||||||
listLiveSampleRecentlyAddedSongs = songDao.getRecentlyAddedSample(20);
|
listLiveSampleRecentlyAddedSongs = songDao.getRecentlyAddedSample(number);
|
||||||
return listLiveSampleRecentlyAddedSongs;
|
return listLiveSampleRecentlyAddedSongs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Song>> getListLiveRecentlyPlayedSampleSong() {
|
public LiveData<List<Song>> getListLiveRecentlyPlayedSampleSong(int number) {
|
||||||
listLiveSampleRecentlyPlayedSongs = songDao.getRecentlyPlayedSample(20);
|
listLiveSampleRecentlyPlayedSongs = songDao.getRecentlyPlayedSample(number);
|
||||||
return listLiveSampleRecentlyPlayedSongs;
|
return listLiveSampleRecentlyPlayedSongs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Song>> getListLiveMostPlayedSampleSong() {
|
public LiveData<List<Song>> getListLiveMostPlayedSampleSong(int number) {
|
||||||
listLiveSampleMostPlayedSongs = songDao.getMostPlayedSample(20);
|
listLiveSampleMostPlayedSongs = songDao.getMostPlayedSample(number);
|
||||||
return listLiveSampleMostPlayedSongs;
|
return listLiveSampleMostPlayedSongs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Song>> getArtistListLiveTopSong(String artistID) {
|
public LiveData<List<Song>> getListLiveSongByGenre(String genreID) {
|
||||||
|
listLiveSongByGenre = songDao.getSongByGenre(genreID);
|
||||||
|
return listLiveSongByGenre;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<List<Song>> getArtistListLiveTopSongSample(String artistID) {
|
||||||
listLiveSampleArtistTopSongs = songDao.getArtistTopSongsSample(artistID, 5);
|
listLiveSampleArtistTopSongs = songDao.getArtistTopSongsSample(artistID, 5);
|
||||||
return listLiveSampleArtistTopSongs;
|
return listLiveSampleArtistTopSongs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<List<Song>> getArtistListLiveTopSong(String artistID) {
|
||||||
|
listLiveSampleArtistTopSongs = songDao.getArtistTopSongs(artistID);
|
||||||
|
return listLiveSampleArtistTopSongs;
|
||||||
|
}
|
||||||
|
|
||||||
public LiveData<List<Song>> getAlbumListLiveSong(String albumID) {
|
public LiveData<List<Song>> getAlbumListLiveSong(String albumID) {
|
||||||
listLiveAlbumSongs = songDao.getAlbumSong(albumID);
|
listLiveAlbumSongs = songDao.getAlbumSong(albumID);
|
||||||
return listLiveAlbumSongs;
|
return listLiveAlbumSongs;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ public class AlbumCatalogueFragment extends Fragment {
|
||||||
albumAdapter.setClickListener((view, position) -> {
|
albumAdapter.setClickListener((view, position) -> {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putParcelable("album_object", albumAdapter.getItem(position));
|
bundle.putParcelable("album_object", albumAdapter.getItem(position));
|
||||||
activity.navController.navigate(R.id.action_libraryFragment_to_albumPageFragment, bundle);
|
activity.navController.navigate(R.id.action_albumCatalogueFragment_to_albumPageFragment, bundle);
|
||||||
});
|
});
|
||||||
bind.albumCatalogueRecyclerView.setAdapter(albumAdapter);
|
bind.albumCatalogueRecyclerView.setAdapter(albumAdapter);
|
||||||
albumCatalogueViewModel.getAlbumList().observe(requireActivity(), albums -> {
|
albumCatalogueViewModel.getAlbumList().observe(requireActivity(), albums -> {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import com.cappielloantonio.play.adapter.RecentMusicAdapter;
|
||||||
import com.cappielloantonio.play.adapter.SongResultSearchAdapter;
|
import com.cappielloantonio.play.adapter.SongResultSearchAdapter;
|
||||||
import com.cappielloantonio.play.databinding.FragmentArtistPageBinding;
|
import com.cappielloantonio.play.databinding.FragmentArtistPageBinding;
|
||||||
import com.cappielloantonio.play.databinding.FragmentHomeBinding;
|
import com.cappielloantonio.play.databinding.FragmentHomeBinding;
|
||||||
|
import com.cappielloantonio.play.model.Song;
|
||||||
import com.cappielloantonio.play.ui.activities.MainActivity;
|
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||||
import com.cappielloantonio.play.viewmodel.ArtistPageViewModel;
|
import com.cappielloantonio.play.viewmodel.ArtistPageViewModel;
|
||||||
import com.cappielloantonio.play.viewmodel.HomeViewModel;
|
import com.cappielloantonio.play.viewmodel.HomeViewModel;
|
||||||
|
|
@ -54,8 +55,17 @@ public class ArtistPageFragment extends Fragment {
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
artistPageViewModel.setArtist(getArguments().getParcelable("artist_object"));
|
artistPageViewModel.setArtist(getArguments().getParcelable("artist_object"));
|
||||||
|
|
||||||
bind.artistNameLabel.setText(artistPageViewModel.getArtist().getName());
|
bind.artistNameLabel.setText(artistPageViewModel.getArtist().getName());
|
||||||
|
|
||||||
|
bind.mostStreamedSongTextViewClickable.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString(Song.BY_ARTIST, Song.BY_ARTIST);
|
||||||
|
bundle.putParcelable("artist_object", artistPageViewModel.getArtist());
|
||||||
|
activity.navController.navigate(R.id.action_artistPageFragment_to_songListPageFragment, bundle);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initTopSongsView() {
|
private void initTopSongsView() {
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,54 @@
|
||||||
package com.cappielloantonio.play.ui.fragment;
|
package com.cappielloantonio.play.ui.fragment;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
|
||||||
|
import com.cappielloantonio.play.App;
|
||||||
|
import com.cappielloantonio.play.R;
|
||||||
import com.cappielloantonio.play.adapter.ArtistCatalogueAdapter;
|
import com.cappielloantonio.play.adapter.ArtistCatalogueAdapter;
|
||||||
import com.cappielloantonio.play.adapter.GenreAdapter;
|
import com.cappielloantonio.play.adapter.GenreAdapter;
|
||||||
import com.cappielloantonio.play.adapter.GenreCatalogueAdapter;
|
import com.cappielloantonio.play.adapter.GenreCatalogueAdapter;
|
||||||
import com.cappielloantonio.play.databinding.FragmentArtistCatalogueBinding;
|
import com.cappielloantonio.play.databinding.FragmentArtistCatalogueBinding;
|
||||||
import com.cappielloantonio.play.databinding.FragmentGenreCatalogueBinding;
|
import com.cappielloantonio.play.databinding.FragmentGenreCatalogueBinding;
|
||||||
import com.cappielloantonio.play.helper.recyclerview.ItemlDecoration;
|
import com.cappielloantonio.play.helper.recyclerview.ItemlDecoration;
|
||||||
|
import com.cappielloantonio.play.interfaces.MediaCallback;
|
||||||
|
import com.cappielloantonio.play.model.Genre;
|
||||||
|
import com.cappielloantonio.play.model.Song;
|
||||||
|
import com.cappielloantonio.play.model.SongGenreCross;
|
||||||
|
import com.cappielloantonio.play.repository.GenreRepository;
|
||||||
|
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||||
|
import com.cappielloantonio.play.util.PreferenceUtil;
|
||||||
|
import com.cappielloantonio.play.util.SyncUtil;
|
||||||
import com.cappielloantonio.play.viewmodel.ArtistCatalogueViewModel;
|
import com.cappielloantonio.play.viewmodel.ArtistCatalogueViewModel;
|
||||||
import com.cappielloantonio.play.viewmodel.GenreCatalogueViewModel;
|
import com.cappielloantonio.play.viewmodel.GenreCatalogueViewModel;
|
||||||
|
import com.google.android.material.snackbar.BaseTransientBottomBar;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class GenreCatalogueFragment extends Fragment {
|
public class GenreCatalogueFragment extends Fragment {
|
||||||
private static final String TAG = "GenreCatalogueFragment";;
|
private static final String TAG = "GenreCatalogueFragment";;
|
||||||
|
|
||||||
private FragmentGenreCatalogueBinding bind;
|
private FragmentGenreCatalogueBinding bind;
|
||||||
|
private MainActivity activity;
|
||||||
private GenreCatalogueViewModel genreCatalogueViewModel;
|
private GenreCatalogueViewModel genreCatalogueViewModel;
|
||||||
|
|
||||||
private GenreCatalogueAdapter genreCatalogueAdapter;
|
private GenreCatalogueAdapter genreCatalogueAdapter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
activity = (MainActivity) getActivity();
|
||||||
|
|
||||||
bind = FragmentGenreCatalogueBinding.inflate(inflater, container, false);
|
bind = FragmentGenreCatalogueBinding.inflate(inflater, container, false);
|
||||||
View view = bind.getRoot();
|
View view = bind.getRoot();
|
||||||
genreCatalogueViewModel = new ViewModelProvider(requireActivity()).get(GenreCatalogueViewModel.class);
|
genreCatalogueViewModel = new ViewModelProvider(requireActivity()).get(GenreCatalogueViewModel.class);
|
||||||
|
|
@ -52,7 +70,15 @@ public class GenreCatalogueFragment extends Fragment {
|
||||||
bind.genreCatalogueRecyclerView.setHasFixedSize(true);
|
bind.genreCatalogueRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
genreCatalogueAdapter = new GenreCatalogueAdapter(requireContext(), new ArrayList<>());
|
genreCatalogueAdapter = new GenreCatalogueAdapter(requireContext(), new ArrayList<>());
|
||||||
genreCatalogueAdapter.setClickListener((view, position) -> Toast.makeText(requireContext(), "Click: " + position, Toast.LENGTH_SHORT).show());
|
genreCatalogueAdapter.setClickListener(new GenreCatalogueAdapter.ItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(View view, int position) {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString(Song.BY_GENRE, Song.BY_GENRE);
|
||||||
|
bundle.putParcelable("genre_object", genreCatalogueAdapter.getItem(position));
|
||||||
|
activity.navController.navigate(R.id.action_genreCatalogueFragment_to_songListPageFragment, bundle);
|
||||||
|
}
|
||||||
|
});
|
||||||
bind.genreCatalogueRecyclerView.setAdapter(genreCatalogueAdapter);
|
bind.genreCatalogueRecyclerView.setAdapter(genreCatalogueAdapter);
|
||||||
|
|
||||||
genreCatalogueViewModel.getGenreList().observe(requireActivity(), genres -> {
|
genreCatalogueViewModel.getGenreList().observe(requireActivity(), genres -> {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
@ -12,9 +11,11 @@ import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
|
import com.cappielloantonio.play.R;
|
||||||
import com.cappielloantonio.play.adapter.DiscoverSongAdapter;
|
import com.cappielloantonio.play.adapter.DiscoverSongAdapter;
|
||||||
import com.cappielloantonio.play.adapter.RecentMusicAdapter;
|
import com.cappielloantonio.play.adapter.RecentMusicAdapter;
|
||||||
import com.cappielloantonio.play.databinding.FragmentHomeBinding;
|
import com.cappielloantonio.play.databinding.FragmentHomeBinding;
|
||||||
|
import com.cappielloantonio.play.model.Song;
|
||||||
import com.cappielloantonio.play.ui.activities.MainActivity;
|
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||||
import com.cappielloantonio.play.util.PreferenceUtil;
|
import com.cappielloantonio.play.util.PreferenceUtil;
|
||||||
import com.cappielloantonio.play.viewmodel.HomeViewModel;
|
import com.cappielloantonio.play.viewmodel.HomeViewModel;
|
||||||
|
|
@ -60,8 +61,27 @@ public class HomeFragment extends Fragment {
|
||||||
private void init() {
|
private void init() {
|
||||||
bind.resyncButton.setOnClickListener(v -> {
|
bind.resyncButton.setOnClickListener(v -> {
|
||||||
PreferenceUtil.getInstance(requireContext()).setSync(false);
|
PreferenceUtil.getInstance(requireContext()).setSync(false);
|
||||||
|
PreferenceUtil.getInstance(requireContext()).setSongGenreSync(false);
|
||||||
activity.goToSync();
|
activity.goToSync();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bind.recentlyAddedTracksTextViewClickable.setOnClickListener(v -> {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString(Song.RECENTLY_ADDED, Song.RECENTLY_ADDED);
|
||||||
|
activity.navController.navigate(R.id.action_homeFragment_to_songListPageFragment, bundle);
|
||||||
|
});
|
||||||
|
|
||||||
|
bind.recentlyPlayedTracksTextViewClickable.setOnClickListener(v -> {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString(Song.RECENTLY_PLAYED, Song.RECENTLY_PLAYED);
|
||||||
|
activity.navController.navigate(R.id.action_homeFragment_to_songListPageFragment, bundle);
|
||||||
|
});
|
||||||
|
|
||||||
|
bind.mostPlayedTracksTextViewClickable.setOnClickListener(v -> {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString(Song.MOST_PLAYED, Song.MOST_PLAYED);
|
||||||
|
activity.navController.navigate(R.id.action_homeFragment_to_songListPageFragment, bundle);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initDiscoverSongSlideView() {
|
private void initDiscoverSongSlideView() {
|
||||||
|
|
|
||||||
|
|
@ -9,24 +9,35 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
|
import com.cappielloantonio.play.App;
|
||||||
import com.cappielloantonio.play.R;
|
import com.cappielloantonio.play.R;
|
||||||
import com.cappielloantonio.play.adapter.AlbumAdapter;
|
import com.cappielloantonio.play.adapter.AlbumAdapter;
|
||||||
import com.cappielloantonio.play.adapter.ArtistAdapter;
|
import com.cappielloantonio.play.adapter.ArtistAdapter;
|
||||||
import com.cappielloantonio.play.adapter.GenreAdapter;
|
import com.cappielloantonio.play.adapter.GenreAdapter;
|
||||||
import com.cappielloantonio.play.adapter.PlaylistAdapter;
|
import com.cappielloantonio.play.adapter.PlaylistAdapter;
|
||||||
import com.cappielloantonio.play.databinding.FragmentLibraryBinding;
|
import com.cappielloantonio.play.databinding.FragmentLibraryBinding;
|
||||||
|
import com.cappielloantonio.play.interfaces.MediaCallback;
|
||||||
import com.cappielloantonio.play.model.Album;
|
import com.cappielloantonio.play.model.Album;
|
||||||
import com.cappielloantonio.play.model.Artist;
|
import com.cappielloantonio.play.model.Artist;
|
||||||
import com.cappielloantonio.play.model.Genre;
|
import com.cappielloantonio.play.model.Genre;
|
||||||
import com.cappielloantonio.play.model.Playlist;
|
import com.cappielloantonio.play.model.Playlist;
|
||||||
|
import com.cappielloantonio.play.model.Song;
|
||||||
|
import com.cappielloantonio.play.model.SongGenreCross;
|
||||||
|
import com.cappielloantonio.play.repository.GenreRepository;
|
||||||
import com.cappielloantonio.play.ui.activities.MainActivity;
|
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||||
|
import com.cappielloantonio.play.util.PreferenceUtil;
|
||||||
|
import com.cappielloantonio.play.util.SyncUtil;
|
||||||
import com.cappielloantonio.play.viewmodel.LibraryViewModel;
|
import com.cappielloantonio.play.viewmodel.LibraryViewModel;
|
||||||
|
import com.google.android.material.snackbar.BaseTransientBottomBar;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -57,6 +68,7 @@ public class LibraryFragment extends Fragment {
|
||||||
initArtistView();
|
initArtistView();
|
||||||
initGenreView();
|
initGenreView();
|
||||||
initPlaylistView();
|
initPlaylistView();
|
||||||
|
initCatalogueSyncCheck();
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +118,15 @@ public class LibraryFragment extends Fragment {
|
||||||
bind.genreRecyclerView.setHasFixedSize(true);
|
bind.genreRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
genreAdapter = new GenreAdapter(requireContext(), new ArrayList<>());
|
genreAdapter = new GenreAdapter(requireContext(), new ArrayList<>());
|
||||||
genreAdapter.setClickListener((view, position) -> Toast.makeText(requireContext(), "Genre: " + position, Toast.LENGTH_SHORT).show());
|
genreAdapter.setClickListener(new GenreAdapter.ItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(View view, int position) {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString(Song.BY_GENRE, Song.BY_GENRE);
|
||||||
|
bundle.putParcelable("genre_object", genreAdapter.getItem(position));
|
||||||
|
activity.navController.navigate(R.id.action_libraryFragment_to_songListPageFragment, bundle);
|
||||||
|
}
|
||||||
|
});
|
||||||
bind.genreRecyclerView.setAdapter(genreAdapter);
|
bind.genreRecyclerView.setAdapter(genreAdapter);
|
||||||
libraryViewModel.getGenreSample().observe(requireActivity(), genres -> genreAdapter.setItems(genres));
|
libraryViewModel.getGenreSample().observe(requireActivity(), genres -> genreAdapter.setItems(genres));
|
||||||
}
|
}
|
||||||
|
|
@ -120,4 +140,39 @@ public class LibraryFragment extends Fragment {
|
||||||
bind.playlistRecyclerView.setAdapter(playlistAdapter);
|
bind.playlistRecyclerView.setAdapter(playlistAdapter);
|
||||||
libraryViewModel.getPlaylistList().observe(requireActivity(), playlists -> playlistAdapter.setItems(playlists));
|
libraryViewModel.getPlaylistList().observe(requireActivity(), playlists -> playlistAdapter.setItems(playlists));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initCatalogueSyncCheck() {
|
||||||
|
if (!PreferenceUtil.getInstance(requireContext()).getSongGenreSync()) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
||||||
|
builder.setMessage("Sync song's genres otherwise nothing will be shown in each genre category")
|
||||||
|
.setTitle("Song's genres not synchronized")
|
||||||
|
.setNegativeButton(R.string.ignore, null)
|
||||||
|
.setPositiveButton("Sync", (dialog, id) -> syncSongsPerGenre(libraryViewModel.getGenreList()))
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncSongsPerGenre(List<Genre> genres) {
|
||||||
|
Snackbar.make(requireView(), "This may take a while...", BaseTransientBottomBar.LENGTH_LONG)
|
||||||
|
.setBackgroundTint(ContextCompat.getColor(requireContext(), R.color.cardColor))
|
||||||
|
.setTextColor(ContextCompat.getColor(requireContext(), R.color.titleTextColor))
|
||||||
|
.show();
|
||||||
|
|
||||||
|
for (Genre genre : genres) {
|
||||||
|
SyncUtil.getSongsPerGenre(requireContext(), new MediaCallback() {
|
||||||
|
@Override
|
||||||
|
public void onError(Exception exception) {
|
||||||
|
Log.e(TAG, "onError: " + exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadMedia(List<?> media) {
|
||||||
|
GenreRepository repository = new GenreRepository(App.getInstance());
|
||||||
|
repository.insertPerGenre((ArrayList<SongGenreCross>) media);
|
||||||
|
}
|
||||||
|
}, genre.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferenceUtil.getInstance(requireContext()).setSongGenreSync(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ public class SearchFragment extends Fragment {
|
||||||
bind.persistentSearchView.collapse();
|
bind.persistentSearchView.collapse();
|
||||||
|
|
||||||
bind.persistentSearchView.setInputQuery(query);
|
bind.persistentSearchView.setInputQuery(query);
|
||||||
performSearch(query);
|
performSearch(query.trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.cappielloantonio.play.ui.fragment;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
|
import com.cappielloantonio.play.adapter.AlbumArtistPageAdapter;
|
||||||
|
import com.cappielloantonio.play.adapter.SongResultSearchAdapter;
|
||||||
|
import com.cappielloantonio.play.databinding.FragmentSongListPageBinding;
|
||||||
|
import com.cappielloantonio.play.model.Song;
|
||||||
|
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||||
|
import com.cappielloantonio.play.viewmodel.SongListPageViewModel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class SongListPageFragment extends Fragment {
|
||||||
|
|
||||||
|
private FragmentSongListPageBinding bind;
|
||||||
|
private MainActivity activity;
|
||||||
|
private SongListPageViewModel songListPageViewModel;
|
||||||
|
|
||||||
|
private SongResultSearchAdapter songResultSearchAdapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
activity = (MainActivity) getActivity();
|
||||||
|
|
||||||
|
bind = FragmentSongListPageBinding.inflate(inflater, container, false);
|
||||||
|
View view = bind.getRoot();
|
||||||
|
songListPageViewModel = new ViewModelProvider(requireActivity()).get(SongListPageViewModel.class);
|
||||||
|
|
||||||
|
init();
|
||||||
|
initSongListView();
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
bind = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
if(getArguments().getString(Song.RECENTLY_PLAYED) != null) {
|
||||||
|
songListPageViewModel.title = Song.RECENTLY_PLAYED;
|
||||||
|
bind.pageTitleLabel.setText(Song.RECENTLY_PLAYED);
|
||||||
|
}
|
||||||
|
else if(getArguments().getString(Song.MOST_PLAYED) != null) {
|
||||||
|
songListPageViewModel.title = Song.MOST_PLAYED;
|
||||||
|
bind.pageTitleLabel.setText(Song.MOST_PLAYED);
|
||||||
|
}
|
||||||
|
else if(getArguments().getString(Song.RECENTLY_ADDED) != null) {
|
||||||
|
songListPageViewModel.title = Song.RECENTLY_ADDED;
|
||||||
|
bind.pageTitleLabel.setText(Song.RECENTLY_ADDED);
|
||||||
|
}
|
||||||
|
else if(getArguments().getString(Song.BY_GENRE) != null) {
|
||||||
|
songListPageViewModel.title = Song.BY_GENRE;
|
||||||
|
songListPageViewModel.genre = getArguments().getParcelable("genre_object");
|
||||||
|
bind.pageTitleLabel.setText(Song.BY_GENRE);
|
||||||
|
}
|
||||||
|
else if(getArguments().getString(Song.BY_ARTIST) != null) {
|
||||||
|
songListPageViewModel.title = Song.BY_ARTIST;
|
||||||
|
songListPageViewModel.artist = getArguments().getParcelable("artist_object");
|
||||||
|
bind.pageTitleLabel.setText(Song.BY_ARTIST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initSongListView() {
|
||||||
|
bind.songListRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||||
|
bind.songListRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
|
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), new ArrayList<>());
|
||||||
|
bind.songListRecyclerView.setAdapter(songResultSearchAdapter);
|
||||||
|
songListPageViewModel.getSongList().observe(requireActivity(), songs -> songResultSearchAdapter.setItems(songs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package com.cappielloantonio.play.ui.fragment;
|
package com.cappielloantonio.play.ui.fragment;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
@ -9,8 +11,11 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.cappielloantonio.play.App;
|
||||||
|
import com.cappielloantonio.play.R;
|
||||||
import com.cappielloantonio.play.databinding.FragmentSyncBinding;
|
import com.cappielloantonio.play.databinding.FragmentSyncBinding;
|
||||||
import com.cappielloantonio.play.interfaces.MediaCallback;
|
import com.cappielloantonio.play.interfaces.MediaCallback;
|
||||||
import com.cappielloantonio.play.model.Album;
|
import com.cappielloantonio.play.model.Album;
|
||||||
|
|
@ -18,6 +23,7 @@ import com.cappielloantonio.play.model.Artist;
|
||||||
import com.cappielloantonio.play.model.Genre;
|
import com.cappielloantonio.play.model.Genre;
|
||||||
import com.cappielloantonio.play.model.Playlist;
|
import com.cappielloantonio.play.model.Playlist;
|
||||||
import com.cappielloantonio.play.model.Song;
|
import com.cappielloantonio.play.model.Song;
|
||||||
|
import com.cappielloantonio.play.model.SongGenreCross;
|
||||||
import com.cappielloantonio.play.repository.AlbumRepository;
|
import com.cappielloantonio.play.repository.AlbumRepository;
|
||||||
import com.cappielloantonio.play.repository.ArtistRepository;
|
import com.cappielloantonio.play.repository.ArtistRepository;
|
||||||
import com.cappielloantonio.play.repository.GenreRepository;
|
import com.cappielloantonio.play.repository.GenreRepository;
|
||||||
|
|
@ -26,6 +32,8 @@ import com.cappielloantonio.play.repository.SongRepository;
|
||||||
import com.cappielloantonio.play.ui.activities.MainActivity;
|
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||||
import com.cappielloantonio.play.util.PreferenceUtil;
|
import com.cappielloantonio.play.util.PreferenceUtil;
|
||||||
import com.cappielloantonio.play.util.SyncUtil;
|
import com.cappielloantonio.play.util.SyncUtil;
|
||||||
|
import com.google.android.material.snackbar.BaseTransientBottomBar;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
import org.jellyfin.apiclient.model.dto.BaseItemDto;
|
import org.jellyfin.apiclient.model.dto.BaseItemDto;
|
||||||
|
|
||||||
|
|
@ -39,6 +47,10 @@ public class SyncFragment extends Fragment {
|
||||||
private FragmentSyncBinding bind;
|
private FragmentSyncBinding bind;
|
||||||
|
|
||||||
private ArrayList<Integer> progressing;
|
private ArrayList<Integer> progressing;
|
||||||
|
private List<Genre> genres;
|
||||||
|
|
||||||
|
private int stepMax = 5;
|
||||||
|
private int increment = 25;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -47,6 +59,8 @@ public class SyncFragment extends Fragment {
|
||||||
|
|
||||||
bind = FragmentSyncBinding.inflate(inflater, container, false);
|
bind = FragmentSyncBinding.inflate(inflater, container, false);
|
||||||
View view = bind.getRoot();
|
View view = bind.getRoot();
|
||||||
|
|
||||||
|
init();
|
||||||
syncLibraries();
|
syncLibraries();
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
|
@ -58,11 +72,12 @@ public class SyncFragment extends Fragment {
|
||||||
bind = null;
|
bind = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showProgressBar() {
|
private void init() {
|
||||||
bind.loadingProgressBar.setVisibility(View.VISIBLE);
|
bind.loadingProgressBar.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncLibraries() {
|
private void syncLibraries() {
|
||||||
|
Log.d(TAG, "syncLibraries");
|
||||||
progressing = new ArrayList<>();
|
progressing = new ArrayList<>();
|
||||||
|
|
||||||
SyncUtil.getLibraries(requireContext(), new MediaCallback() {
|
SyncUtil.getLibraries(requireContext(), new MediaCallback() {
|
||||||
|
|
@ -77,7 +92,7 @@ public class SyncFragment extends Fragment {
|
||||||
|
|
||||||
for (BaseItemDto itemDto : libraries) {
|
for (BaseItemDto itemDto : libraries) {
|
||||||
if (itemDto.getCollectionType().equals("music"))
|
if (itemDto.getCollectionType().equals("music"))
|
||||||
SyncUtil.musicLibrary = itemDto;
|
PreferenceUtil.getInstance(requireContext()).setMusicLibraryID(itemDto.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
startSyncing();
|
startSyncing();
|
||||||
|
|
@ -86,7 +101,6 @@ public class SyncFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startSyncing() {
|
private void startSyncing() {
|
||||||
showProgressBar();
|
|
||||||
syncAlbums();
|
syncAlbums();
|
||||||
syncArtists();
|
syncArtists();
|
||||||
syncGenres();
|
syncGenres();
|
||||||
|
|
@ -95,95 +109,103 @@ public class SyncFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncAlbums() {
|
private void syncAlbums() {
|
||||||
|
Log.d(TAG, "syncAlbums");
|
||||||
SyncUtil.getAlbums(requireContext(), new MediaCallback() {
|
SyncUtil.getAlbums(requireContext(), new MediaCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception exception) {
|
public void onError(Exception exception) {
|
||||||
Log.e(TAG, "onError: " + exception.getMessage());
|
Log.e(TAG, "onError: " + exception.getMessage());
|
||||||
setProgress(false);
|
setProgress(false, "Album");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadMedia(List<?> media) {
|
public void onLoadMedia(List<?> media) {
|
||||||
AlbumRepository repository = new AlbumRepository(activity.getApplication());
|
AlbumRepository repository = new AlbumRepository(activity.getApplication());
|
||||||
repository.insertAll((ArrayList<Album>) media);
|
repository.insertAll((ArrayList<Album>) media);
|
||||||
setProgress(true);
|
setProgress(true, "Album");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncArtists() {
|
private void syncArtists() {
|
||||||
|
Log.d(TAG, "syncArtists");
|
||||||
SyncUtil.getArtists(requireContext(), new MediaCallback() {
|
SyncUtil.getArtists(requireContext(), new MediaCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception exception) {
|
public void onError(Exception exception) {
|
||||||
Log.e(TAG, "onError: " + exception.getMessage());
|
Log.e(TAG, "onError: " + exception.getMessage());
|
||||||
setProgress(false);
|
setProgress(false, "Artist");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadMedia(List<?> media) {
|
public void onLoadMedia(List<?> media) {
|
||||||
ArtistRepository repository = new ArtistRepository(activity.getApplication());
|
ArtistRepository repository = new ArtistRepository(activity.getApplication());
|
||||||
repository.insertAll((ArrayList<Artist>) media);
|
repository.insertAll((ArrayList<Artist>) media);
|
||||||
setProgress(true);
|
setProgress(true, "Artist");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncGenres() {
|
private void syncGenres() {
|
||||||
|
Log.d(TAG, "syncGenres");
|
||||||
SyncUtil.getGenres(requireContext(), new MediaCallback() {
|
SyncUtil.getGenres(requireContext(), new MediaCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception exception) {
|
public void onError(Exception exception) {
|
||||||
Log.e(TAG, "onError: " + exception.getMessage());
|
Log.e(TAG, "onError: " + exception.getMessage());
|
||||||
setProgress(false);
|
setProgress(false, "Genres");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadMedia(List<?> media) {
|
public void onLoadMedia(List<?> media) {
|
||||||
GenreRepository repository = new GenreRepository(activity.getApplication());
|
GenreRepository repository = new GenreRepository(activity.getApplication());
|
||||||
repository.insertAll((ArrayList<Genre>) media);
|
repository.insertAll((ArrayList<Genre>) media);
|
||||||
setProgress(true);
|
setProgress(true, "Genres");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncPlaylist() {
|
private void syncPlaylist() {
|
||||||
|
Log.d(TAG, "syncPlaylist");
|
||||||
SyncUtil.getPlaylists(requireContext(), new MediaCallback() {
|
SyncUtil.getPlaylists(requireContext(), new MediaCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception exception) {
|
public void onError(Exception exception) {
|
||||||
Log.e(TAG, "onError: " + exception.getMessage());
|
Log.e(TAG, "onError: " + exception.getMessage());
|
||||||
setProgress(false);
|
setProgress(false, "PlayList");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadMedia(List<?> media) {
|
public void onLoadMedia(List<?> media) {
|
||||||
PlaylistRepository repository = new PlaylistRepository(activity.getApplication());
|
PlaylistRepository repository = new PlaylistRepository(activity.getApplication());
|
||||||
repository.insertAll((ArrayList<Playlist>) media);
|
repository.insertAll((ArrayList<Playlist>) media);
|
||||||
setProgress(true);
|
setProgress(true, "PlayList");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncSongs() {
|
private void syncSongs() {
|
||||||
|
Log.d(TAG, "syncSongs");
|
||||||
SyncUtil.getSongs(requireContext(), new MediaCallback() {
|
SyncUtil.getSongs(requireContext(), new MediaCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception exception) {
|
public void onError(Exception exception) {
|
||||||
Log.e(TAG, "onError: " + exception.getMessage());
|
Log.e(TAG, "onError: " + exception.getMessage());
|
||||||
setProgress(false);
|
setProgress(false, "Songs");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadMedia(List<?> media) {
|
public void onLoadMedia(List<?> media) {
|
||||||
SongRepository repository = new SongRepository(activity.getApplication());
|
SongRepository repository = new SongRepository(activity.getApplication());
|
||||||
repository.insertAll((ArrayList<Song>) media);
|
repository.insertAll((ArrayList<Song>) media);
|
||||||
setProgress(true);
|
setProgress(true, "Songs");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setProgress(boolean step) {
|
|
||||||
|
private void setProgress(boolean step, String who) {
|
||||||
if (step) {
|
if (step) {
|
||||||
progressing.add(25);
|
Log.d(TAG, "setProgress " + who + ": adding " + increment);
|
||||||
bind.loadingProgressBar.setProgress(bind.loadingProgressBar.getProgress() + 25, true);
|
progressing.add(increment);
|
||||||
|
bind.loadingProgressBar.setProgress(bind.loadingProgressBar.getProgress() + increment, true);
|
||||||
} else {
|
} else {
|
||||||
|
Log.d(TAG, "setProgress" + who + ": adding " + 0);
|
||||||
progressing.add(0);
|
progressing.add(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,12 +213,14 @@ public class SyncFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void countProgress() {
|
private void countProgress() {
|
||||||
if (progressing.size() == 5) {
|
if (progressing.size() == stepMax) {
|
||||||
if (bind.loadingProgressBar.getProgress() == 100)
|
if (bind.loadingProgressBar.getProgress() == 100)
|
||||||
terminate();
|
terminate();
|
||||||
else
|
else
|
||||||
Toast.makeText(requireContext(), "Sync error", Toast.LENGTH_SHORT).show();
|
Toast.makeText(requireContext(), "Sync error", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "countProgress: SIZE: " + progressing.size() + " - SUM: " + bind.loadingProgressBar.getProgress());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void terminate() {
|
private void terminate() {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ public class PreferenceUtil {
|
||||||
public static final String SERVER = "server";
|
public static final String SERVER = "server";
|
||||||
public static final String USER = "user";
|
public static final String USER = "user";
|
||||||
public static final String TOKEN = "token";
|
public static final String TOKEN = "token";
|
||||||
|
public static final String MUSIC_LIBRARY_ID = "music_library_id";
|
||||||
|
|
||||||
public static final String SYNC = "sync";
|
public static final String SYNC = "sync";
|
||||||
|
public static final String SONG_GENRE_SYNC = "song_genre_sync";
|
||||||
|
|
||||||
public static final String HOST_URL = "host";
|
public static final String HOST_URL = "host";
|
||||||
public static final String IMAGE_CACHE_SIZE = "image_cache_size";
|
public static final String IMAGE_CACHE_SIZE = "image_cache_size";
|
||||||
|
|
@ -75,6 +77,26 @@ public class PreferenceUtil {
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getSongGenreSync() {
|
||||||
|
return mPreferences.getBoolean(SONG_GENRE_SYNC, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSongGenreSync(Boolean sync) {
|
||||||
|
final SharedPreferences.Editor editor = mPreferences.edit();
|
||||||
|
editor.putBoolean(SONG_GENRE_SYNC, sync);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMusicLibraryID() {
|
||||||
|
return mPreferences.getString(MUSIC_LIBRARY_ID, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMusicLibraryID(String musicLibraryID) {
|
||||||
|
final SharedPreferences.Editor editor = mPreferences.edit();
|
||||||
|
editor.putString(MUSIC_LIBRARY_ID, musicLibraryID);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
public final String getHostUrl() {
|
public final String getHostUrl() {
|
||||||
return mPreferences.getString(HOST_URL, "undefined");
|
return mPreferences.getString(HOST_URL, "undefined");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import com.cappielloantonio.play.model.Artist;
|
||||||
import com.cappielloantonio.play.model.Genre;
|
import com.cappielloantonio.play.model.Genre;
|
||||||
import com.cappielloantonio.play.model.Playlist;
|
import com.cappielloantonio.play.model.Playlist;
|
||||||
import com.cappielloantonio.play.model.Song;
|
import com.cappielloantonio.play.model.Song;
|
||||||
|
import com.cappielloantonio.play.model.SongGenreCross;
|
||||||
|
|
||||||
import org.jellyfin.apiclient.interaction.Response;
|
import org.jellyfin.apiclient.interaction.Response;
|
||||||
import org.jellyfin.apiclient.model.dto.BaseItemDto;
|
import org.jellyfin.apiclient.model.dto.BaseItemDto;
|
||||||
|
|
@ -23,8 +24,6 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SyncUtil {
|
public class SyncUtil {
|
||||||
public static BaseItemDto musicLibrary;
|
|
||||||
|
|
||||||
public static void getLibraries(Context context, MediaCallback callback) {
|
public static void getLibraries(Context context, MediaCallback callback) {
|
||||||
String id = App.getApiClientInstance(context).getCurrentUserId();
|
String id = App.getApiClientInstance(context).getCurrentUserId();
|
||||||
|
|
||||||
|
|
@ -51,7 +50,7 @@ public class SyncUtil {
|
||||||
query.setFields(new ItemFields[]{ItemFields.MediaSources});
|
query.setFields(new ItemFields[]{ItemFields.MediaSources});
|
||||||
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
||||||
query.setRecursive(true);
|
query.setRecursive(true);
|
||||||
query.setParentId(musicLibrary.getId());
|
query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID());
|
||||||
|
|
||||||
App.getApiClientInstance(context).GetItemsAsync(query, new Response<ItemsResult>() {
|
App.getApiClientInstance(context).GetItemsAsync(query, new Response<ItemsResult>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -78,7 +77,7 @@ public class SyncUtil {
|
||||||
query.setIncludeItemTypes(new String[]{"MusicAlbum"});
|
query.setIncludeItemTypes(new String[]{"MusicAlbum"});
|
||||||
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
||||||
query.setRecursive(true);
|
query.setRecursive(true);
|
||||||
query.setParentId(musicLibrary.getId());
|
query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID());
|
||||||
|
|
||||||
App.getApiClientInstance(context).GetItemsAsync(query, new Response<ItemsResult>() {
|
App.getApiClientInstance(context).GetItemsAsync(query, new Response<ItemsResult>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -104,7 +103,7 @@ public class SyncUtil {
|
||||||
query.setFields(new ItemFields[]{ItemFields.Genres});
|
query.setFields(new ItemFields[]{ItemFields.Genres});
|
||||||
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
||||||
query.setRecursive(true);
|
query.setRecursive(true);
|
||||||
query.setParentId(musicLibrary.getId());
|
query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID());
|
||||||
|
|
||||||
App.getApiClientInstance(context).GetAlbumArtistsAsync(query, new Response<ItemsResult>() {
|
App.getApiClientInstance(context).GetAlbumArtistsAsync(query, new Response<ItemsResult>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -130,7 +129,7 @@ public class SyncUtil {
|
||||||
query.setIncludeItemTypes(new String[]{"Playlist"});
|
query.setIncludeItemTypes(new String[]{"Playlist"});
|
||||||
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
||||||
query.setRecursive(true);
|
query.setRecursive(true);
|
||||||
query.setParentId(musicLibrary.getId());
|
query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID());
|
||||||
|
|
||||||
App.getApiClientInstance(context).GetItemsAsync(query, new Response<ItemsResult>() {
|
App.getApiClientInstance(context).GetItemsAsync(query, new Response<ItemsResult>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -155,7 +154,7 @@ public class SyncUtil {
|
||||||
|
|
||||||
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
||||||
query.setRecursive(true);
|
query.setRecursive(true);
|
||||||
query.setParentId(musicLibrary.getId());
|
query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID());
|
||||||
|
|
||||||
App.getApiClientInstance(context).GetGenresAsync(query, new Response<ItemsResult>() {
|
App.getApiClientInstance(context).GetGenresAsync(query, new Response<ItemsResult>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -174,4 +173,33 @@ public class SyncUtil {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void getSongsPerGenre(Context context, MediaCallback callback, String genreId) {
|
||||||
|
ItemQuery query = new ItemQuery();
|
||||||
|
|
||||||
|
query.setIncludeItemTypes(new String[]{"Audio"});
|
||||||
|
query.setFields(new ItemFields[]{ItemFields.MediaSources});
|
||||||
|
query.setUserId(App.getApiClientInstance(context).getCurrentUserId());
|
||||||
|
query.setRecursive(true);
|
||||||
|
query.setParentId(PreferenceUtil.getInstance(context).getMusicLibraryID());
|
||||||
|
query.setGenreIds(new String[]{genreId});
|
||||||
|
|
||||||
|
App.getApiClientInstance(context).GetItemsAsync(query, new Response<ItemsResult>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(ItemsResult result) {
|
||||||
|
ArrayList<SongGenreCross> crosses = new ArrayList<>();
|
||||||
|
|
||||||
|
for (BaseItemDto itemDto : result.getItems()) {
|
||||||
|
crosses.add(new SongGenreCross(itemDto.getId(), genreId));
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.onLoadMedia(crosses);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception exception) {
|
||||||
|
callback.onError(exception);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ public class ArtistPageViewModel extends AndroidViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Song>> getArtistTopSongList() {
|
public LiveData<List<Song>> getArtistTopSongList() {
|
||||||
songList = songRepository.getArtistListLiveTopSong(artist.id);
|
songList = songRepository.getArtistListLiveTopSongSample(artist.id);
|
||||||
return songList;
|
return songList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,8 @@ public class GenreCatalogueViewModel extends AndroidViewModel {
|
||||||
genreList = genreRepository.getListLiveGenres();
|
genreList = genreRepository.getListLiveGenres();
|
||||||
return genreList;
|
return genreList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Genre> getGenres() {
|
||||||
|
return genreRepository.getListGenre();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,17 @@ public class HomeViewModel extends AndroidViewModel {
|
||||||
songRepository = new SongRepository(application);
|
songRepository = new SongRepository(application);
|
||||||
|
|
||||||
dicoverSongSample = songRepository.getRandomSample(5);
|
dicoverSongSample = songRepository.getRandomSample(5);
|
||||||
recentlyPlayedSongSample = songRepository.getListLiveRecentlyPlayedSampleSong();
|
recentlyPlayedSongSample = songRepository.getListLiveRecentlyPlayedSampleSong(20);
|
||||||
recentlyAddedSongSample = songRepository.getListLiveRecentlyAddedSampleSong();
|
recentlyAddedSongSample = songRepository.getListLiveRecentlyAddedSampleSong(20);
|
||||||
mostPlayedSongSample = songRepository.getListLiveMostPlayedSampleSong();
|
mostPlayedSongSample = songRepository.getListLiveMostPlayedSampleSong(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<Song> getDiscoverSongList() {
|
public List<Song> getDiscoverSongList() {
|
||||||
|
if(dicoverSongSample.isEmpty()) {
|
||||||
|
dicoverSongSample = songRepository.getRandomSample(5);
|
||||||
|
}
|
||||||
|
|
||||||
return dicoverSongSample;
|
return dicoverSongSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,16 +46,15 @@ public class LibraryViewModel extends AndroidViewModel {
|
||||||
sampleGenres = genreRepository.getListLiveSampleGenre();
|
sampleGenres = genreRepository.getListLiveSampleGenre();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Genre>> getGenreList() {
|
|
||||||
allGenres = genreRepository.getListLiveGenres();
|
|
||||||
return allGenres;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LiveData<List<Playlist>> getPlaylistList() {
|
public LiveData<List<Playlist>> getPlaylistList() {
|
||||||
allPlaylist = playlistRepository.getListLivePlaylists();
|
allPlaylist = playlistRepository.getListLivePlaylists();
|
||||||
return allPlaylist;
|
return allPlaylist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Genre> getGenreList() {
|
||||||
|
return genreRepository.getListGenre();
|
||||||
|
}
|
||||||
|
|
||||||
public LiveData<List<Album>> getAlbumSample() {
|
public LiveData<List<Album>> getAlbumSample() {
|
||||||
return sampleAlbum;
|
return sampleAlbum;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.cappielloantonio.play.viewmodel;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
|
import com.cappielloantonio.play.model.Artist;
|
||||||
|
import com.cappielloantonio.play.model.Genre;
|
||||||
|
import com.cappielloantonio.play.model.Song;
|
||||||
|
import com.cappielloantonio.play.repository.SongRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SongListPageViewModel extends AndroidViewModel {
|
||||||
|
private SongRepository songRepository;
|
||||||
|
|
||||||
|
private LiveData<List<Song>> songList;
|
||||||
|
|
||||||
|
public String title;
|
||||||
|
public Genre genre;
|
||||||
|
public Artist artist;
|
||||||
|
|
||||||
|
public SongListPageViewModel(@NonNull Application application) {
|
||||||
|
super(application);
|
||||||
|
|
||||||
|
songRepository = new SongRepository(application);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<List<Song>> getSongList() {
|
||||||
|
switch (title) {
|
||||||
|
case Song.RECENTLY_PLAYED:
|
||||||
|
songList = songRepository.getListLiveRecentlyPlayedSampleSong(100);
|
||||||
|
break;
|
||||||
|
case Song.MOST_PLAYED:
|
||||||
|
songList = songRepository.getListLiveMostPlayedSampleSong(100);
|
||||||
|
break;
|
||||||
|
case Song.RECENTLY_ADDED:
|
||||||
|
songList = songRepository.getListLiveRecentlyAddedSampleSong(100);
|
||||||
|
break;
|
||||||
|
case Song.BY_GENRE:
|
||||||
|
songList = songRepository.getListLiveSongByGenre(genre.getId());
|
||||||
|
break;
|
||||||
|
case Song.BY_ARTIST:
|
||||||
|
songList = songRepository.getArtistListLiveTopSong(artist.getId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return songList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/album_catalogue_text_view_clickable"
|
android:id="@+id/most_streamed_song_text_view_clickable"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/open_sans_font_family"
|
android:fontFamily="@font/open_sans_font_family"
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
<androidx.viewpager.widget.ViewPager
|
<androidx.viewpager.widget.ViewPager
|
||||||
android:id="@+id/discover_song_view_pager"
|
android:id="@+id/discover_song_view_pager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="152dp"
|
android:layout_height="172dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
|
|
@ -41,6 +41,18 @@
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
android:paddingBottom="8dp" />
|
android:paddingBottom="8dp" />
|
||||||
|
|
||||||
|
<!-- <androidx.recyclerview.widget.RecyclerView-->
|
||||||
|
<!-- android:id="@+id/discover_song_recycler_view"-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="172dp"-->
|
||||||
|
<!-- android:layout_marginTop="8dp"-->
|
||||||
|
<!-- android:layout_marginBottom="8dp"-->
|
||||||
|
<!-- android:clipToPadding="false"-->
|
||||||
|
<!-- android:paddingStart="16dp"-->
|
||||||
|
<!-- android:paddingTop="8dp"-->
|
||||||
|
<!-- android:paddingEnd="16dp"-->
|
||||||
|
<!-- android:paddingBottom="8dp" />-->
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Recently added tracks -->
|
<!-- Recently added tracks -->
|
||||||
|
|
@ -73,6 +85,7 @@
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/recently_added_tracks_text_view_clickable"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/open_sans_font_family"
|
android:fontFamily="@font/open_sans_font_family"
|
||||||
|
|
@ -128,6 +141,7 @@
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/recently_played_tracks_text_view_clickable"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/open_sans_font_family"
|
android:fontFamily="@font/open_sans_font_family"
|
||||||
|
|
@ -183,6 +197,7 @@
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/most_played_tracks_text_view_clickable"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/open_sans_font_family"
|
android:fontFamily="@font/open_sans_font_family"
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,6 @@
|
||||||
android:text="See all"
|
android:text="See all"
|
||||||
android:textColor="@color/subtitleTextColor"
|
android:textColor="@color/subtitleTextColor"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
|
|
||||||
|
|
@ -90,19 +90,6 @@
|
||||||
android:paddingEnd="8dp" />
|
android:paddingEnd="8dp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 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
|
<androidx.core.widget.NestedScrollView
|
||||||
android:id="@+id/search_result_nested_scroll_view"
|
android:id="@+id/search_result_nested_scroll_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -116,6 +103,19 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- 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" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
||||||
38
app/src/main/res/layout/fragment_song_list_page.xml
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/page_title_label"
|
||||||
|
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="@string/label_placeholder"
|
||||||
|
android:textColor="@color/titleTextColor"
|
||||||
|
android:textSize="22sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/song_list_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>
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/artist_discover_song_label"
|
android:id="@+id/album_discover_song_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/title_discover_song_label"
|
android:layout_below="@id/title_discover_song_label"
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
|
@ -63,9 +63,10 @@
|
||||||
tools:layout="@layout/fragment_home">
|
tools:layout="@layout/fragment_home">
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_homeFragment_to_syncFragment"
|
android:id="@+id/action_homeFragment_to_syncFragment"
|
||||||
app:destination="@id/syncFragment"
|
app:destination="@id/syncFragment" />
|
||||||
app:popUpTo="@id/homeFragment"
|
<action
|
||||||
app:popUpToInclusive="true" />
|
android:id="@+id/action_homeFragment_to_songListPageFragment"
|
||||||
|
app:destination="@id/songListPageFragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/libraryFragment"
|
android:id="@+id/libraryFragment"
|
||||||
|
|
@ -87,6 +88,9 @@
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_libraryFragment_to_albumPageFragment"
|
android:id="@+id/action_libraryFragment_to_albumPageFragment"
|
||||||
app:destination="@id/albumPageFragment" />
|
app:destination="@id/albumPageFragment" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_libraryFragment_to_songListPageFragment"
|
||||||
|
app:destination="@id/songListPageFragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/settingsFragment"
|
android:id="@+id/settingsFragment"
|
||||||
|
|
@ -135,7 +139,11 @@
|
||||||
android:id="@+id/genreCatalogueFragment"
|
android:id="@+id/genreCatalogueFragment"
|
||||||
android:name="com.cappielloantonio.play.ui.fragment.GenreCatalogueFragment"
|
android:name="com.cappielloantonio.play.ui.fragment.GenreCatalogueFragment"
|
||||||
android:label="GenreCatalogueFragment"
|
android:label="GenreCatalogueFragment"
|
||||||
tools:layout="@layout/fragment_genre_catalogue"/>
|
tools:layout="@layout/fragment_genre_catalogue">
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_genreCatalogueFragment_to_songListPageFragment"
|
||||||
|
app:destination="@id/songListPageFragment" />
|
||||||
|
</fragment>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/artistPageFragment"
|
android:id="@+id/artistPageFragment"
|
||||||
|
|
@ -145,10 +153,18 @@
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_artistPageFragment_to_albumPageFragment"
|
android:id="@+id/action_artistPageFragment_to_albumPageFragment"
|
||||||
app:destination="@id/albumPageFragment" />
|
app:destination="@id/albumPageFragment" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_artistPageFragment_to_songListPageFragment"
|
||||||
|
app:destination="@id/songListPageFragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/albumPageFragment"
|
android:id="@+id/albumPageFragment"
|
||||||
android:name="com.cappielloantonio.play.ui.fragment.AlbumPageFragment"
|
android:name="com.cappielloantonio.play.ui.fragment.AlbumPageFragment"
|
||||||
android:label="AlbumPageFragment"
|
android:label="AlbumPageFragment"
|
||||||
tools:layout="@layout/fragment_album_page"/>
|
tools:layout="@layout/fragment_album_page"/>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/songListPageFragment"
|
||||||
|
android:name="com.cappielloantonio.play.ui.fragment.SongListPageFragment"
|
||||||
|
android:label="SongListPageFragment"
|
||||||
|
tools:layout="@layout/fragment_song_list_page"/>
|
||||||
</navigation>
|
</navigation>
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
<string name="action_settings">Settings</string>
|
<string name="action_settings">Settings</string>
|
||||||
<string name="general_header">General</string>
|
<string name="general_header">General</string>
|
||||||
<string name="search_hint">Search title, artists or albums</string>
|
<string name="search_hint">Search</string>
|
||||||
<string name="menu_home">Home</string>
|
<string name="menu_home">Home</string>
|
||||||
<string name="settings_menu_label">Settings</string>
|
<string name="settings_menu_label">Settings</string>
|
||||||
<string name="download_label">Download</string>
|
<string name="download_label">Download</string>
|
||||||
|
|
|
||||||