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:
ktprograms 2022-03-16 01:32:39 +08:00 committed by GitHub
parent b607a09125
commit 02fa5aa0fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 29 deletions

View File

@ -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
////////////////////////////////////////////////////////////////////////////

View File

@ -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()) {

View File

@ -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" />