Cleaned up PlaylistDialog-related code

This commit is contained in:
litetex 2021-10-09 18:46:20 +02:00
parent 4fde62ff89
commit 731640997e
8 changed files with 147 additions and 170 deletions

View File

@ -9,8 +9,8 @@ import android.widget.PopupMenu;
import androidx.fragment.app.FragmentManager;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.local.dialog.PlaylistCreationDialog;
import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.util.NavigationHelper;
@ -47,13 +47,15 @@ public final class QueueItemMenuUtil {
false);
return true;
case R.id.menu_item_append_playlist:
final PlaylistAppendDialog d = PlaylistAppendDialog.fromPlayQueueItems(
Collections.singletonList(item)
PlaylistDialog.createCorrespondingDialog(
context,
Collections.singletonList(new StreamEntity(item)),
dialog -> dialog.show(
fragmentManager,
"QueueItemMenuUtil@append_playlist"
)
);
PlaylistAppendDialog.onPlaylistFound(context,
() -> d.show(fragmentManager, "QueueItemMenuUtil@append_playlist"),
() -> PlaylistCreationDialog.newInstance(d)
.show(fragmentManager, "QueueItemMenuUtil@append_playlist"));
return true;
case R.id.menu_item_share:
shareText(context, item.getTitle(), item.getUrl(),

View File

@ -33,6 +33,7 @@ import androidx.core.widget.TextViewCompat;
import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager;
import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.databinding.ListRadioIconItemBinding;
import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding;
import org.schabi.newpipe.download.DownloadDialog;
@ -59,8 +60,7 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.local.dialog.PlaylistCreationDialog;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.player.MainPlayer;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.helper.PlayerHolder;
@ -82,6 +82,7 @@ import org.schabi.newpipe.views.FocusOverlayView;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import icepick.Icepick;
@ -593,31 +594,26 @@ public class RouterActivity extends AppCompatActivity {
disposables.add(ExtractorHelper.getStreamInfo(currentServiceId, currentUrl, false)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(info -> {
final FragmentManager fm = getSupportFragmentManager();
final PlaylistAppendDialog playlistAppendDialog = PlaylistAppendDialog
.fromStreamInfo(info);
.subscribe(
info -> PlaylistDialog.createCorrespondingDialog(
getThemeWrapperContext(),
Collections.singletonList(new StreamEntity(info)),
playlistDialog -> {
playlistDialog.setOnDismissListener(dialog -> finish());
playlistAppendDialog.setOnDismissListener(dialog -> finish());
PlaylistAppendDialog.onPlaylistFound(getThemeWrapperContext(),
() -> {
playlistAppendDialog.show(fm, "addToPlaylistDialog");
fm.executePendingTransactions();
},
() -> {
final PlaylistCreationDialog playlistCreationDialog =
PlaylistCreationDialog.newInstance(playlistAppendDialog);
playlistCreationDialog.show(fm, "addToPlaylistDialog");
fm.executePendingTransactions();
});
}, throwable -> handleError(this,
new ErrorInfo(throwable, UserAction.REQUESTED_STREAM,
playlistDialog.show(
this.getSupportFragmentManager(),
"addToPlaylistDialog"
);
}
),
throwable -> handleError(this, new ErrorInfo(
throwable,
UserAction.REQUESTED_STREAM,
"Tried to add " + currentUrl + " to a playlist",
currentService.getServiceId())))
currentService.getServiceId())
)
)
);
}

View File

@ -52,6 +52,7 @@ import com.squareup.picasso.Callback;
import org.schabi.newpipe.App;
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.databinding.FragmentVideoDetailBinding;
import org.schabi.newpipe.download.DownloadDialog;
import org.schabi.newpipe.error.ErrorActivity;
@ -73,8 +74,7 @@ import org.schabi.newpipe.fragments.EmptyFragment;
import org.schabi.newpipe.fragments.list.comments.CommentsFragment;
import org.schabi.newpipe.fragments.list.videos.RelatedItemsFragment;
import org.schabi.newpipe.ktx.AnimationType;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.local.dialog.PlaylistCreationDialog;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.player.MainPlayer;
import org.schabi.newpipe.player.MainPlayer.PlayerType;
@ -99,6 +99,7 @@ import org.schabi.newpipe.util.external_communication.KoreUtils;
import org.schabi.newpipe.util.external_communication.ShareUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@ -444,12 +445,11 @@ public final class VideoDetailFragment
break;
case R.id.detail_controls_playlist_append:
if (getFM() != null && currentInfo != null) {
final PlaylistAppendDialog d = PlaylistAppendDialog.fromStreamInfo(currentInfo);
disposables.add(
PlaylistAppendDialog.onPlaylistFound(getContext(),
() -> d.show(getFM(), TAG),
() -> PlaylistCreationDialog.newInstance(d).show(getFM(), TAG)
PlaylistDialog.createCorrespondingDialog(
getContext(),
Collections.singletonList(new StreamEntity(currentInfo)),
dialog -> dialog.show(getFM(), TAG)
)
);
}

View File

@ -1,8 +1,5 @@
package org.schabi.newpipe.local.dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@ -19,20 +16,14 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.database.LocalItem;
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.local.LocalItemListAdapter;
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.util.OnClickGesture;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
public final class PlaylistAppendDialog extends PlaylistDialog {
private static final String TAG = PlaylistAppendDialog.class.getCanonicalName();
@ -42,58 +33,8 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
private final CompositeDisposable playlistDisposables = new CompositeDisposable();
@Nullable
private OnDismissListener onDismissListener = null;
public static Disposable onPlaylistFound(
final Context context, final Runnable onSuccess, final Runnable onFailed
) {
final LocalPlaylistManager playlistManager =
new LocalPlaylistManager(NewPipeDatabase.getInstance(context));
return playlistManager.hasPlaylists()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(hasPlaylists -> {
if (hasPlaylists) {
onSuccess.run();
} else {
onFailed.run();
}
});
}
public static PlaylistAppendDialog fromStreamInfo(final StreamInfo info) {
final PlaylistAppendDialog dialog = new PlaylistAppendDialog();
dialog.setInfo(Collections.singletonList(new StreamEntity(info)));
return dialog;
}
public static PlaylistAppendDialog fromStreamInfoItems(final List<StreamInfoItem> items) {
final PlaylistAppendDialog dialog = new PlaylistAppendDialog();
final List<StreamEntity> entities = new ArrayList<>(items.size());
for (final StreamInfoItem item : items) {
entities.add(new StreamEntity(item));
}
dialog.setInfo(entities);
return dialog;
}
public static PlaylistAppendDialog fromPlayQueueItems(final List<PlayQueueItem> items) {
final PlaylistAppendDialog dialog = new PlaylistAppendDialog();
final List<StreamEntity> entities = new ArrayList<>(items.size());
for (final PlayQueueItem item : items) {
entities.add(new StreamEntity(item));
}
dialog.setInfo(entities);
return dialog;
}
public void setOnDismissListener(@Nullable final OnDismissListener onDismissListener) {
this.onDismissListener = onDismissListener;
}
public OnDismissListener getOnDismissListener() {
return onDismissListener;
public PlaylistAppendDialog(final List<StreamEntity> streamEntities) {
super(streamEntities);
}
/*//////////////////////////////////////////////////////////////////////////
@ -117,11 +58,15 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
playlistAdapter.setSelectedListener(new OnClickGesture<LocalItem>() {
@Override
public void selected(final LocalItem selectedItem) {
if (!(selectedItem instanceof PlaylistMetadataEntry) || getStreams() == null) {
if (!(selectedItem instanceof PlaylistMetadataEntry)
|| getStreamEntities() == null) {
return;
}
onPlaylistSelected(playlistManager, (PlaylistMetadataEntry) selectedItem,
getStreams());
onPlaylistSelected(
playlistManager,
(PlaylistMetadataEntry) selectedItem,
getStreamEntities()
);
}
});
@ -154,29 +99,22 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
playlistAdapter = null;
}
@Override
public void onDismiss(@NonNull final DialogInterface dialog) {
super.onDismiss(dialog);
if (onDismissListener != null) {
onDismissListener.onDismiss(dialog);
}
}
/*//////////////////////////////////////////////////////////////////////////
// Helper
//////////////////////////////////////////////////////////////////////////*/
public void openCreatePlaylistDialog() {
if (getStreams() == null || !isAdded()) {
if (getStreamEntities() == null || !isAdded()) {
return;
}
final PlaylistCreationDialog dialog = PlaylistCreationDialog.newInstance(getStreams());
final PlaylistCreationDialog playlistCreationDialog =
new PlaylistCreationDialog(getStreamEntities());
// Move the dismissListener to the new dialog.
dialog.setOnDismissListener(this.onDismissListener);
this.onDismissListener = null;
playlistCreationDialog.setOnDismissListener(this.getOnDismissListener());
this.setOnDismissListener(null);
dialog.show(getParentFragmentManager(), TAG);
playlistCreationDialog.show(getParentFragmentManager(), TAG);
requireDialog().dismiss();
}
@ -191,7 +129,7 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
private void onPlaylistSelected(@NonNull final LocalPlaylistManager manager,
@NonNull final PlaylistMetadataEntry playlist,
@NonNull final List<StreamEntity> streams) {
if (getStreams() == null) {
if (getStreamEntities() == null) {
return;
}

View File

@ -1,8 +1,6 @@
package org.schabi.newpipe.local.dialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.os.Bundle;
import android.text.InputType;
import android.widget.Toast;
@ -23,32 +21,8 @@ import java.util.List;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
public final class PlaylistCreationDialog extends PlaylistDialog {
@Nullable
private OnDismissListener onDismissListener = null;
public static PlaylistCreationDialog newInstance(final List<StreamEntity> streams) {
final PlaylistCreationDialog dialog = new PlaylistCreationDialog();
dialog.setInfo(streams);
return dialog;
}
public static PlaylistCreationDialog newInstance(final PlaylistAppendDialog appendDialog) {
final PlaylistCreationDialog dialog = new PlaylistCreationDialog();
dialog.setInfo(appendDialog.getStreams());
dialog.setOnDismissListener(appendDialog.getOnDismissListener());
return dialog;
}
public void setOnDismissListener(@Nullable final OnDismissListener onDismissListener) {
this.onDismissListener = onDismissListener;
}
@Override
public void onDismiss(@NonNull final DialogInterface dialog) {
super.onDismiss(dialog);
if (onDismissListener != null) {
onDismissListener.onDismiss(dialog);
}
public PlaylistCreationDialog(final List<StreamEntity> streamEntities) {
super(streamEntities);
}
/*//////////////////////////////////////////////////////////////////////////
@ -58,7 +32,7 @@ public final class PlaylistCreationDialog extends PlaylistDialog {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
if (getStreams() == null) {
if (getStreamEntities() == null) {
return super.onCreateDialog(savedInstanceState);
}
@ -81,7 +55,7 @@ public final class PlaylistCreationDialog extends PlaylistDialog {
R.string.playlist_creation_success,
Toast.LENGTH_SHORT);
playlistManager.createPlaylist(name, getStreams())
playlistManager.createPlaylist(name, getStreamEntities())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(longs -> successToast.show());
});

View File

@ -1,6 +1,8 @@
package org.schabi.newpipe.local.dialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.Window;
@ -8,23 +10,29 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
import org.schabi.newpipe.util.StateSaver;
import java.util.List;
import java.util.Queue;
import java.util.function.Consumer;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.Disposable;
public abstract class PlaylistDialog extends DialogFragment implements StateSaver.WriteRead {
@Nullable
private DialogInterface.OnDismissListener onDismissListener = null;
private List<StreamEntity> streamEntities;
private org.schabi.newpipe.util.SavedState savedState;
protected void setInfo(final List<StreamEntity> entities) {
this.streamEntities = entities;
}
protected List<StreamEntity> getStreams() {
return streamEntities;
public PlaylistDialog(final List<StreamEntity> streamEntities) {
this.streamEntities = streamEntities;
}
/*//////////////////////////////////////////////////////////////////////////
@ -43,6 +51,10 @@ public abstract class PlaylistDialog extends DialogFragment implements StateSave
StateSaver.onDestroy(savedState);
}
public List<StreamEntity> getStreamEntities() {
return streamEntities;
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
@ -55,6 +67,14 @@ public abstract class PlaylistDialog extends DialogFragment implements StateSave
return dialog;
}
@Override
public void onDismiss(@NonNull final DialogInterface dialog) {
super.onDismiss(dialog);
if (onDismissListener != null) {
onDismissListener.onDismiss(dialog);
}
}
/*//////////////////////////////////////////////////////////////////////////
// State Saving
//////////////////////////////////////////////////////////////////////////*/
@ -84,4 +104,47 @@ public abstract class PlaylistDialog extends DialogFragment implements StateSave
savedState, outState, this);
}
}
/*//////////////////////////////////////////////////////////////////////////
// Getter + Setter
//////////////////////////////////////////////////////////////////////////*/
@Nullable
public DialogInterface.OnDismissListener getOnDismissListener() {
return onDismissListener;
}
public void setOnDismissListener(
@Nullable final DialogInterface.OnDismissListener onDismissListener
) {
this.onDismissListener = onDismissListener;
}
/*//////////////////////////////////////////////////////////////////////////
// Dialog creation
//////////////////////////////////////////////////////////////////////////*/
/**
* Creates a {@link PlaylistAppendDialog} when playlists exists,
* otherwise a {@link PlaylistCreationDialog}.
*
* @param context context used for accessing the database
* @param streamEntities used for crating the dialog
* @param onExec execution that should occur after a dialog got created, e.g. showing it
* @return Disposable
*/
public static Disposable createCorrespondingDialog(
final Context context,
final List<StreamEntity> streamEntities,
final Consumer<PlaylistDialog> onExec
) {
return new LocalPlaylistManager(NewPipeDatabase.getInstance(context))
.hasPlaylists()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(hasPlaylists ->
onExec.accept(hasPlaylists
? new PlaylistAppendDialog(streamEntities)
: new PlaylistCreationDialog(streamEntities))
);
}
}

View File

@ -23,11 +23,11 @@ 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.PlaylistAppendDialog;
import org.schabi.newpipe.local.dialog.PlaylistCreationDialog;
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;
@ -43,6 +43,7 @@ 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;
@ -452,12 +453,12 @@ public final class PlayQueueActivity extends AppCompatActivity
}
}
private void openPlaylistAppendDialog(final List<PlayQueueItem> playlist) {
final PlaylistAppendDialog d = PlaylistAppendDialog.fromPlayQueueItems(playlist);
PlaylistAppendDialog.onPlaylistFound(getApplicationContext(),
() -> d.show(getSupportFragmentManager(), TAG),
() -> PlaylistCreationDialog.newInstance(d).show(getSupportFragmentManager(), TAG));
private void openPlaylistAppendDialog(final List<PlayQueueItem> playQueueItems) {
PlaylistDialog.createCorrespondingDialog(
getApplicationContext(),
playQueueItems.stream().map(StreamEntity::new).collect(Collectors.toList()),
dialog -> dialog.show(getSupportFragmentManager(), TAG)
);
}
////////////////////////////////////////////////////////////////////////////

View File

@ -8,9 +8,10 @@ import androidx.fragment.app.Fragment;
import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.local.dialog.PlaylistCreationDialog;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.util.external_communication.KoreUtils;
@ -82,13 +83,15 @@ public enum StreamDialogEntry {
}), // has to be set manually
append_playlist(R.string.add_to_playlist, (fragment, item) -> {
final PlaylistAppendDialog d = PlaylistAppendDialog
.fromStreamInfoItems(Collections.singletonList(item));
PlaylistAppendDialog.onPlaylistFound(fragment.getContext(),
() -> d.show(fragment.getParentFragmentManager(), "StreamDialogEntry@append_playlist"),
() -> PlaylistCreationDialog.newInstance(d)
.show(fragment.getParentFragmentManager(), "StreamDialogEntry@create_playlist")
PlaylistDialog.createCorrespondingDialog(
fragment.getContext(),
Collections.singletonList(new StreamEntity(item)),
dialog -> dialog.show(
fragment.getParentFragmentManager(),
"StreamDialogEntry@"
+ (dialog instanceof PlaylistAppendDialog ? "append" : "create")
+ "_playlist"
)
);
}),