mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 17:43:32 +00:00
feat: added the ability to shuffle the playback queue
This commit is contained in:
parent
b656ad9e7f
commit
99be2764d0
3 changed files with 89 additions and 9 deletions
|
|
@ -204,6 +204,22 @@ public class MediaManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void shuffle(ListenableFuture<MediaBrowser> mediaBrowserListenableFuture, List<Child> media, int startIndex, int endIndex) {
|
||||||
|
if (mediaBrowserListenableFuture != null) {
|
||||||
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
|
try {
|
||||||
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
|
mediaBrowserListenableFuture.get().removeMediaItems(startIndex, endIndex + 1);
|
||||||
|
mediaBrowserListenableFuture.get().addMediaItems(MappingUtil.mapMediaItems(media).subList(startIndex, endIndex + 1));
|
||||||
|
swapDatabase(media);
|
||||||
|
}
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}, MoreExecutors.directExecutor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void swap(ListenableFuture<MediaBrowser> mediaBrowserListenableFuture, List<Child> media, int from, int to) {
|
public static void swap(ListenableFuture<MediaBrowser> mediaBrowserListenableFuture, List<Child> media, int from, int to) {
|
||||||
if (mediaBrowserListenableFuture != null) {
|
if (mediaBrowserListenableFuture != null) {
|
||||||
mediaBrowserListenableFuture.addListener(() -> {
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,16 @@ import com.cappielloantonio.tempo.ui.adapter.PlayerSongQueueAdapter;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.viewmodel.PlayerBottomSheetViewModel;
|
import com.cappielloantonio.tempo.viewmodel.PlayerBottomSheetViewModel;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
||||||
|
private static final String TAG = "PlayerQueueFragment";
|
||||||
|
|
||||||
private InnerFragmentPlayerQueueBinding bind;
|
private InnerFragmentPlayerQueueBinding bind;
|
||||||
|
|
||||||
private PlayerBottomSheetViewModel playerBottomSheetViewModel;
|
private PlayerBottomSheetViewModel playerBottomSheetViewModel;
|
||||||
|
|
@ -54,6 +58,7 @@ public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
initializeBrowser();
|
initializeBrowser();
|
||||||
|
bindMediaController();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -83,6 +88,17 @@ public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
||||||
MediaBrowser.releaseFuture(mediaBrowserListenableFuture);
|
MediaBrowser.releaseFuture(mediaBrowserListenableFuture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void bindMediaController() {
|
||||||
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
|
try {
|
||||||
|
MediaBrowser mediaBrowser = mediaBrowserListenableFuture.get();
|
||||||
|
initShuffleButton(mediaBrowser);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
}, MoreExecutors.directExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
private void setMediaBrowserListenableFuture() {
|
private void setMediaBrowserListenableFuture() {
|
||||||
playerSongQueueAdapter.setMediaBrowserListenableFuture(mediaBrowserListenableFuture);
|
playerSongQueueAdapter.setMediaBrowserListenableFuture(mediaBrowserListenableFuture);
|
||||||
}
|
}
|
||||||
|
|
@ -151,6 +167,36 @@ public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
||||||
}).attachToRecyclerView(bind.playerQueueRecyclerView);
|
}).attachToRecyclerView(bind.playerQueueRecyclerView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initShuffleButton(MediaBrowser mediaBrowser) {
|
||||||
|
bind.playerShuffleQueueFab.setOnClickListener(view -> {
|
||||||
|
int startPosition = mediaBrowser.getCurrentMediaItemIndex() + 1;
|
||||||
|
int endPosition = playerSongQueueAdapter.getItems().size() - 1;
|
||||||
|
|
||||||
|
if (startPosition < endPosition) {
|
||||||
|
ArrayList<Integer> pool = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = startPosition; i <= endPosition; i++) {
|
||||||
|
pool.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pool.size() >= 2) {
|
||||||
|
int fromPosition = (int) (Math.random() * (pool.size()));
|
||||||
|
int positionA = pool.get(fromPosition);
|
||||||
|
pool.remove(fromPosition);
|
||||||
|
|
||||||
|
int toPosition = (int) (Math.random() * (pool.size()));
|
||||||
|
int positionB = pool.get(toPosition);
|
||||||
|
pool.remove(toPosition);
|
||||||
|
|
||||||
|
Collections.swap(playerSongQueueAdapter.getItems(), positionA, positionB);
|
||||||
|
bind.playerQueueRecyclerView.getAdapter().notifyItemMoved(positionA, positionB);
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaManager.shuffle(mediaBrowserListenableFuture, playerSongQueueAdapter.getItems(), startPosition, endPosition);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void updateNowPlayingItem() {
|
private void updateNowPlayingItem() {
|
||||||
playerSongQueueAdapter.notifyDataSetChanged();
|
playerSongQueueAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,32 @@
|
||||||
<com.cappielloantonio.tempo.helper.recyclerview.NestedScrollableHost xmlns:android="http://schemas.android.com/apk/res/android"
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<com.cappielloantonio.tempo.helper.recyclerview.NestedScrollableHost
|
||||||
android:id="@+id/player_queue_recycler_view"
|
android:id="@+id/player_queue_nested_scrollable_recycler_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:clipToPadding="false"
|
|
||||||
android:orientation="vertical"
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:paddingTop="8dp"
|
android:id="@+id/player_queue_recycler_view"
|
||||||
android:paddingBottom="@dimen/global_padding_bottom" />
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingBottom="@dimen/global_padding_bottom" />
|
||||||
|
</com.cappielloantonio.tempo.helper.recyclerview.NestedScrollableHost>
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/player_shuffle_queue_fab"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
|
||||||
|
app:srcCompat="@drawable/ic_shuffle"/>
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
</com.cappielloantonio.tempo.helper.recyclerview.NestedScrollableHost>
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue