Implement appending queue to playlist in main player (#8008)
This also allows saving a remote playlist locally. - Add an "Add to playlist" button to the queue menu in the Player. - Move the appendAllToPlaylist functionality from PlayQueueActivity to Player. Fixes: #8004
This commit is contained in:
parent
b607a09125
commit
02fa5aa0fa
|
@ -1,5 +1,9 @@
|
|||
package org.schabi.newpipe.player;
|
||||
|
||||
import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -23,11 +27,9 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
||||
import org.schabi.newpipe.databinding.ActivityPlayerQueueControlBinding;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
||||
import org.schabi.newpipe.local.dialog.PlaylistDialog;
|
||||
import org.schabi.newpipe.player.event.PlayerEventListener;
|
||||
import org.schabi.newpipe.player.helper.PlaybackParameterDialog;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
|
@ -42,13 +44,6 @@ import org.schabi.newpipe.util.PermissionHelper;
|
|||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||
|
||||
public final class PlayQueueActivity extends AppCompatActivity
|
||||
implements PlayerEventListener, SeekBar.OnSeekBarChangeListener,
|
||||
View.OnClickListener, PlaybackParameterDialog.Callback {
|
||||
|
@ -129,7 +124,7 @@ public final class PlayQueueActivity extends AppCompatActivity
|
|||
NavigationHelper.openSettings(this);
|
||||
return true;
|
||||
case R.id.action_append_playlist:
|
||||
appendAllToPlaylist();
|
||||
player.onAddToPlaylistClicked(getSupportFragmentManager());
|
||||
return true;
|
||||
case R.id.action_playback_speed:
|
||||
openPlaybackParameterDialog();
|
||||
|
@ -443,24 +438,6 @@ public final class PlayQueueActivity extends AppCompatActivity
|
|||
seeking = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Playlist append
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void appendAllToPlaylist() {
|
||||
if (player != null && player.getPlayQueue() != null) {
|
||||
openPlaylistAppendDialog(player.getPlayQueue().getStreams());
|
||||
}
|
||||
}
|
||||
|
||||
private void openPlaylistAppendDialog(final List<PlayQueueItem> playQueueItems) {
|
||||
PlaylistDialog.createCorrespondingDialog(
|
||||
getApplicationContext(),
|
||||
playQueueItems.stream().map(StreamEntity::new).collect(Collectors.toList()),
|
||||
dialog -> dialog.show(getSupportFragmentManager(), TAG)
|
||||
);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Binding Service Listener
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -105,6 +105,7 @@ import androidx.core.graphics.Insets;
|
|||
import androidx.core.view.GestureDetectorCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
@ -138,6 +139,7 @@ import com.squareup.picasso.Target;
|
|||
import org.schabi.newpipe.DownloaderImpl;
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
||||
import org.schabi.newpipe.databinding.PlayerBinding;
|
||||
import org.schabi.newpipe.databinding.PlayerPopupCloseOverlayBinding;
|
||||
import org.schabi.newpipe.error.ErrorInfo;
|
||||
|
@ -152,6 +154,7 @@ import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
|||
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
||||
import org.schabi.newpipe.info_list.StreamSegmentAdapter;
|
||||
import org.schabi.newpipe.ktx.AnimationType;
|
||||
import org.schabi.newpipe.local.dialog.PlaylistDialog;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.player.MainPlayer.PlayerType;
|
||||
import org.schabi.newpipe.player.event.DisplayPortion;
|
||||
|
@ -197,6 +200,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
|
@ -541,6 +545,7 @@ public final class Player implements
|
|||
binding.segmentsButton.setOnClickListener(this);
|
||||
binding.repeatButton.setOnClickListener(this);
|
||||
binding.shuffleButton.setOnClickListener(this);
|
||||
binding.addToPlaylistButton.setOnClickListener(this);
|
||||
|
||||
binding.playPauseButton.setOnClickListener(this);
|
||||
binding.playPreviousButton.setOnClickListener(this);
|
||||
|
@ -2389,6 +2394,32 @@ public final class Player implements
|
|||
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Playlist append
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
//region Playlist append
|
||||
|
||||
public void onAddToPlaylistClicked(@NonNull final FragmentManager fragmentManager) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onAddToPlaylistClicked() called");
|
||||
}
|
||||
|
||||
if (getPlayQueue() != null) {
|
||||
PlaylistDialog.createCorrespondingDialog(
|
||||
getContext(),
|
||||
getPlayQueue()
|
||||
.getStreams()
|
||||
.stream()
|
||||
.map(StreamEntity::new)
|
||||
.collect(Collectors.toList()),
|
||||
dialog -> dialog.show(fragmentManager, TAG)
|
||||
);
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Mute / Unmute
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -3131,6 +3162,7 @@ public final class Player implements
|
|||
binding.itemsListHeaderDuration.setVisibility(View.VISIBLE);
|
||||
binding.shuffleButton.setVisibility(View.VISIBLE);
|
||||
binding.repeatButton.setVisibility(View.VISIBLE);
|
||||
binding.addToPlaylistButton.setVisibility(View.VISIBLE);
|
||||
|
||||
hideControls(0, 0);
|
||||
binding.itemsListPanel.requestFocus();
|
||||
|
@ -3168,6 +3200,7 @@ public final class Player implements
|
|||
binding.itemsListHeaderDuration.setVisibility(View.GONE);
|
||||
binding.shuffleButton.setVisibility(View.GONE);
|
||||
binding.repeatButton.setVisibility(View.GONE);
|
||||
binding.addToPlaylistButton.setVisibility(View.GONE);
|
||||
|
||||
hideControls(0, 0);
|
||||
binding.itemsListPanel.requestFocus();
|
||||
|
@ -3196,6 +3229,7 @@ public final class Player implements
|
|||
|
||||
binding.shuffleButton.setVisibility(View.GONE);
|
||||
binding.repeatButton.setVisibility(View.GONE);
|
||||
binding.addToPlaylistButton.setVisibility(View.GONE);
|
||||
binding.itemsListClose.setOnClickListener(view -> closeItemsList());
|
||||
}
|
||||
|
||||
|
@ -3733,6 +3767,11 @@ public final class Player implements
|
|||
} else if (v.getId() == binding.shuffleButton.getId()) {
|
||||
onShuffleClicked();
|
||||
return;
|
||||
} else if (v.getId() == binding.addToPlaylistButton.getId()) {
|
||||
if (getParentActivity() != null) {
|
||||
onAddToPlaylistClicked(getParentActivity().getSupportFragmentManager());
|
||||
}
|
||||
return;
|
||||
} else if (v.getId() == binding.moreOptionsButton.getId()) {
|
||||
onMoreOptionsClicked();
|
||||
} else if (v.getId() == binding.share.getId()) {
|
||||
|
|
|
@ -581,6 +581,21 @@
|
|||
app:srcCompat="@drawable/ic_close"
|
||||
app:tint="@color/white" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/addToPlaylistButton"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/itemsListClose"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="10dp"
|
||||
android:scaleType="fitXY"
|
||||
android:tint="?attr/colorAccent"
|
||||
app:srcCompat="@drawable/ic_playlist_add"
|
||||
tools:ignore="ContentDescription,RtlHardcoded" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/repeatButton"
|
||||
android:layout_width="50dp"
|
||||
|
@ -620,7 +635,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@id/itemsListClose"
|
||||
android:layout_toStartOf="@id/addToPlaylistButton"
|
||||
android:layout_toEndOf="@id/shuffleButton"
|
||||
android:gravity="center"
|
||||
android:textColor="@android:color/white" />
|
||||
|
|
Loading…
Reference in New Issue