Add a add to playlist option in the share menu.

This commit is contained in:
Kalle Struik 2021-10-02 19:21:25 +02:00
parent 2e3e7f9bf2
commit d844e0aba6
5 changed files with 103 additions and 6 deletions

View File

@ -1,5 +1,8 @@
package org.schabi.newpipe; package org.schabi.newpipe;
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO;
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.VIDEO;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.IntentService; import android.app.IntentService;
import android.content.Context; import android.content.Context;
@ -56,6 +59,8 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.ktx.ExceptionUtils; import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.local.dialog.PlaylistCreationDialog;
import org.schabi.newpipe.player.MainPlayer; import org.schabi.newpipe.player.MainPlayer;
import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.helper.PlayerHolder; import org.schabi.newpipe.player.helper.PlayerHolder;
@ -69,8 +74,8 @@ import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.util.urlfinder.UrlFinder; import org.schabi.newpipe.util.urlfinder.UrlFinder;
import org.schabi.newpipe.views.FocusOverlayView; import org.schabi.newpipe.views.FocusOverlayView;
@ -89,9 +94,6 @@ import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO;
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.VIDEO;
/** /**
* Get the url from the intent and open it in the chosen preferred player. * Get the url from the intent and open it in the chosen preferred player.
*/ */
@ -107,6 +109,7 @@ public class RouterActivity extends AppCompatActivity {
protected String currentUrl; protected String currentUrl;
private StreamingService currentService; private StreamingService currentService;
private boolean selectionIsDownload = false; private boolean selectionIsDownload = false;
private boolean selectionIsAddToPlaylist = false;
private AlertDialog alertDialogChoice = null; private AlertDialog alertDialogChoice = null;
@Override @Override
@ -350,7 +353,7 @@ public class RouterActivity extends AppCompatActivity {
.setNegativeButton(R.string.just_once, dialogButtonsClickListener) .setNegativeButton(R.string.just_once, dialogButtonsClickListener)
.setPositiveButton(R.string.always, dialogButtonsClickListener) .setPositiveButton(R.string.always, dialogButtonsClickListener)
.setOnDismissListener((dialog) -> { .setOnDismissListener((dialog) -> {
if (!selectionIsDownload) { if (!selectionIsDownload && !selectionIsAddToPlaylist) {
finish(); finish();
} }
}) })
@ -446,6 +449,10 @@ public class RouterActivity extends AppCompatActivity {
final AdapterChoiceItem backgroundPlayer = new AdapterChoiceItem( final AdapterChoiceItem backgroundPlayer = new AdapterChoiceItem(
getString(R.string.background_player_key), getString(R.string.background_player), getString(R.string.background_player_key), getString(R.string.background_player),
R.drawable.ic_headset); R.drawable.ic_headset);
final AdapterChoiceItem addToPlaylist = new AdapterChoiceItem(
getString(R.string.add_to_playlist_key), getString(R.string.add_to_playlist),
R.drawable.ic_add);
if (linkType == LinkType.STREAM) { if (linkType == LinkType.STREAM) {
if (isExtVideoEnabled) { if (isExtVideoEnabled) {
@ -482,6 +489,10 @@ public class RouterActivity extends AppCompatActivity {
getString(R.string.download), getString(R.string.download),
R.drawable.ic_file_download)); R.drawable.ic_file_download));
// Add to playlist is not necessary for CHANNEL and PLAYLIST linkType since those can
// not be added to a playlist
returnList.add(addToPlaylist);
} else { } else {
returnList.add(showInfo); returnList.add(showInfo);
if (capabilities.contains(VIDEO) && !isExtVideoEnabled) { if (capabilities.contains(VIDEO) && !isExtVideoEnabled) {
@ -547,6 +558,12 @@ public class RouterActivity extends AppCompatActivity {
return; return;
} }
if (selectedChoiceKey.equals(getString(R.string.add_to_playlist_key))) {
selectionIsAddToPlaylist = true;
openAddToPlaylistDialog();
return;
}
// stop and bypass FetcherService if InfoScreen was selected since // stop and bypass FetcherService if InfoScreen was selected since
// StreamDetailFragment can fetch data itself // StreamDetailFragment can fetch data itself
if (selectedChoiceKey.equals(getString(R.string.show_info_key))) { if (selectedChoiceKey.equals(getString(R.string.show_info_key))) {
@ -572,6 +589,38 @@ public class RouterActivity extends AppCompatActivity {
finish(); finish();
} }
private void openAddToPlaylistDialog() {
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);
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,
"Tried to add " + currentUrl + " to a playlist",
currentService.getServiceId())))
);
}
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
private void openDownloadDialog() { private void openDownloadDialog() {
disposables.add(ExtractorHelper.getStreamInfo(currentServiceId, currentUrl, true) disposables.add(ExtractorHelper.getStreamInfo(currentServiceId, currentUrl, true)

View File

@ -1,6 +1,8 @@
package org.schabi.newpipe.local.dialog; package org.schabi.newpipe.local.dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -40,6 +42,9 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
private final CompositeDisposable playlistDisposables = new CompositeDisposable(); private final CompositeDisposable playlistDisposables = new CompositeDisposable();
@Nullable
private OnDismissListener onDismissListener = null;
public static Disposable onPlaylistFound( public static Disposable onPlaylistFound(
final Context context, final Runnable onSuccess, final Runnable onFailed final Context context, final Runnable onSuccess, final Runnable onFailed
) { ) {
@ -83,6 +88,14 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
return dialog; return dialog;
} }
public void setOnDismissListener(@Nullable final OnDismissListener onDismissListener) {
this.onDismissListener = onDismissListener;
}
public OnDismissListener getOnDismissListener() {
return onDismissListener;
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// LifeCycle - Creation // LifeCycle - Creation
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -141,6 +154,14 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
playlistAdapter = null; playlistAdapter = null;
} }
@Override
public void onDismiss(@NonNull final DialogInterface dialog) {
super.onDismiss(dialog);
if (onDismissListener != null) {
onDismissListener.onDismiss(dialog);
}
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Helper // Helper
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -150,7 +171,12 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
return; return;
} }
PlaylistCreationDialog.newInstance(getStreams()).show(getParentFragmentManager(), TAG); final PlaylistCreationDialog dialog = PlaylistCreationDialog.newInstance(getStreams());
// Move the dismissListener to the new dialog.
dialog.setOnDismissListener(this.onDismissListener);
this.onDismissListener = null;
dialog.show(getParentFragmentManager(), TAG);
requireDialog().dismiss(); requireDialog().dismiss();
} }

View File

@ -1,6 +1,8 @@
package org.schabi.newpipe.local.dialog; package org.schabi.newpipe.local.dialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.os.Bundle; import android.os.Bundle;
import android.text.InputType; import android.text.InputType;
import android.widget.Toast; import android.widget.Toast;
@ -20,6 +22,9 @@ import java.util.List;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
public final class PlaylistCreationDialog extends PlaylistDialog { public final class PlaylistCreationDialog extends PlaylistDialog {
@Nullable
private OnDismissListener onDismissListener = null;
public static PlaylistCreationDialog newInstance(final List<StreamEntity> streams) { public static PlaylistCreationDialog newInstance(final List<StreamEntity> streams) {
final PlaylistCreationDialog dialog = new PlaylistCreationDialog(); final PlaylistCreationDialog dialog = new PlaylistCreationDialog();
dialog.setInfo(streams); dialog.setInfo(streams);
@ -29,9 +34,22 @@ public final class PlaylistCreationDialog extends PlaylistDialog {
public static PlaylistCreationDialog newInstance(final PlaylistAppendDialog appendDialog) { public static PlaylistCreationDialog newInstance(final PlaylistAppendDialog appendDialog) {
final PlaylistCreationDialog dialog = new PlaylistCreationDialog(); final PlaylistCreationDialog dialog = new PlaylistCreationDialog();
dialog.setInfo(appendDialog.getStreams()); dialog.setInfo(appendDialog.getStreams());
dialog.setOnDismissListener(appendDialog.getOnDismissListener());
return dialog; 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);
}
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Dialog // Dialog
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/

View File

@ -360,6 +360,7 @@
<string name="popup_player_key" translatable="false">popup_player</string> <string name="popup_player_key" translatable="false">popup_player</string>
<string name="download_key" translatable="false">download</string> <string name="download_key" translatable="false">download</string>
<string name="always_ask_open_action_key" translatable="false">always_ask_player</string> <string name="always_ask_open_action_key" translatable="false">always_ask_player</string>
<string name="add_to_playlist_key" translatable="false">add_to_playlist</string>
<string-array name="preferred_open_action_description_list" translatable="false"> <string-array name="preferred_open_action_description_list" translatable="false">
<item>@string/show_info</item> <item>@string/show_info</item>
@ -368,6 +369,7 @@
<item>@string/popup_player</item> <item>@string/popup_player</item>
<item>@string/download</item> <item>@string/download</item>
<item>@string/always_ask_open_action</item> <item>@string/always_ask_open_action</item>
<item>@string/add_to_playlist</item>
</string-array> </string-array>
<string-array name="preferred_open_action_values_list" translatable="false"> <string-array name="preferred_open_action_values_list" translatable="false">
<item>@string/show_info_key</item> <item>@string/show_info_key</item>
@ -376,6 +378,7 @@
<item>@string/popup_player_key</item> <item>@string/popup_player_key</item>
<item>@string/download_key</item> <item>@string/download_key</item>
<item>@string/always_ask_open_action_key</item> <item>@string/always_ask_open_action_key</item>
<item>@string/add_to_playlist_key</item>
</string-array> </string-array>
<!-- Updates --> <!-- Updates -->

View File

@ -433,6 +433,7 @@
<string name="background_player">Background player</string> <string name="background_player">Background player</string>
<string name="popup_player">Popup player</string> <string name="popup_player">Popup player</string>
<string name="always_ask_open_action">Always ask</string> <string name="always_ask_open_action">Always ask</string>
<string name="add_to_playlist">Add to playlist</string>
<string name="preferred_player_fetcher_notification_title">Getting info…</string> <string name="preferred_player_fetcher_notification_title">Getting info…</string>
<string name="preferred_player_fetcher_notification_message">"Loading requested content"</string> <string name="preferred_player_fetcher_notification_message">"Loading requested content"</string>
<!-- Local Playlist --> <!-- Local Playlist -->