mirror of
https://github.com/antebudimir/tempus.git
synced 2026-01-01 18:03:33 +00:00
Add experimental bottom sheet player
This commit is contained in:
parent
9af0afa441
commit
f837bb14e2
65 changed files with 1570 additions and 547 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.ImageView;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.cappielloantonio.play.App;
|
||||
import com.cappielloantonio.play.R;
|
||||
import com.cappielloantonio.play.glide.CustomGlideRequest;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
import com.cappielloantonio.play.repository.SongRepository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PlayerNowPlayingSongAdapter extends RecyclerView.Adapter<PlayerNowPlayingSongAdapter.ViewHolder> {
|
||||
private static final String TAG = "DiscoverSongAdapter";
|
||||
|
||||
private List<Song> songs;
|
||||
private LayoutInflater inflater;
|
||||
private Context context;
|
||||
|
||||
public PlayerNowPlayingSongAdapter(Context context) {
|
||||
this.context = context;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
this.songs = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = inflater.inflate(R.layout.item_player_now_playing_song, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
Song song = songs.get(position);
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(context, song.getPrimary(), song.getPrimary(), CustomGlideRequest.PRIMARY, CustomGlideRequest.TOP_QUALITY)
|
||||
.build()
|
||||
.into(holder.cover);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return songs.size();
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
ImageView cover;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
|
||||
cover = itemView.findViewById(R.id.discover_song_cover_image_view);
|
||||
|
||||
itemView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
SongRepository songRepository = new SongRepository(App.getInstance());
|
||||
songRepository.increasePlayCount(songs.get(getAdapterPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
public void setItems(List<Song> songs) {
|
||||
this.songs = songs;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
package com.cappielloantonio.play.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.cappielloantonio.play.App;
|
||||
import com.cappielloantonio.play.R;
|
||||
import com.cappielloantonio.play.glide.CustomGlideRequest;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
import com.cappielloantonio.play.repository.QueueRepository;
|
||||
import com.cappielloantonio.play.repository.SongRepository;
|
||||
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Adapter per i brani ritrovati nella ricerca
|
||||
*/
|
||||
public class PlayerSongQueueAdapter extends RecyclerView.Adapter<PlayerSongQueueAdapter.ViewHolder> {
|
||||
private static final String TAG = "SongResultSearchAdapter";
|
||||
|
||||
private List<Song> songs;
|
||||
private LayoutInflater mInflater;
|
||||
private MainActivity mainActivity;
|
||||
private Context context;
|
||||
private FragmentManager fragmentManager;
|
||||
|
||||
public PlayerSongQueueAdapter(MainActivity mainActivity, Context context, FragmentManager fragmentManager) {
|
||||
this.mainActivity = mainActivity;
|
||||
this.context = context;
|
||||
this.fragmentManager = fragmentManager;
|
||||
this.mInflater = LayoutInflater.from(context);
|
||||
this.songs = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = mInflater.inflate(R.layout.item_player_queue_song, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
Song song = songs.get(position);
|
||||
|
||||
holder.songTitle.setText(song.getTitle());
|
||||
holder.songArtist.setText(song.getArtistName());
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(context, song.getPrimary(), song.getBlurHash(), CustomGlideRequest.PRIMARY, CustomGlideRequest.TOP_QUALITY)
|
||||
.build()
|
||||
.into(holder.cover);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return songs.size();
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
TextView songTitle;
|
||||
TextView songArtist;
|
||||
ImageView cover;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
|
||||
songTitle = itemView.findViewById(R.id.queue_song_title_text_view);
|
||||
songArtist = itemView.findViewById(R.id.queue_song_artist_text_view);
|
||||
cover = itemView.findViewById(R.id.queue_song_cover_image_view);
|
||||
|
||||
itemView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
SongRepository songRepository = new SongRepository(App.getInstance());
|
||||
QueueRepository queueRepository = new QueueRepository(App.getInstance());
|
||||
|
||||
songRepository.increasePlayCount(songs.get(getAdapterPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
public void setItems(List<Song> songs) {
|
||||
this.songs = songs;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public Song getItem(int id) {
|
||||
return songs.get(id);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,9 @@ import com.cappielloantonio.play.App;
|
|||
import com.cappielloantonio.play.R;
|
||||
import com.cappielloantonio.play.glide.CustomGlideRequest;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
import com.cappielloantonio.play.repository.QueueRepository;
|
||||
import com.cappielloantonio.play.repository.SongRepository;
|
||||
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -29,10 +31,12 @@ public class RecentMusicAdapter extends RecyclerView.Adapter<RecentMusicAdapter.
|
|||
|
||||
private List<Song> songs;
|
||||
private LayoutInflater mInflater;
|
||||
private MainActivity mainActivity;
|
||||
private Context context;
|
||||
private FragmentManager fragmentManager;
|
||||
|
||||
public RecentMusicAdapter(Context context, FragmentManager fragmentManager) {
|
||||
public RecentMusicAdapter(MainActivity mainActivity, Context context, FragmentManager fragmentManager) {
|
||||
this.mainActivity = mainActivity;
|
||||
this.context = context;
|
||||
this.fragmentManager = fragmentManager;
|
||||
this.mInflater = LayoutInflater.from(context);
|
||||
|
|
@ -82,7 +86,12 @@ public class RecentMusicAdapter extends RecyclerView.Adapter<RecentMusicAdapter.
|
|||
@Override
|
||||
public void onClick(View view) {
|
||||
SongRepository songRepository = new SongRepository(App.getInstance());
|
||||
QueueRepository queueRepository = new QueueRepository(App.getInstance());
|
||||
|
||||
songRepository.increasePlayCount(songs.get(getAdapterPosition()));
|
||||
queueRepository.insertAllAndStartNew(songs.subList(getAdapterPosition(), songs.size()));
|
||||
|
||||
mainActivity.isBottomSheetInPeek(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@ import com.cappielloantonio.play.App;
|
|||
import com.cappielloantonio.play.R;
|
||||
import com.cappielloantonio.play.glide.CustomGlideRequest;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
import com.cappielloantonio.play.repository.QueueRepository;
|
||||
import com.cappielloantonio.play.repository.SongRepository;
|
||||
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||
import com.cappielloantonio.play.util.Util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -30,10 +32,12 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter<SongResultSear
|
|||
|
||||
private List<Song> songs;
|
||||
private LayoutInflater mInflater;
|
||||
private MainActivity mainActivity;
|
||||
private Context context;
|
||||
private FragmentManager fragmentManager;
|
||||
|
||||
public SongResultSearchAdapter(Context context, FragmentManager fragmentManager) {
|
||||
public SongResultSearchAdapter(MainActivity mainActivity, Context context, FragmentManager fragmentManager) {
|
||||
this.mainActivity = mainActivity;
|
||||
this.context = context;
|
||||
this.fragmentManager = fragmentManager;
|
||||
this.mInflater = LayoutInflater.from(context);
|
||||
|
|
@ -86,7 +90,12 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter<SongResultSear
|
|||
@Override
|
||||
public void onClick(View view) {
|
||||
SongRepository songRepository = new SongRepository(App.getInstance());
|
||||
QueueRepository queueRepository = new QueueRepository(App.getInstance());
|
||||
|
||||
songRepository.increasePlayCount(songs.get(getAdapterPosition()));
|
||||
queueRepository.insertAllAndStartNew(songs.subList(getAdapterPosition(), songs.size()));
|
||||
|
||||
mainActivity.isBottomSheetInPeek(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -106,5 +115,4 @@ public class SongResultSearchAdapter extends RecyclerView.Adapter<SongResultSear
|
|||
public Song getItem(int id) {
|
||||
return songs.get(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ public class ConnectivityStatusBroadcastReceiver extends BroadcastReceiver {
|
|||
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
|
||||
|
||||
if (noConnectivity) {
|
||||
activity.activityMainBinding.offlineModeLinearLayout.setVisibility(View.VISIBLE);
|
||||
activity.bind.offlineModeTextView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
activity.activityMainBinding.offlineModeLinearLayout.setVisibility(View.GONE);
|
||||
activity.bind.offlineModeTextView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.cappielloantonio.play.database.dao.AlbumDao;
|
|||
import com.cappielloantonio.play.database.dao.ArtistDao;
|
||||
import com.cappielloantonio.play.database.dao.GenreDao;
|
||||
import com.cappielloantonio.play.database.dao.PlaylistDao;
|
||||
import com.cappielloantonio.play.database.dao.QueueDao;
|
||||
import com.cappielloantonio.play.database.dao.RecentSearchDao;
|
||||
import com.cappielloantonio.play.database.dao.SongDao;
|
||||
import com.cappielloantonio.play.database.dao.SongGenreCrossDao;
|
||||
|
|
@ -17,11 +18,12 @@ import com.cappielloantonio.play.model.Album;
|
|||
import com.cappielloantonio.play.model.Artist;
|
||||
import com.cappielloantonio.play.model.Genre;
|
||||
import com.cappielloantonio.play.model.Playlist;
|
||||
import com.cappielloantonio.play.model.Queue;
|
||||
import com.cappielloantonio.play.model.RecentSearch;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
import com.cappielloantonio.play.model.SongGenreCross;
|
||||
|
||||
@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class, SongGenreCross.class}, version = 5, exportSchema = false)
|
||||
@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class, SongGenreCross.class, Queue.class}, version = 6, exportSchema = false)
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
private static final String TAG = "AppDatabase";
|
||||
|
||||
|
|
@ -51,4 +53,6 @@ public abstract class AppDatabase extends RoomDatabase {
|
|||
public abstract RecentSearchDao recentSearchDao();
|
||||
|
||||
public abstract SongGenreCrossDao songGenreCrossDao();
|
||||
|
||||
public abstract QueueDao queueDao();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
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 com.cappielloantonio.play.model.Queue;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Dao
|
||||
public interface QueueDao {
|
||||
@Query("SELECT * FROM song JOIN queue ON song.id = queue.song_id")
|
||||
LiveData<List<Song>> getAll();
|
||||
|
||||
@Query("SELECT * FROM song JOIN queue ON song.id = queue.song_id")
|
||||
List<Song> getAllSimple();
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
void insert(Queue songQueueObject);
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
void insertAll(List<Queue> songQueueObject);
|
||||
|
||||
@Delete
|
||||
void delete(Queue songQueueObject);
|
||||
|
||||
@Query("DELETE FROM queue")
|
||||
void deleteAll();
|
||||
|
||||
@Query("SELECT COUNT(*) FROM queue;")
|
||||
int count();
|
||||
}
|
||||
44
app/src/main/java/com/cappielloantonio/play/model/Queue.java
Normal file
44
app/src/main/java/com/cappielloantonio/play/model/Queue.java
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package com.cappielloantonio.play.model;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
@Entity(tableName = "queue")
|
||||
public class Queue {
|
||||
@NonNull
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = "id")
|
||||
private int id;
|
||||
|
||||
@ColumnInfo(name = "song_id")
|
||||
private String songID;
|
||||
|
||||
public Queue(@NonNull int id, String songID) {
|
||||
this.id = id;
|
||||
this.songID = songID;
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public Queue(String songID) {
|
||||
this.songID = songID;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
package com.cappielloantonio.play.repository;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
|
||||
import com.cappielloantonio.play.database.AppDatabase;
|
||||
import com.cappielloantonio.play.database.dao.QueueDao;
|
||||
import com.cappielloantonio.play.model.Queue;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
import com.cappielloantonio.play.util.QueueUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class QueueRepository {
|
||||
private static final String TAG = "QueueRepository";
|
||||
|
||||
private QueueDao queueDao;
|
||||
private LiveData<List<Song>> listLiveQueue;
|
||||
|
||||
public QueueRepository(Application application) {
|
||||
AppDatabase database = AppDatabase.getInstance(application);
|
||||
queueDao = database.queueDao();
|
||||
}
|
||||
|
||||
public LiveData<List<Song>> getLiveQueue() {
|
||||
listLiveQueue = queueDao.getAll();
|
||||
return listLiveQueue;
|
||||
}
|
||||
|
||||
public List<Song> getSongs() {
|
||||
List<Song> songs = new ArrayList<>();
|
||||
|
||||
GetSongsThreadSafe getSongs = new GetSongsThreadSafe(queueDao);
|
||||
Thread thread = new Thread(getSongs);
|
||||
thread.start();
|
||||
|
||||
try {
|
||||
thread.join();
|
||||
songs = getSongs.getSongs();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
public void insert(Song song) {
|
||||
InsertThreadSafe insert = new InsertThreadSafe(queueDao, song);
|
||||
Thread thread = new Thread(insert);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void insertAll(List<Song> songs) {
|
||||
InsertAllThreadSafe insertAll = new InsertAllThreadSafe(queueDao, songs);
|
||||
Thread thread = new Thread(insertAll);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void insertAllAndStartNew(List<Song> songs) {
|
||||
try {
|
||||
final Thread delete = new Thread(new DeleteAllThreadSafe(queueDao));
|
||||
final Thread insertAll = new Thread(new InsertAllThreadSafe(queueDao, songs));
|
||||
|
||||
delete.start();
|
||||
delete.join();
|
||||
insertAll.start();
|
||||
insertAll.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(Queue queueElement) {
|
||||
DeleteThreadSafe delete = new DeleteThreadSafe(queueDao, queueElement);
|
||||
Thread thread = new Thread(delete);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void deleteAll() {
|
||||
DeleteAllThreadSafe delete = new DeleteAllThreadSafe(queueDao);
|
||||
Thread thread = new Thread(delete);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public int count() {
|
||||
int count = 0;
|
||||
|
||||
CountThreadSafe countThread = new CountThreadSafe(queueDao);
|
||||
Thread thread = new Thread(countThread);
|
||||
thread.start();
|
||||
|
||||
try {
|
||||
thread.join();
|
||||
count = countThread.getCount();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private static class InsertThreadSafe implements Runnable {
|
||||
private QueueDao queueDao;
|
||||
private Song song;
|
||||
|
||||
public InsertThreadSafe(QueueDao queueDao, Song song) {
|
||||
this.queueDao = queueDao;
|
||||
this.song = song;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
queueDao.insert(QueueUtil.getQueueElementFromSong(song));
|
||||
}
|
||||
}
|
||||
|
||||
private static class InsertAllThreadSafe implements Runnable {
|
||||
private QueueDao queueDao;
|
||||
private List<Song> songs;
|
||||
|
||||
public InsertAllThreadSafe(QueueDao queueDao, List<Song> songs) {
|
||||
this.queueDao = queueDao;
|
||||
this.songs = songs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
queueDao.insertAll(QueueUtil.getQueueElementsFromSongs(songs));
|
||||
}
|
||||
}
|
||||
|
||||
private static class DeleteThreadSafe implements Runnable {
|
||||
private QueueDao queueDao;
|
||||
private Queue queueElement;
|
||||
|
||||
public DeleteThreadSafe(QueueDao queueDao, Queue queueElement) {
|
||||
this.queueDao = queueDao;
|
||||
this.queueElement = queueElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
queueDao.delete(queueElement);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DeleteAllThreadSafe implements Runnable {
|
||||
private QueueDao queueDao;
|
||||
|
||||
public DeleteAllThreadSafe(QueueDao queueDao) {
|
||||
this.queueDao = queueDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
queueDao.deleteAll();
|
||||
}
|
||||
}
|
||||
|
||||
private static class CountThreadSafe implements Runnable {
|
||||
private QueueDao queueDao;
|
||||
private int count = 0;
|
||||
|
||||
public CountThreadSafe(QueueDao queueDao) {
|
||||
this.queueDao = queueDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
count = queueDao.count();
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
private static class GetSongsThreadSafe implements Runnable {
|
||||
private QueueDao queueDao;
|
||||
private List<Song> songs;
|
||||
|
||||
public GetSongsThreadSafe(QueueDao queueDao) {
|
||||
this.queueDao = queueDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
songs = queueDao.getAllSimple();
|
||||
}
|
||||
|
||||
public List<Song> getSongs() {
|
||||
return songs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,12 @@ package com.cappielloantonio.play.ui.activities;
|
|||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.navigation.ui.NavigationUI;
|
||||
|
|
@ -15,9 +18,12 @@ import com.cappielloantonio.play.R;
|
|||
import com.cappielloantonio.play.broadcast.receiver.ConnectivityStatusBroadcastReceiver;
|
||||
import com.cappielloantonio.play.databinding.ActivityMainBinding;
|
||||
import com.cappielloantonio.play.ui.activities.base.BaseActivity;
|
||||
import com.cappielloantonio.play.ui.fragment.PlayerBottomSheetFragment;
|
||||
import com.cappielloantonio.play.util.PreferenceUtil;
|
||||
import com.cappielloantonio.play.util.SyncUtil;
|
||||
import com.cappielloantonio.play.viewmodel.MainViewModel;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
|
||||
import org.jellyfin.apiclient.interaction.EmptyResponse;
|
||||
import org.jellyfin.apiclient.interaction.Response;
|
||||
|
|
@ -29,21 +35,27 @@ import java.util.Objects;
|
|||
public class MainActivity extends BaseActivity {
|
||||
private static final String TAG = "MainActivity";
|
||||
|
||||
public ActivityMainBinding activityMainBinding;
|
||||
public ActivityMainBinding bind;
|
||||
private MainViewModel mainViewModel;
|
||||
|
||||
private FragmentManager fragmentManager;
|
||||
private NavHostFragment navHostFragment;
|
||||
private BottomNavigationView bottomNavigationView;
|
||||
public NavController navController;
|
||||
private BottomSheetBehavior bottomSheetBehavior;
|
||||
|
||||
ConnectivityStatusBroadcastReceiver connectivityStatusBroadcastReceiver;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
activityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
View view = activityMainBinding.getRoot();
|
||||
|
||||
bind = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
View view = bind.getRoot();
|
||||
setContentView(view);
|
||||
|
||||
mainViewModel = new ViewModelProvider(this).get(MainViewModel.class);
|
||||
|
||||
connectivityStatusBroadcastReceiver = new ConnectivityStatusBroadcastReceiver(this);
|
||||
connectivityStatusReceiverManager(true);
|
||||
|
||||
|
|
@ -58,11 +70,9 @@ public class MainActivity extends BaseActivity {
|
|||
|
||||
public void init() {
|
||||
fragmentManager = getSupportFragmentManager();
|
||||
bottomNavigationView = findViewById(R.id.bottom_navigation);
|
||||
|
||||
navHostFragment = (NavHostFragment) fragmentManager.findFragmentById(R.id.nav_host_fragment);
|
||||
navController = navHostFragment.getNavController();
|
||||
NavigationUI.setupWithNavController(bottomNavigationView, navController);
|
||||
initBottomSheet();
|
||||
initNavigation();
|
||||
|
||||
if (PreferenceUtil.getInstance(this).getToken() != null) {
|
||||
checkPreviousSession();
|
||||
|
|
@ -71,6 +81,42 @@ public class MainActivity extends BaseActivity {
|
|||
}
|
||||
}
|
||||
|
||||
private void initBottomSheet() {
|
||||
bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.player_bottom_sheet));
|
||||
bottomSheetBehavior.addBottomSheetCallback(bottomSheetCallback);
|
||||
fragmentManager.beginTransaction().replace(R.id.player_bottom_sheet, new PlayerBottomSheetFragment(), "PlayerBottomSheet").commit();
|
||||
|
||||
isBottomSheetInPeek(mainViewModel.isQueueLoaded());
|
||||
}
|
||||
|
||||
public void isBottomSheetInPeek(Boolean isVisible) {
|
||||
|
||||
Log.d(TAG, "isBottomSheetInPeek: " + isVisible);
|
||||
|
||||
if (isVisible) {
|
||||
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||
} else {
|
||||
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
private void initNavigation() {
|
||||
bottomNavigationView = findViewById(R.id.bottom_navigation);
|
||||
navHostFragment = (NavHostFragment) fragmentManager.findFragmentById(R.id.nav_host_fragment);
|
||||
navController = navHostFragment.getNavController();
|
||||
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
|
||||
if(bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED && (
|
||||
destination.getId() == R.id.homeFragment ||
|
||||
destination.getId() == R.id.libraryFragment ||
|
||||
destination.getId() == R.id.searchFragment ||
|
||||
destination.getId() == R.id.settingsFragment)
|
||||
) {
|
||||
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||
}
|
||||
});
|
||||
NavigationUI.setupWithNavController(bottomNavigationView, navController);
|
||||
}
|
||||
|
||||
private void checkPreviousSession() {
|
||||
App.getApiClientInstance(getApplicationContext()).ChangeServerLocation(PreferenceUtil.getInstance(this).getServer());
|
||||
App.getApiClientInstance(getApplicationContext()).SetAuthenticationInfo(PreferenceUtil.getInstance(this).getToken(), PreferenceUtil.getInstance(this).getUser());
|
||||
|
|
@ -94,8 +140,6 @@ public class MainActivity extends BaseActivity {
|
|||
});
|
||||
}
|
||||
|
||||
// True: VISIBLE
|
||||
// False: GONE
|
||||
public void setBottomNavigationBarVisibility(boolean visibility) {
|
||||
if (visibility) {
|
||||
bottomNavigationView.setVisibility(View.VISIBLE);
|
||||
|
|
@ -104,13 +148,50 @@ public class MainActivity extends BaseActivity {
|
|||
}
|
||||
}
|
||||
|
||||
public void setBottomSheetVisibility(boolean visibility) {
|
||||
if (visibility) {
|
||||
findViewById(R.id.player_bottom_sheet).setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.player_bottom_sheet).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private BottomSheetBehavior.BottomSheetCallback bottomSheetCallback =
|
||||
new BottomSheetBehavior.BottomSheetCallback() {
|
||||
@Override
|
||||
public void onStateChanged(@NonNull View view, int state) {
|
||||
switch (state) {
|
||||
case BottomSheetBehavior.STATE_COLLAPSED:
|
||||
PlayerBottomSheetFragment playerBottomSheetFragment = (PlayerBottomSheetFragment) getSupportFragmentManager().findFragmentByTag("PlayerBottomSheet");
|
||||
if(playerBottomSheetFragment == null) break;
|
||||
|
||||
playerBottomSheetFragment.scrollOnTop();
|
||||
break;
|
||||
case BottomSheetBehavior.STATE_HIDDEN:
|
||||
mainViewModel.deleteQueue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSlide(@NonNull View view, float slideOffset) {
|
||||
PlayerBottomSheetFragment playerBottomSheetFragment = (PlayerBottomSheetFragment) getSupportFragmentManager().findFragmentByTag("PlayerBottomSheet");
|
||||
if(playerBottomSheetFragment == null) return;
|
||||
|
||||
float condensedSlideOffset = Math.max(0.0f, Math.min(0.2f, slideOffset - 0.2f)) / 0.2f;
|
||||
playerBottomSheetFragment.getPlayerHeader().setAlpha(1 - condensedSlideOffset);
|
||||
playerBottomSheetFragment.getPlayerHeader().setVisibility(condensedSlideOffset > 0.99 ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
};
|
||||
|
||||
public void goToLogin() {
|
||||
if (Objects.requireNonNull(navController.getCurrentDestination()).getId() == R.id.landingFragment)
|
||||
navController.navigate(R.id.action_landingFragment_to_loginFragment);
|
||||
}
|
||||
|
||||
public void goToSync() {
|
||||
bottomNavigationView.setVisibility(View.GONE);
|
||||
setBottomNavigationBarVisibility(false);
|
||||
setBottomSheetVisibility(false);
|
||||
|
||||
if (Objects.requireNonNull(navController.getCurrentDestination()).getId() == R.id.loginFragment) {
|
||||
Bundle bundle = SyncUtil.getSyncBundle(true, true, true, true, true, false);
|
||||
|
|
@ -145,12 +226,19 @@ public class MainActivity extends BaseActivity {
|
|||
}
|
||||
|
||||
private void connectivityStatusReceiverManager(boolean isActive) {
|
||||
if(isActive) {
|
||||
if (isActive) {
|
||||
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
registerReceiver(connectivityStatusBroadcastReceiver, filter);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
unregisterReceiver(connectivityStatusBroadcastReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if(bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED)
|
||||
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||
else
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,18 @@
|
|||
package com.cappielloantonio.play.ui.fragment;
|
||||
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.cappielloantonio.play.R;
|
||||
import com.cappielloantonio.play.adapter.SongResultSearchAdapter;
|
||||
import com.cappielloantonio.play.databinding.FragmentAlbumPageBinding;
|
||||
import com.cappielloantonio.play.glide.CustomGlideRequest;
|
||||
|
|
@ -24,7 +28,14 @@ public class AlbumPageFragment extends Fragment {
|
|||
private SongResultSearchAdapter songResultSearchAdapter;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
initAppBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
activity = (MainActivity) getActivity();
|
||||
|
||||
bind = FragmentAlbumPageBinding.inflate(inflater, container, false);
|
||||
|
|
@ -50,6 +61,29 @@ public class AlbumPageFragment extends Fragment {
|
|||
bind = null;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
albumPageViewModel.setAlbum(getArguments().getParcelable("album_object"));
|
||||
}
|
||||
|
||||
private void initAppBar() {
|
||||
activity.setSupportActionBar(bind.animToolbar);
|
||||
if (activity.getSupportActionBar() != null)
|
||||
activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
bind.collapsingToolbar.setTitle(albumPageViewModel.getAlbum().getTitle());
|
||||
bind.animToolbar.setNavigationOnClickListener(v -> activity.navController.navigateUp());
|
||||
bind.collapsingToolbar.setCollapsedTitleTextColor(getResources().getColor(R.color.titleTextColor, null));
|
||||
|
||||
bind.appbar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
|
||||
if ((bind.collapsingToolbar.getHeight() + verticalOffset) < (2 * ViewCompat.getMinimumHeight(bind.collapsingToolbar))) {
|
||||
bind.animToolbar.getNavigationIcon().setColorFilter(getResources().getColor(R.color.titleTextColor, null), PorterDuff.Mode.SRC_ATOP);
|
||||
} else {
|
||||
bind.animToolbar.getNavigationIcon().setColorFilter(getResources().getColor(R.color.white, null), PorterDuff.Mode.SRC_ATOP);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void initBackCover() {
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), albumPageViewModel.getAlbum().getPrimary(), albumPageViewModel.getAlbum().getBlurHash(), CustomGlideRequest.PRIMARY, CustomGlideRequest.TOP_QUALITY)
|
||||
|
|
@ -57,17 +91,11 @@ public class AlbumPageFragment extends Fragment {
|
|||
.into(bind.albumBackCoverImageView);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
albumPageViewModel.setAlbum(getArguments().getParcelable("album_object"));
|
||||
|
||||
bind.albumTitleLabel.setText(albumPageViewModel.getAlbum().getTitle());
|
||||
}
|
||||
|
||||
private void initSongsView() {
|
||||
bind.songRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.songRecyclerView.setHasFixedSize(true);
|
||||
|
||||
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), getChildFragmentManager());
|
||||
songResultSearchAdapter = new SongResultSearchAdapter(activity, requireContext(), getChildFragmentManager());
|
||||
bind.songRecyclerView.setAdapter(songResultSearchAdapter);
|
||||
albumPageViewModel.getAlbumSongList().observe(requireActivity(), songs -> songResultSearchAdapter.setItems(songs));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
package com.cappielloantonio.play.ui.fragment;
|
||||
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
|
@ -27,6 +30,13 @@ public class ArtistPageFragment extends Fragment {
|
|||
private SongResultSearchAdapter songResultSearchAdapter;
|
||||
private AlbumArtistPageAdapter albumArtistPageAdapter;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
initAppBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
activity = (MainActivity) getActivity();
|
||||
|
|
@ -58,7 +68,6 @@ public class ArtistPageFragment extends Fragment {
|
|||
|
||||
private void init() {
|
||||
artistPageViewModel.setArtist(getArguments().getParcelable("artist_object"));
|
||||
bind.artistNameLabel.setText(artistPageViewModel.getArtist().getName());
|
||||
|
||||
bind.mostStreamedSongTextViewClickable.setOnClickListener(v -> {
|
||||
Bundle bundle = new Bundle();
|
||||
|
|
@ -68,6 +77,24 @@ public class ArtistPageFragment extends Fragment {
|
|||
});
|
||||
}
|
||||
|
||||
private void initAppBar() {
|
||||
activity.setSupportActionBar(bind.animToolbar);
|
||||
if (activity.getSupportActionBar() != null)
|
||||
activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
bind.collapsingToolbar.setTitle(artistPageViewModel.getArtist().getName());
|
||||
bind.animToolbar.setNavigationOnClickListener(v -> activity.navController.navigateUp());
|
||||
bind.collapsingToolbar.setCollapsedTitleTextColor(getResources().getColor(R.color.titleTextColor, null));
|
||||
|
||||
bind.appbar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
|
||||
if ((bind.collapsingToolbar.getHeight() + verticalOffset) < (2 * ViewCompat.getMinimumHeight(bind.collapsingToolbar))) {
|
||||
bind.animToolbar.getNavigationIcon().setColorFilter(getResources().getColor(R.color.titleTextColor, null), PorterDuff.Mode.SRC_ATOP);
|
||||
} else {
|
||||
bind.animToolbar.getNavigationIcon().setColorFilter(getResources().getColor(R.color.white, null), PorterDuff.Mode.SRC_ATOP);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initBackdrop() {
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), artistPageViewModel.getArtist().getBackdrop(), artistPageViewModel.getArtist().getBackdropBlurHash(), CustomGlideRequest.BACKDROP, CustomGlideRequest.TOP_QUALITY)
|
||||
|
|
@ -77,16 +104,14 @@ public class ArtistPageFragment extends Fragment {
|
|||
|
||||
private void initTopSongsView() {
|
||||
bind.mostStreamedSongRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.mostStreamedSongRecyclerView.setHasFixedSize(true);
|
||||
|
||||
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), getChildFragmentManager());
|
||||
songResultSearchAdapter = new SongResultSearchAdapter(activity, requireContext(), getChildFragmentManager());
|
||||
bind.mostStreamedSongRecyclerView.setAdapter(songResultSearchAdapter);
|
||||
artistPageViewModel.getArtistTopSongList().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());
|
||||
bind.albumsRecyclerView.setAdapter(albumArtistPageAdapter);
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ public class HomeFragment extends Fragment {
|
|||
public void onStart() {
|
||||
super.onStart();
|
||||
activity.setBottomNavigationBarVisibility(true);
|
||||
activity.setBottomSheetVisibility(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -123,14 +124,14 @@ public class HomeFragment extends Fragment {
|
|||
discoverSongAdapter = new DiscoverSongAdapter(requireContext(), homeViewModel.getDiscoverSongList());
|
||||
bind.discoverSongViewPager.setAdapter(discoverSongAdapter);
|
||||
bind.discoverSongViewPager.setOffscreenPageLimit(3);
|
||||
settDiscoverSongSlideViewOffset(20, 16);
|
||||
setDiscoverSongSlideViewOffset(20, 16);
|
||||
}
|
||||
|
||||
private void initRecentAddedSongView() {
|
||||
bind.recentlyAddedTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||
bind.recentlyAddedTracksRecyclerView.setHasFixedSize(true);
|
||||
|
||||
recentlyAddedMusicAdapter = new RecentMusicAdapter(requireContext(), getChildFragmentManager());
|
||||
recentlyAddedMusicAdapter = new RecentMusicAdapter(activity, requireContext(), getChildFragmentManager());
|
||||
bind.recentlyAddedTracksRecyclerView.setAdapter(recentlyAddedMusicAdapter);
|
||||
homeViewModel.getRecentlyAddedSongList().observe(requireActivity(), songs -> recentlyAddedMusicAdapter.setItems(songs));
|
||||
}
|
||||
|
|
@ -153,7 +154,7 @@ public class HomeFragment extends Fragment {
|
|||
bind.favoritesTracksRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 5, GridLayoutManager.HORIZONTAL, false));
|
||||
bind.favoritesTracksRecyclerView.setHasFixedSize(true);
|
||||
|
||||
favoriteSongAdapter = new SongResultSearchAdapter(requireContext(), getChildFragmentManager());
|
||||
favoriteSongAdapter = new SongResultSearchAdapter(activity, requireContext(), getChildFragmentManager());
|
||||
bind.favoritesTracksRecyclerView.setAdapter(favoriteSongAdapter);
|
||||
homeViewModel.getFavorites().observe(requireActivity(), songs -> favoriteSongAdapter.setItems(songs));
|
||||
|
||||
|
|
@ -165,7 +166,7 @@ public class HomeFragment extends Fragment {
|
|||
bind.mostPlayedTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||
bind.mostPlayedTracksRecyclerView.setHasFixedSize(true);
|
||||
|
||||
mostPlayedMusicAdapter = new RecentMusicAdapter(requireContext(), getChildFragmentManager());
|
||||
mostPlayedMusicAdapter = new RecentMusicAdapter(activity, requireContext(), getChildFragmentManager());
|
||||
bind.mostPlayedTracksRecyclerView.setAdapter(mostPlayedMusicAdapter);
|
||||
homeViewModel.getMostPlayedSongList().observe(requireActivity(), songs -> mostPlayedMusicAdapter.setItems(songs));
|
||||
}
|
||||
|
|
@ -174,12 +175,12 @@ public class HomeFragment extends Fragment {
|
|||
bind.recentlyPlayedTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||
bind.recentlyPlayedTracksRecyclerView.setHasFixedSize(true);
|
||||
|
||||
recentlyPlayedMusicAdapter = new RecentMusicAdapter(requireContext(), getChildFragmentManager());
|
||||
recentlyPlayedMusicAdapter = new RecentMusicAdapter(activity, requireContext(), getChildFragmentManager());
|
||||
bind.recentlyPlayedTracksRecyclerView.setAdapter(recentlyPlayedMusicAdapter);
|
||||
homeViewModel.getRecentlyPlayedSongList().observe(requireActivity(), songs -> recentlyPlayedMusicAdapter.setItems(songs));
|
||||
}
|
||||
|
||||
private void settDiscoverSongSlideViewOffset(float pageOffset, float pageMargin) {
|
||||
private void setDiscoverSongSlideViewOffset(float pageOffset, float pageMargin) {
|
||||
bind.discoverSongViewPager.setPageTransformer((page, position) -> {
|
||||
float myOffset = position * -(2 * pageOffset + pageMargin);
|
||||
if (bind.discoverSongViewPager.getOrientation() == ViewPager2.ORIENTATION_HORIZONTAL) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
package com.cappielloantonio.play.ui.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.cappielloantonio.play.R;
|
||||
import com.cappielloantonio.play.adapter.PlayerNowPlayingSongAdapter;
|
||||
import com.cappielloantonio.play.adapter.PlayerSongQueueAdapter;
|
||||
import com.cappielloantonio.play.databinding.FragmentPlayerBottomSheetBinding;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||
import com.cappielloantonio.play.viewmodel.PlayerBottomSheetViewModel;
|
||||
|
||||
public class PlayerBottomSheetFragment extends Fragment {
|
||||
private static final String TAG = "PlayerBottomSheetFragment";
|
||||
|
||||
private FragmentPlayerBottomSheetBinding bind;
|
||||
private MainActivity activity;
|
||||
private PlayerBottomSheetViewModel playerBottomSheetViewModel;
|
||||
|
||||
private PlayerNowPlayingSongAdapter playerNowPlayingSongAdapter;
|
||||
private PlayerSongQueueAdapter playerSongQueueAdapter;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
activity = (MainActivity) getActivity();
|
||||
|
||||
bind = FragmentPlayerBottomSheetBinding.inflate(inflater, container, false);
|
||||
View view = bind.getRoot();
|
||||
playerBottomSheetViewModel = new ViewModelProvider(requireActivity()).get(PlayerBottomSheetViewModel.class);
|
||||
|
||||
initQueueSlideView();
|
||||
initQueueRecyclerView();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void initQueueSlideView() {
|
||||
bind.playerSongCoverViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
|
||||
|
||||
playerNowPlayingSongAdapter = new PlayerNowPlayingSongAdapter(requireContext());
|
||||
bind.playerSongCoverViewPager.setAdapter(playerNowPlayingSongAdapter);
|
||||
playerBottomSheetViewModel.getQueueSong().observe(requireActivity(), songs -> playerNowPlayingSongAdapter.setItems(songs));
|
||||
|
||||
bind.playerSongCoverViewPager.setOffscreenPageLimit(3);
|
||||
setDiscoverSongSlideViewOffset(40, 4);
|
||||
|
||||
bind.playerSongCoverViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||
|
||||
playerBottomSheetViewModel.setNowPlayingSong(position);
|
||||
}
|
||||
});
|
||||
|
||||
playerBottomSheetViewModel.getNowPlayingSong().observe(requireActivity(), song -> {
|
||||
if(song != null)
|
||||
setSongInfo(song);
|
||||
});
|
||||
}
|
||||
|
||||
private void initQueueRecyclerView() {
|
||||
bind.playerQueueRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.playerQueueRecyclerView.setHasFixedSize(true);
|
||||
|
||||
playerSongQueueAdapter = new PlayerSongQueueAdapter(activity, requireContext(), getChildFragmentManager());
|
||||
bind.playerQueueRecyclerView.setAdapter(playerSongQueueAdapter);
|
||||
playerBottomSheetViewModel.getQueueSong().observe(requireActivity(), songs -> playerSongQueueAdapter.setItems(songs));
|
||||
}
|
||||
|
||||
private void setDiscoverSongSlideViewOffset(float pageOffset, float pageMargin) {
|
||||
bind.playerSongCoverViewPager.setPageTransformer((page, position) -> {
|
||||
float myOffset = position * -(2 * pageOffset + pageMargin);
|
||||
if (bind.playerSongCoverViewPager.getOrientation() == ViewPager2.ORIENTATION_HORIZONTAL) {
|
||||
if (ViewCompat.getLayoutDirection(bind.playerSongCoverViewPager) == ViewCompat.LAYOUT_DIRECTION_RTL) {
|
||||
page.setTranslationX(-myOffset);
|
||||
} else {
|
||||
page.setTranslationX(myOffset);
|
||||
}
|
||||
} else {
|
||||
page.setTranslationY(myOffset);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setSongInfo(Song song) {
|
||||
if(song != null) {
|
||||
bind.playerSongTitleLabel.setText(song.getTitle());
|
||||
bind.playerArtistNameLabel.setText(song.getArtistName());
|
||||
}
|
||||
}
|
||||
|
||||
public View getPlayerHeader() {
|
||||
return getView().findViewById(R.id.player_header_layout);
|
||||
}
|
||||
|
||||
public void scrollOnTop() {
|
||||
bind.playerNestedScrollView.fullScroll(ScrollView.FOCUS_UP);
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ public class SearchFragment extends Fragment {
|
|||
bind.searchResultTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.searchResultTracksRecyclerView.setHasFixedSize(true);
|
||||
|
||||
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), getChildFragmentManager());
|
||||
songResultSearchAdapter = new SongResultSearchAdapter(activity, requireContext(), getChildFragmentManager());
|
||||
bind.searchResultTracksRecyclerView.setAdapter(songResultSearchAdapter);
|
||||
|
||||
// Albums
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public class SongListPageFragment extends Fragment {
|
|||
bind.songListRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.songListRecyclerView.setHasFixedSize(true);
|
||||
|
||||
songResultSearchAdapter = new SongResultSearchAdapter(requireContext(), getChildFragmentManager());
|
||||
songResultSearchAdapter = new SongResultSearchAdapter(activity, requireContext(), getChildFragmentManager());
|
||||
bind.songListRecyclerView.setAdapter(songResultSearchAdapter);
|
||||
songListPageViewModel.getSongList().observe(requireActivity(), songs -> songResultSearchAdapter.setItems(songs));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public class PreferenceUtil {
|
|||
}
|
||||
|
||||
public String getToken() {
|
||||
return mPreferences.getString(TOKEN, "");
|
||||
return mPreferences.getString(TOKEN, null);
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package com.cappielloantonio.play.util;
|
||||
|
||||
import com.cappielloantonio.play.model.Queue;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class QueueUtil {
|
||||
public static Queue getQueueElementFromSong(Song song) {
|
||||
return new Queue(song.getId());
|
||||
}
|
||||
|
||||
public static List<Queue> getQueueElementsFromSongs(List<Song> songs) {
|
||||
List<Queue> queue = new ArrayList<>();
|
||||
|
||||
for(Song song: songs) {
|
||||
queue.add(new Queue(song.getId()));
|
||||
}
|
||||
|
||||
return queue;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.cappielloantonio.play.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class Util {
|
||||
|
|
@ -15,4 +17,12 @@ public class Util {
|
|||
return String.format(Locale.getDefault(), "%d:%02d:%02d", hours, minutes, seconds);
|
||||
}
|
||||
}
|
||||
|
||||
public static float dpFromPx(final Context context, final float px) {
|
||||
return px / context.getResources().getDisplayMetrics().density;
|
||||
}
|
||||
|
||||
public static float pxFromDp(final Context context, final float dp) {
|
||||
return dp * context.getResources().getDisplayMetrics().density;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
package com.cappielloantonio.play.viewmodel;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
|
||||
import com.cappielloantonio.play.repository.QueueRepository;
|
||||
|
||||
public class MainViewModel extends AndroidViewModel {
|
||||
private static final String TAG = "SearchViewModel";
|
||||
|
||||
private QueueRepository queueRepository;
|
||||
|
||||
public MainViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
|
||||
queueRepository = new QueueRepository(application);
|
||||
}
|
||||
|
||||
public boolean isQueueLoaded() {
|
||||
if(queueRepository.count() == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void deleteQueue(){
|
||||
queueRepository.deleteAll();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.cappielloantonio.play.viewmodel;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
import com.cappielloantonio.play.repository.QueueRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PlayerBottomSheetViewModel extends AndroidViewModel {
|
||||
private static final String TAG = "HomeViewModel";
|
||||
private QueueRepository queueRepository;
|
||||
|
||||
private LiveData<List<Song>> queueSong;
|
||||
private LiveData<Song> nowPlayingSong = new MutableLiveData<>();
|
||||
|
||||
|
||||
public PlayerBottomSheetViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
|
||||
queueRepository = new QueueRepository(application);
|
||||
|
||||
queueSong = queueRepository.getLiveQueue();
|
||||
}
|
||||
|
||||
public LiveData<List<Song>> getQueueSong() {
|
||||
return queueSong;
|
||||
}
|
||||
|
||||
public LiveData<Song> getNowPlayingSong() {
|
||||
return nowPlayingSong;
|
||||
}
|
||||
|
||||
public LiveData<Song> setNowPlayingSong(int position) {
|
||||
Song song = queueRepository.getSongs().get(position);
|
||||
|
||||
if(song != null) {
|
||||
nowPlayingSong = new MutableLiveData<>(song);
|
||||
}
|
||||
|
||||
return nowPlayingSong;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue