diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/PlayerSongQueueAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/PlayerSongQueueAdapter.java index 0efbf547..dbde45ec 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/PlayerSongQueueAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/PlayerSongQueueAdapter.java @@ -9,12 +9,10 @@ import android.widget.TextView; 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.helper.MusicPlayerRemote; import com.cappielloantonio.play.model.Song; -import com.cappielloantonio.play.repository.SongRepository; import com.cappielloantonio.play.ui.fragment.PlayerBottomSheetFragment; import java.util.ArrayList; diff --git a/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java b/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java index b3cffa6d..30de9441 100644 --- a/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java +++ b/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java @@ -23,7 +23,7 @@ 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, Queue.class}, version = 6, exportSchema = false) +@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class, SongGenreCross.class, Queue.class}, version = 7, exportSchema = false) public abstract class AppDatabase extends RoomDatabase { private static final String TAG = "AppDatabase"; diff --git a/app/src/main/java/com/cappielloantonio/play/database/dao/QueueDao.java b/app/src/main/java/com/cappielloantonio/play/database/dao/QueueDao.java index 03583360..9ccb23d6 100644 --- a/app/src/main/java/com/cappielloantonio/play/database/dao/QueueDao.java +++ b/app/src/main/java/com/cappielloantonio/play/database/dao/QueueDao.java @@ -20,18 +20,6 @@ public interface QueueDao { @Query("SELECT * FROM song JOIN queue ON song.id = queue.id") List getAllSimple(); - @Query("SELECT * FROM song JOIN queue ON song.id = queue.id WHERE queue.rowid = :position") - Song getSongByIndex(int position); - - @Query("SELECT * FROM song JOIN queue ON song.id = queue.id WHERE queue.last_played != 0 ORDER BY queue.last_played DESC LIMIT 1") - LiveData getLastPlayedSong(); - - @Query("UPDATE queue SET last_played = :timestamp WHERE queue.rowid = :position") - void setLastPlayedSong(int position, long timestamp); - - @Query("UPDATE queue SET last_played = :timestamp WHERE queue.id = :songID") - void setLastPlayedSong(String songID, long timestamp); - @Insert(onConflict = OnConflictStrategy.REPLACE) void insert(Queue songQueueObject); @@ -41,7 +29,7 @@ public interface QueueDao { @Delete void delete(Queue songQueueObject); - @Query("DELETE FROM queue WHERE queue.rowid = :position") + @Query("DELETE FROM queue WHERE queue.track_order = :position") void deleteByPosition(int position); @Query("DELETE FROM queue") diff --git a/app/src/main/java/com/cappielloantonio/play/model/Queue.java b/app/src/main/java/com/cappielloantonio/play/model/Queue.java index 5cbf4451..efd9dbe3 100644 --- a/app/src/main/java/com/cappielloantonio/play/model/Queue.java +++ b/app/src/main/java/com/cappielloantonio/play/model/Queue.java @@ -12,12 +12,12 @@ public class Queue { @ColumnInfo(name = "id") private String songID; - @ColumnInfo(name = "last_played") - private long lastPlayed; + @ColumnInfo(name = "track_order") + private int trackOrder; - public Queue(String songID, long lastPlayed) { + public Queue(String songID, int trackOrder) { this.songID = songID; - this.lastPlayed = lastPlayed; + this.trackOrder = trackOrder; } public String getSongID() { @@ -28,11 +28,11 @@ public class Queue { this.songID = songID; } - public long getLastPlayed() { - return lastPlayed; + public int getTrackOrder() { + return trackOrder; } - public void setLastPlayed(long lastPlayed) { - this.lastPlayed = lastPlayed; + public void setTrackOrder(int trackOrder) { + this.trackOrder = trackOrder; } } diff --git a/app/src/main/java/com/cappielloantonio/play/repository/QueueRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/QueueRepository.java index 76b12a82..2d027e29 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/QueueRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/QueueRepository.java @@ -19,7 +19,6 @@ public class QueueRepository { private QueueDao queueDao; private LiveData> listLiveQueue; - private LiveData liveLastPlayedSong; public QueueRepository(Application application) { AppDatabase database = AppDatabase.getInstance(application); @@ -31,34 +30,6 @@ public class QueueRepository { return listLiveQueue; } - public Song getSongByPosition(int position) { - Song song = null; - - GetSongByPositionThreadSafe getSong = new GetSongByPositionThreadSafe(queueDao, position); - Thread thread = new Thread(getSong); - thread.start(); - - try { - thread.join(); - song = getSong.getSong(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - return song; - } - - public LiveData getLiveLastPlayedSong() { - liveLastPlayedSong = queueDao.getLastPlayedSong(); - return liveLastPlayedSong; - } - - public void setLiveLastPlayedSong(Song song, int position) { - SetLastPlayedSongThreadSafe update = new SetLastPlayedSongThreadSafe(queueDao, song, position); - Thread thread = new Thread(update); - thread.start(); - } - public List getSongs() { List songs = new ArrayList<>(); @@ -245,44 +216,4 @@ public class QueueRepository { return songs; } } - - private static class SetLastPlayedSongThreadSafe implements Runnable { - private QueueDao queueDao; - private Song song; - private int position; - - public SetLastPlayedSongThreadSafe(QueueDao queueDao, Song song, int position) { - this.queueDao = queueDao; - this.song = song; - this.position = position; - } - - @Override - public void run() { - if(song != null) - queueDao.setLastPlayedSong(song.getId(), Instant.now().toEpochMilli()); - else - queueDao.setLastPlayedSong(position, Instant.now().toEpochMilli()); - } - } - - private static class GetSongByPositionThreadSafe implements Runnable { - private QueueDao queueDao; - private int position; - private Song song; - - public GetSongByPositionThreadSafe(QueueDao queueDao, int position) { - this.queueDao = queueDao; - this.position = position; - } - - @Override - public void run() { - song = queueDao.getSongByIndex(position); - } - - public Song getSong() { - return song; - } - } } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java index 121b892c..b3f40eeb 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java @@ -3,7 +3,6 @@ package com.cappielloantonio.play.ui.fragment; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -145,29 +144,62 @@ public class PlayerBottomSheetFragment extends Fragment implements MusicServiceE playerBottomSheetViewModel.getQueueSong().observe(requireActivity(), songs -> playerSongQueueAdapter.setItems(songs)); new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT) { + int originalPosition = -1; + int fromPosition = -1; + int toPosition = -1; + @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { - int fromPosition = viewHolder.getBindingAdapterPosition(); - int toPosition = target.getBindingAdapterPosition(); + if(originalPosition == -1) originalPosition = viewHolder.getBindingAdapterPosition(); + + fromPosition = viewHolder.getBindingAdapterPosition(); + toPosition = target.getBindingAdapterPosition(); + + /* + * Per spostare un elemento nella coda devo: + * - Spostare graficamente la traccia da una posizione all'altra con Collections.swap() + * - Spostare nel db la traccia, tramite QueueRepository + * - Notificare il Service dell'avvenuto spostamento con MusicPlayerRemote.moveSong() + * + * In onMove prendo la posizione di inizio e fine, ma solo al rilascio dell'elemento procedo allo spostamento + * In questo modo evito che ad ogni cambio di posizione vada a riscrivere nel db + * Al rilascio dell'elemento chiamo il metodo clearView() + */ Collections.swap(playerSongQueueAdapter.getItems(), fromPosition, toPosition); + recyclerView.getAdapter().notifyItemMoved(fromPosition, toPosition); - bind.playerBodyLayout.playerQueueRecyclerView.getAdapter().notifyItemMoved(fromPosition, toPosition); - // bind.playerBodyLayout.playerSongCoverViewPager.getAdapter().notifyItemMoved(fromPosition, toPosition); - - // bind.playerBodyLayout.playerQueueRecyclerView.getAdapter().notifyDataSetChanged(); - // bind.playerBodyLayout.playerSongCoverViewPager.getAdapter().notifyDataSetChanged(); - - // MusicPlayerRemote.moveSong(fromPosition, toPosition); return false; } @Override - public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { - Log.i(TAG, "onSwiped: " + viewHolder.getBindingAdapterPosition()); - Log.i(TAG, "onSwiped: " + MusicPlayerRemote.getPlayingQueue().get(viewHolder.getBindingAdapterPosition()).getTitle()); + public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { + super.clearView(recyclerView, viewHolder); - playerBottomSheetViewModel.removeSong(viewHolder.getBindingAdapterPosition()); + /* + * Qui vado a riscivere tutta la table Queue, quando teoricamente potrei solo swappare l'ordine degli elementi interessati + * Nel caso la coda contenesse parecchi brani, potrebbero verificarsi rallentamenti pesanti + */ + playerBottomSheetViewModel.orderSongAfterSwap(playerSongQueueAdapter.getItems()); + MusicPlayerRemote.moveSong(originalPosition, toPosition); + bind.playerBodyLayout.playerSongCoverViewPager.setCurrentItem(MusicPlayerRemote.getPosition(), true); + + originalPosition = -1; + fromPosition = -1; + toPosition = -1; + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + if(!(viewHolder.getBindingAdapterPosition() == MusicPlayerRemote.getPosition()) && !(MusicPlayerRemote.getPlayingQueue().size() <= 1)) { + MusicPlayerRemote.removeFromQueue(viewHolder.getBindingAdapterPosition()); + playerBottomSheetViewModel.removeSong(viewHolder.getBindingAdapterPosition()); + bind.playerBodyLayout.playerQueueRecyclerView.getAdapter().notifyItemRemoved(viewHolder.getBindingAdapterPosition()); + bind.playerBodyLayout.playerSongCoverViewPager.setCurrentItem(MusicPlayerRemote.getPosition(), true); + } + else { + bind.playerBodyLayout.playerQueueRecyclerView.getAdapter().notifyDataSetChanged(); + } } } ).attachToRecyclerView(bind.playerBodyLayout.playerQueueRecyclerView); @@ -264,6 +296,10 @@ public class PlayerBottomSheetFragment extends Fragment implements MusicServiceE setSongInfo(song); } + private void setCurrentItemInSlideView(boolean smoothScroll) { + + } + @Override public void onServiceConnected() { setSongInfo(MusicPlayerRemote.getCurrentSong()); diff --git a/app/src/main/java/com/cappielloantonio/play/util/QueueUtil.java b/app/src/main/java/com/cappielloantonio/play/util/QueueUtil.java index 53cb9430..30d75f12 100644 --- a/app/src/main/java/com/cappielloantonio/play/util/QueueUtil.java +++ b/app/src/main/java/com/cappielloantonio/play/util/QueueUtil.java @@ -12,10 +12,12 @@ public class QueueUtil { } public static List getQueueElementsFromSongs(List songs) { + int counter = 0; List queue = new ArrayList<>(); for(Song song: songs) { - queue.add(new Queue(song.getId(), 0)); + queue.add(new Queue(song.getId(), counter)); + counter++; } return queue; diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java index cedc4e65..40b2d835 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java @@ -50,6 +50,10 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel { this.song = song; } + public void orderSongAfterSwap(List songs) { + queueRepository.insertAllAndStartNew(songs); + } + public void removeSong(int position) { queueRepository.deleteByPosition(position); } diff --git a/app/src/main/res/layout/item_player_queue_song.xml b/app/src/main/res/layout/item_player_queue_song.xml index 6bab220c..a574c0f5 100644 --- a/app/src/main/res/layout/item_player_queue_song.xml +++ b/app/src/main/res/layout/item_player_queue_song.xml @@ -41,7 +41,7 @@ android:textStyle="bold" app:layout_constraintStart_toEndOf="@+id/queue_song_cover_image_view" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintEnd_toStartOf="@+id/queue_song_dragger_image"/> + app:layout_constraintEnd_toStartOf="@+id/queue_song_holder_image"/> + app:layout_constraintEnd_toStartOf="@+id/queue_song_holder_image"/>