mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 17:43:32 +00:00
Add option to order and delete elements from queue by dragging and swiping
This commit is contained in:
parent
49c3d60ed1
commit
a2770daaa8
9 changed files with 70 additions and 111 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
|
|
|
|||
|
|
@ -20,18 +20,6 @@ public interface QueueDao {
|
|||
@Query("SELECT * FROM song JOIN queue ON song.id = queue.id")
|
||||
List<Song> 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<Song> 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")
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ public class QueueRepository {
|
|||
|
||||
private QueueDao queueDao;
|
||||
private LiveData<List<Song>> listLiveQueue;
|
||||
private LiveData<Song> 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<Song> 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<Song> getSongs() {
|
||||
List<Song> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -12,10 +12,12 @@ public class QueueUtil {
|
|||
}
|
||||
|
||||
public static List<Queue> getQueueElementsFromSongs(List<Song> songs) {
|
||||
int counter = 0;
|
||||
List<Queue> queue = new ArrayList<>();
|
||||
|
||||
for(Song song: songs) {
|
||||
queue.add(new Queue(song.getId(), 0));
|
||||
queue.add(new Queue(song.getId(), counter));
|
||||
counter++;
|
||||
}
|
||||
|
||||
return queue;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
|
|||
this.song = song;
|
||||
}
|
||||
|
||||
public void orderSongAfterSwap(List<Song> songs) {
|
||||
queueRepository.insertAllAndStartNew(songs);
|
||||
}
|
||||
|
||||
public void removeSong(int position) {
|
||||
queueRepository.deleteByPosition(position);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/queue_song_artist_text_view"
|
||||
|
|
@ -54,10 +54,10 @@
|
|||
android:textSize="12sp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/queue_song_title_text_view"
|
||||
app:layout_constraintStart_toEndOf="@+id/queue_song_cover_image_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/queue_song_dragger_image"/>
|
||||
app:layout_constraintEnd_toStartOf="@+id/queue_song_holder_image"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/queue_song_dragger_image"
|
||||
android:id="@+id/queue_song_holder_image"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingStart="8dp"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue