From 80157fc1be921beda9051879dfbe1b9ef95e6075 Mon Sep 17 00:00:00 2001
From: TobiGr Builder to generate a {@link InfoItemDialog}. Create an instance of this Builder Change an entries' action that is called when the entry is selected. Warning: Only use this method when the entry has been already added.
+ * Changing the action of an entry which has not been added to the Builder yet
+ * does not have an effect. Create a Builder instance that automatically adds the some default entries
+ * at the top and bottom of the dialog. Create an instance of this Builder Create an instance of this Builder. If {@code addDefaultEntriesAutomatically} is set to {@code true},
+ * some default entries are added to the top and bottom of the dialog.
+ * Custom actions for entries can be set using
+ * {@link #setAction(StreamDialogDefaultEntry, StreamDialogEntry.StreamDialogEntryAction)}.
+ */
+ public static class Builder {
+ @NonNull private final Activity activity;
+ @NonNull private final StreamInfoItem info;
+ @NonNull private final Fragment fragment;
+ @NonNull private final List, Void> {
// Save the list 10 seconds after the last change occurred
private static final long SAVE_DEBOUNCE_MILLIS = 10000;
@@ -751,62 +747,33 @@ public class LocalPlaylistFragment extends BaseLocalListFragment
entries = new ArrayList<>();
+ final InfoItemDialog.Builder dialogBuilder = new InfoItemDialog.Builder(
+ activity, this, infoItem);
- if (PlayerHolder.getInstance().isPlayQueueReady()) {
- entries.add(StreamDialogEntry.enqueue);
+ dialogBuilder.addEnqueueEntriesIfNeeded();
+ dialogBuilder.addStartHereEntries();
+ dialogBuilder.addAllEntries(
+ StreamDialogDefaultEntry.SET_AS_PLAYLIST_THUMBNAIL,
+ StreamDialogDefaultEntry.DELETE,
+ StreamDialogDefaultEntry.APPEND_PLAYLIST,
+ StreamDialogDefaultEntry.SHARE,
+ StreamDialogDefaultEntry.OPEN_IN_BROWSER
+ );
+ dialogBuilder.addPlayWithKodiEntryIfNeeded();
+ dialogBuilder.addMarkAsWatchedEntryIfNeeded(infoItem.getStreamType());
+ dialogBuilder.addChannelDetailsEntryIfPossible();
- if (PlayerHolder.getInstance().getQueueSize() > 1) {
- entries.add(StreamDialogEntry.enqueue_next);
- }
- }
- if (infoItem.getStreamType() == StreamType.AUDIO_STREAM) {
- entries.addAll(Arrays.asList(
- StreamDialogEntry.start_here_on_background,
- StreamDialogEntry.set_as_playlist_thumbnail,
- StreamDialogEntry.delete,
- StreamDialogEntry.append_playlist,
- StreamDialogEntry.share
- ));
- } else {
- entries.addAll(Arrays.asList(
- StreamDialogEntry.start_here_on_background,
- StreamDialogEntry.start_here_on_popup,
- StreamDialogEntry.set_as_playlist_thumbnail,
- StreamDialogEntry.delete,
- StreamDialogEntry.append_playlist,
- StreamDialogEntry.share
- ));
- }
- entries.add(StreamDialogEntry.open_in_browser);
- if (KoreUtils.shouldShowPlayWithKodi(context, infoItem.getServiceId())) {
- entries.add(StreamDialogEntry.play_with_kodi);
- }
-
- // show "mark as watched" only when watch history is enabled
- if (StreamDialogEntry.shouldAddMarkAsWatched(
- item.getStreamEntity().getStreamType(),
- context
- )) {
- entries.add(
- StreamDialogEntry.mark_as_watched
- );
- }
- entries.add(StreamDialogEntry.show_channel_details);
-
- StreamDialogEntry.setEnabledEntries(entries);
-
- StreamDialogEntry.start_here_on_background.setCustomAction((fragment, infoItemDuplicate) ->
- NavigationHelper.playOnBackgroundPlayer(context,
- getPlayQueueStartingAt(item), true));
- StreamDialogEntry.set_as_playlist_thumbnail.setCustomAction(
+ // set custom actions
+ dialogBuilder.setAction(StreamDialogDefaultEntry.START_HERE_ON_BACKGROUND,
+ (fragment, infoItemDuplicate) -> NavigationHelper.playOnBackgroundPlayer(
+ context, getPlayQueueStartingAt(item), true));
+ dialogBuilder.setAction(StreamDialogDefaultEntry.SET_AS_PLAYLIST_THUMBNAIL,
(fragment, infoItemDuplicate) ->
changeThumbnailUrl(item.getStreamEntity().getThumbnailUrl()));
- StreamDialogEntry.delete.setCustomAction((fragment, infoItemDuplicate) ->
- deleteItem(item));
+ dialogBuilder.setAction(StreamDialogDefaultEntry.DELETE,
+ (fragment, infoItemDuplicate) -> deleteItem(item));
- new InfoItemDialog(activity, infoItem, StreamDialogEntry.getCommands(context),
- (dialog, which) -> StreamDialogEntry.clickOn(which, this, infoItem)).show();
+ dialogBuilder.create().show();
}
private void setInitialData(final long pid, final String title) {
diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java
new file mode 100644
index 000000000..435a32219
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java
@@ -0,0 +1,151 @@
+package org.schabi.newpipe.util;
+
+import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
+
+import android.net.Uri;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+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.PlaylistDialog;
+import org.schabi.newpipe.local.history.HistoryRecordManager;
+import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
+import org.schabi.newpipe.util.external_communication.KoreUtils;
+import org.schabi.newpipe.util.external_communication.ShareUtils;
+
+import java.util.Collections;
+
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
+import io.reactivex.rxjava3.schedulers.Schedulers;
+
+public enum StreamDialogDefaultEntry {
+ //////////////////////////////////////
+ // enum values with DEFAULT actions //
+ //////////////////////////////////////
+
+ SHOW_CHANNEL_DETAILS(R.string.show_channel_details, (fragment, item) -> {
+ if (isNullOrEmpty(item.getUploaderUrl())) {
+ final int serviceId = item.getServiceId();
+ final String url = item.getUrl();
+ Toast.makeText(fragment.getContext(), R.string.loading_channel_details,
+ Toast.LENGTH_SHORT).show();
+ ExtractorHelper.getStreamInfo(serviceId, url, false)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> {
+ NewPipeDatabase.getInstance(fragment.requireContext()).streamDAO()
+ .setUploaderUrl(serviceId, url, result.getUploaderUrl())
+ .subscribeOn(Schedulers.io()).subscribe();
+ openChannelFragment(fragment, item, result.getUploaderUrl());
+ }, throwable -> Toast.makeText(
+ // TODO: Open the Error Activity
+ fragment.getContext(),
+ R.string.error_show_channel_details,
+ Toast.LENGTH_SHORT
+ ).show());
+ } else {
+ openChannelFragment(fragment, item, item.getUploaderUrl());
+ }
+ }),
+
+ /**
+ * Enqueues the stream automatically to the current PlayerType.
+ *
+ * Info: Add this entry within showStreamDialog.
+ */
+ ENQUEUE(R.string.enqueue_stream, (fragment, item) ->
+ NavigationHelper.enqueueOnPlayer(fragment.getContext(), new SinglePlayQueue(item))
+ ),
+
+ ENQUEUE_NEXT(R.string.enqueue_next_stream, (fragment, item) ->
+ NavigationHelper.enqueueNextOnPlayer(fragment.getContext(), new SinglePlayQueue(item))
+ ),
+
+ START_HERE_ON_BACKGROUND(R.string.start_here_on_background, (fragment, item) ->
+ NavigationHelper.playOnBackgroundPlayer(fragment.getContext(),
+ new SinglePlayQueue(item), true)),
+
+ START_HERE_ON_POPUP(R.string.start_here_on_popup, (fragment, item) ->
+ NavigationHelper.playOnPopupPlayer(fragment.getContext(),
+ new SinglePlayQueue(item), true)),
+
+ SET_AS_PLAYLIST_THUMBNAIL(R.string.set_as_playlist_thumbnail, (fragment, item) -> {
+ }), // has to be set manually
+
+ DELETE(R.string.delete, (fragment, item) -> {
+ }), // has to be set manually
+
+ APPEND_PLAYLIST(R.string.add_to_playlist, (fragment, item) ->
+ PlaylistDialog.createCorrespondingDialog(
+ fragment.getContext(),
+ Collections.singletonList(new StreamEntity(item)),
+ dialog -> dialog.show(
+ fragment.getParentFragmentManager(),
+ "StreamDialogEntry@"
+ + (dialog instanceof PlaylistAppendDialog ? "append" : "create")
+ + "_playlist"
+ )
+ )
+ ),
+
+ PLAY_WITH_KODI(R.string.play_with_kodi_title, (fragment, item) -> {
+ final Uri videoUrl = Uri.parse(item.getUrl());
+ try {
+ NavigationHelper.playWithKore(fragment.requireContext(), videoUrl);
+ } catch (final Exception e) {
+ KoreUtils.showInstallKoreDialog(fragment.requireActivity());
+ }
+ }),
+
+ SHARE(R.string.share, (fragment, item) ->
+ ShareUtils.shareText(fragment.requireContext(), item.getName(), item.getUrl(),
+ item.getThumbnailUrl())),
+
+ OPEN_IN_BROWSER(R.string.open_in_browser, (fragment, item) ->
+ ShareUtils.openUrlInBrowser(fragment.requireContext(), item.getUrl())),
+
+
+ MARK_AS_WATCHED(R.string.mark_as_watched, (fragment, item) ->
+ new HistoryRecordManager(fragment.getContext())
+ .markAsWatched(item)
+ .onErrorComplete()
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe()
+ );
+
+
+ @StringRes
+ public final int resource;
+ @NonNull
+ public final StreamDialogEntry.StreamDialogEntryAction action;
+ StreamDialogDefaultEntry(@StringRes final int resource,
+ @NonNull final StreamDialogEntry.StreamDialogEntryAction action) {
+ this.resource = resource;
+ this.action = action;
+ }
+
+ @NonNull
+ public StreamDialogEntry toStreamDialogEntry() {
+ return new StreamDialogEntry(resource, action);
+ }
+
+ /////////////////////////////////////////////
+ // private method to open channel fragment //
+ /////////////////////////////////////////////
+
+ private static void openChannelFragment(@NonNull final Fragment fragment,
+ @NonNull final StreamInfoItem item,
+ final String uploaderUrl) {
+ // For some reason `getParentFragmentManager()` doesn't work, but this does.
+ NavigationHelper.openChannelFragment(
+ fragment.requireActivity().getSupportFragmentManager(),
+ item.getServiceId(), uploaderUrl, item.getUploaderName());
+ }
+}
diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java
index 1b4c8046c..bb59d0f29 100644
--- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java
+++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java
@@ -1,238 +1,36 @@
package org.schabi.newpipe.util;
import android.content.Context;
-import android.net.Uri;
-import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
-import androidx.preference.PreferenceManager;
-import org.schabi.newpipe.R;
-import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
-import org.schabi.newpipe.extractor.stream.StreamType;
-import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
-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;
-import org.schabi.newpipe.util.external_communication.ShareUtils;
-import java.util.Collections;
-import java.util.List;
import java.util.function.Consumer;
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
-import io.reactivex.rxjava3.schedulers.Schedulers;
+import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
-public enum StreamDialogEntry {
- //////////////////////////////////////
- // enum values with DEFAULT actions //
- //////////////////////////////////////
+public class StreamDialogEntry {
- show_channel_details(R.string.show_channel_details, (fragment, item) -> {
- SaveUploaderUrlHelper.saveUploaderUrlIfNeeded(fragment, item,
- uploaderUrl -> openChannelFragment(fragment, item, uploaderUrl));
- }),
+ @StringRes
+ public final int resource;
+ @NonNull
+ public final StreamDialogEntryAction action;
- /**
- * Enqueues the stream automatically to the current PlayerType.
- *
- * Info: Add this entry within showStreamDialog.
- */
- enqueue(R.string.enqueue_stream, (fragment, item) -> {
- fetchItemInfoIfSparse(fragment, item, fullItem ->
- NavigationHelper.enqueueOnPlayer(fragment.getContext(), fullItem));
- }),
-
- enqueue_next(R.string.enqueue_next_stream, (fragment, item) -> {
- fetchItemInfoIfSparse(fragment, item, fullItem ->
- NavigationHelper.enqueueNextOnPlayer(fragment.getContext(), fullItem));
- }),
-
- start_here_on_background(R.string.start_here_on_background, (fragment, item) -> {
- fetchItemInfoIfSparse(fragment, item, fullItem ->
- NavigationHelper.playOnBackgroundPlayer(fragment.getContext(), fullItem, true));
- }),
-
- start_here_on_popup(R.string.start_here_on_popup, (fragment, item) -> {
- fetchItemInfoIfSparse(fragment, item, fullItem ->
- NavigationHelper.playOnPopupPlayer(fragment.getContext(), fullItem, true));
- }),
-
- set_as_playlist_thumbnail(R.string.set_as_playlist_thumbnail, (fragment, item) -> {
- }), // has to be set manually
-
- delete(R.string.delete, (fragment, item) -> {
- }), // has to be set manually
-
- append_playlist(R.string.add_to_playlist, (fragment, item) -> {
- PlaylistDialog.createCorrespondingDialog(
- fragment.getContext(),
- Collections.singletonList(new StreamEntity(item)),
- dialog -> dialog.show(
- fragment.getParentFragmentManager(),
- "StreamDialogEntry@"
- + (dialog instanceof PlaylistAppendDialog ? "append" : "create")
- + "_playlist"
- )
- );
- }),
-
- play_with_kodi(R.string.play_with_kodi_title, (fragment, item) -> {
- final Uri videoUrl = Uri.parse(item.getUrl());
- try {
- NavigationHelper.playWithKore(fragment.requireContext(), videoUrl);
- } catch (final Exception e) {
- KoreUtils.showInstallKoreDialog(fragment.requireActivity());
- }
- }),
-
- share(R.string.share, (fragment, item) ->
- ShareUtils.shareText(fragment.requireContext(), item.getName(), item.getUrl(),
- item.getThumbnailUrl())),
-
- open_in_browser(R.string.open_in_browser, (fragment, item) ->
- ShareUtils.openUrlInBrowser(fragment.requireContext(), item.getUrl())),
-
-
- mark_as_watched(R.string.mark_as_watched, (fragment, item) -> {
- new HistoryRecordManager(fragment.getContext())
- .markAsWatched(item)
- .onErrorComplete()
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe();
- });
-
- ///////////////
- // variables //
- ///////////////
-
- private static StreamDialogEntry[] enabledEntries;
- private final int resource;
- private final StreamDialogEntryAction defaultAction;
- private StreamDialogEntryAction customAction;
-
- StreamDialogEntry(final int resource, final StreamDialogEntryAction defaultAction) {
+ public StreamDialogEntry(@StringRes final int resource,
+ @NonNull final StreamDialogEntryAction action) {
this.resource = resource;
- this.defaultAction = defaultAction;
- this.customAction = null;
+ this.action = action;
}
-
- ///////////////////////////////////////////////////////
- // non-static methods to initialize and edit entries //
- ///////////////////////////////////////////////////////
-
- public static void setEnabledEntries(final List
Date: Thu, 23 Dec 2021 00:33:34 +0100
Subject: [PATCH 03/11] Add default entries automatically
---
.../fragments/list/BaseListFragment.java | 8 +--
.../list/playlist/PlaylistFragment.java | 3 -
.../newpipe/info_list/InfoItemDialog.java | 62 ++++++++++++++-----
.../schabi/newpipe/local/feed/FeedFragment.kt | 7 +--
.../history/StatisticsPlaylistFragment.java | 4 +-
.../local/playlist/LocalPlaylistFragment.java | 6 +-
6 files changed, 53 insertions(+), 37 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java
index 1129baaec..4b5c260e0 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java
@@ -409,13 +409,7 @@ public abstract class BaseListFragment extends BaseStateFragment
return;
}
- final InfoItemDialog.Builder dialogBuilder = new InfoItemDialog.Builder(
- activity, this, item);
-
- dialogBuilder.addDefaultEntriesAtBeginning();
- dialogBuilder.addDefaultEntriesAtEnd();
-
- dialogBuilder.create().show();
+ new InfoItemDialog.Builder(activity, this, item).create().show();
}
/*//////////////////////////////////////////////////////////////////////////
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
index 26498f61a..14d77b31d 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
@@ -145,9 +145,6 @@ public class PlaylistFragment extends BaseListInfoFragment
NavigationHelper.playOnBackgroundPlayer(
context, getPlayQueueStartingAt(item), true));
From 962fe9c36d6ee83235da757533d6119ed610790c Mon Sep 17 00:00:00 2001
From: TobiGr
+ * + - - - - - - - - - - - - - - - - - - - - - -+
+ * | ENQUEUE |
+ * | ENQUEUE_HERE |
+ * | START_ON_BACKGROUND |
+ * | START_ON_POPUP |
+ * + - - - - - - - - - - - - - - - - - - - - - -+
+ * | entries added manually with |
+ * | addEntry() and addAllEntries() |
+ * + - - - - - - - - - - - - - - - - - - - - - -+
+ * | APPEND_PLAYLIST |
+ * | SHARE |
+ * | OPEN_IN_BROWSER |
+ * | PLAY_WITH_KODI |
+ * | MARK_AS_WATCHED |
+ * | SHOW_CHANNEL_DETAILS |
+ * + - - - - - - - - - - - - - - - - - - - - - -+
+ *
+ * Please note that some entries are not added depending on the user's preferences,
+ * the item's {@link StreamType} and the current player state.
+ *
+ * @param activity
+ * @param context
+ * @param fragment
+ * @param infoItem the item for this dialog; all entries and their actions work with
+ * this {@link org.schabi.newpipe.extractor.InfoItem}
+ */
public Builder(@NonNull final Activity activity,
+ @NonNull final Context context,
@NonNull final Fragment fragment,
@NonNull final StreamInfoItem infoItem) {
- this(activity, fragment, infoItem, true);
+ this(activity, context, fragment, infoItem, true);
}
/**
- *
+ * + - - - - - - - - - - - - - - - - - - - - - -+
+ * | ENQUEUE |
+ * | ENQUEUE_HERE |
+ * | START_ON_BACKGROUND |
+ * | START_ON_POPUP |
+ * + - - - - - - - - - - - - - - - - - - - - - -+
+ * | entries added manually with |
+ * | addEntry() and addAllEntries() |
+ * + - - - - - - - - - - - - - - - - - - - - - -+
+ * | APPEND_PLAYLIST |
+ * | SHARE |
+ * | OPEN_IN_BROWSER |
+ * | PLAY_WITH_KODI |
+ * | MARK_AS_WATCHED |
+ * | SHOW_CHANNEL_DETAILS |
+ * + - - - - - - - - - - - - - - - - - - - - - -+
+ *
+ * Please note that some entries are not added depending on the user's preferences,
+ * the item's {@link StreamType} and the current player state.
+ *
* @param activity
+ * @param context
* @param fragment
* @param infoItem
- * @param addDefaultEntriesAutomatically whether default entries added with
- * {@link #addDefaultEntriesAtBeginning()} and
- * {@link #addDefaultEntriesAtEnd()}
- * are added automatically when generating
- * the {@link InfoItemDialog}.
+ * @param addDefaultEntriesAutomatically
+ * whether default entries added with {@link #addDefaultBeginningEntries()}
+ * and {@link #addDefaultEndEntries()} are added automatically when generating
+ * the {@link InfoItemDialog}.
+ *
+ * Entries added with {@link #addEntry(StreamDialogDefaultEntry)} and
+ * {@link #addAllEntries(StreamDialogDefaultEntry...)} are added in between.
*/
public Builder(@NonNull final Activity activity,
+ @NonNull final Context context,
@NonNull final Fragment fragment,
@NonNull final StreamInfoItem infoItem,
final boolean addDefaultEntriesAutomatically) {
this.activity = activity;
+ this.context = context;
this.fragment = fragment;
this.infoItem = infoItem;
this.addDefaultEntriesAutomatically = addDefaultEntriesAutomatically;
if (addDefaultEntriesAutomatically) {
- addDefaultEntriesAtBeginning();
+ addDefaultBeginningEntries();
}
}
@@ -139,12 +208,11 @@ public final class InfoItemDialog {
}
}
- public void addChannelDetailsEntryIfPossible() {
- if (!isNullOrEmpty(infoItem.getUploaderUrl())) {
- addEntry(StreamDialogDefaultEntry.SHOW_CHANNEL_DETAILS);
- }
- }
-
+ /**
+ * Adds {@link StreamDialogDefaultEntry#ENQUEUE} if the player is open and
+ * {@link StreamDialogDefaultEntry#ENQUEUE_NEXT} if there are multiple streams
+ * in the play queue.
+ */
public void addEnqueueEntriesIfNeeded() {
if (PlayerHolder.getInstance().isPlayerOpen()) {
addEntry(StreamDialogDefaultEntry.ENQUEUE);
@@ -155,6 +223,11 @@ public final class InfoItemDialog {
}
}
+ /**
+ * Adds the {@link StreamDialogDefaultEntry#START_HERE_ON_BACKGROUND}.
+ * If the {@link #infoItem} is not a pure audio (live) stream,
+ * {@link StreamDialogDefaultEntry#START_HERE_ON_POPUP} is added, too.
+ */
public void addStartHereEntries() {
addEntry(StreamDialogDefaultEntry.START_HERE_ON_BACKGROUND);
if (infoItem.getStreamType() != StreamType.AUDIO_STREAM
@@ -169,8 +242,8 @@ public final class InfoItemDialog {
*/
public void addMarkAsWatchedEntryIfNeeded() {
final boolean isWatchHistoryEnabled = PreferenceManager
- .getDefaultSharedPreferences(activity)
- .getBoolean(activity.getString(R.string.enable_watch_history_key), false);
+ .getDefaultSharedPreferences(context)
+ .getBoolean(context.getString(R.string.enable_watch_history_key), false);
if (isWatchHistoryEnabled
&& infoItem.getStreamType() != StreamType.LIVE_STREAM
&& infoItem.getStreamType() != StreamType.AUDIO_LIVE_STREAM) {
@@ -179,17 +252,26 @@ public final class InfoItemDialog {
}
public void addPlayWithKodiEntryIfNeeded() {
- if (KoreUtils.shouldShowPlayWithKodi(activity, infoItem.getServiceId())) {
+ if (KoreUtils.shouldShowPlayWithKodi(context, infoItem.getServiceId())) {
addEntry(StreamDialogDefaultEntry.PLAY_WITH_KODI);
}
}
- public void addDefaultEntriesAtBeginning() {
+ /**
+ * Add the entries which are usually at the top of the action list.
+ *
+ * This method adds the "enqueue" (see {@link #addEnqueueEntriesIfNeeded()})
+ * and "start here" (see {@link #addStartHereEntries()} entries.
+ */
+ public void addDefaultBeginningEntries() {
addEnqueueEntriesIfNeeded();
addStartHereEntries();
}
- public void addDefaultEntriesAtEnd() {
+ /**
+ * Add the entries which are usually at the bottom of the action list.
+ */
+ public void addDefaultEndEntries() {
addAllEntries(
StreamDialogDefaultEntry.APPEND_PLAYLIST,
StreamDialogDefaultEntry.SHARE,
@@ -197,7 +279,7 @@ public final class InfoItemDialog {
);
addPlayWithKodiEntryIfNeeded();
addMarkAsWatchedEntryIfNeeded();
- addChannelDetailsEntryIfPossible();
+ addEntry(StreamDialogDefaultEntry.SHOW_CHANNEL_DETAILS);
}
/**
@@ -206,7 +288,7 @@ public final class InfoItemDialog {
*/
public InfoItemDialog create() {
if (addDefaultEntriesAutomatically) {
- addDefaultEntriesAtEnd();
+ addDefaultEndEntries();
}
return new InfoItemDialog(this.activity, this.fragment, this.infoItem, this.entries);
}
diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt
index 63e918739..5c1c78902 100644
--- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt
@@ -357,7 +357,7 @@ class FeedFragment : BaseStateFragment
+ * This enum provides entries that are accepted
+ * by the {@link org.schabi.newpipe.info_list.InfoItemDialog.Builder}.
+ *
+ * These entries contain a String {@link #resource} which is displayed in the dialog and
+ * a default {@link #action} that is executed
+ * when the entry is selected (via onClick()
).
+ *
+ * They action can be overridden by using the Builder's
+ * {@link org.schabi.newpipe.info_list.InfoItemDialog.Builder#setAction(
+ * StreamDialogDefaultEntry, StreamDialogEntry.StreamDialogEntryAction)}
+ * method.
+ *
* + - - - - - - - - - - - - - - - - - - - - - -+ * | ENQUEUE | - * | ENQUEUE_HERE | + * | ENQUEUE_NEXT | * | START_ON_BACKGROUND | * | START_ON_POPUP | * + - - - - - - - - - - - - - - - - - - - - - -+ @@ -118,10 +132,12 @@ public final class InfoItemDialog { * @param context * @param fragment * @param infoItem the item for this dialog; all entries and their actions work with - * this {@link org.schabi.newpipe.extractor.InfoItem} + * this {@link StreamInfoItem} + * @throws IllegalArgumentException ifactivity, context
+ * or resources isnull
*/ - public Builder(@NonNull final Activity activity, - @NonNull final Context context, + public Builder(final Activity activity, + final Context context, @NonNull final Fragment fragment, @NonNull final StreamInfoItem infoItem) { this(activity, context, fragment, infoItem, true); @@ -135,7 +151,7 @@ public final class InfoItemDialog { ** + - - - - - - - - - - - - - - - - - - - - - -+ * | ENQUEUE | - * | ENQUEUE_HERE | + * | ENQUEUE_NEXT | * | START_ON_BACKGROUND | * | START_ON_POPUP | * + - - - - - - - - - - - - - - - - - - - - - -+ @@ -164,12 +180,21 @@ public final class InfoItemDialog { *
* Entries added with {@link #addEntry(StreamDialogDefaultEntry)} and * {@link #addAllEntries(StreamDialogDefaultEntry...)} are added in between. + * @throws IllegalArgumentException ifactivity, context
+ * or resources isnull
*/ - public Builder(@NonNull final Activity activity, - @NonNull final Context context, + public Builder(final Activity activity, + final Context context, @NonNull final Fragment fragment, @NonNull final StreamInfoItem infoItem, final boolean addDefaultEntriesAutomatically) { + if (activity == null || context == null || context.getResources() == null) { + if (DEBUG) { + Log.d(TAG, "activity, context or resources is null: activity = " + + activity + ", context = " + context); + } + throw new IllegalArgumentException("activity, context or resources is null"); + } this.activity = activity; this.context = context; this.fragment = fragment; @@ -180,14 +205,24 @@ public final class InfoItemDialog { } } - public void addEntry(@NonNull final StreamDialogDefaultEntry entry) { + /** + * Adds a new entry and appends it to the current entry list. + * @param entry the entry to add + * @return the current {@link Builder} instance + */ + public Builder addEntry(@NonNull final StreamDialogDefaultEntry entry) { entries.add(entry.toStreamDialogEntry()); + return this; } - public void addAllEntries(@NonNull final StreamDialogDefaultEntry... newEntries) { - for (final StreamDialogDefaultEntry entry: newEntries) { - this.entries.add(entry.toStreamDialogEntry()); - } + /** + * Adds new entries. These are appended to the current entry list. + * @param newEntries the entries to add + * @return the current {@link Builder} instance + */ + public Builder addAllEntries(@NonNull final StreamDialogDefaultEntry... newEntries) { + Stream.of(newEntries).forEach(this::addEntry); + return this; } /** @@ -197,23 +232,26 @@ public final class InfoItemDialog { * does not have an effect. * @param entry the entry to change * @param action the action to perform when the entry is selected + * @return the current {@link Builder} instance */ - public void setAction(@NonNull final StreamDialogDefaultEntry entry, + public Builder setAction(@NonNull final StreamDialogDefaultEntry entry, @NonNull final StreamDialogEntry.StreamDialogEntryAction action) { for (int i = 0; i < entries.size(); i++) { if (entries.get(i).resource == entry.resource) { entries.set(i, new StreamDialogEntry(entry.resource, action)); - return; + return this; } } + return this; } /** * Adds {@link StreamDialogDefaultEntry#ENQUEUE} if the player is open and * {@link StreamDialogDefaultEntry#ENQUEUE_NEXT} if there are multiple streams * in the play queue. + * @return the current {@link Builder} instance */ - public void addEnqueueEntriesIfNeeded() { + public Builder addEnqueueEntriesIfNeeded() { if (PlayerHolder.getInstance().isPlayerOpen()) { addEntry(StreamDialogDefaultEntry.ENQUEUE); @@ -221,26 +259,30 @@ public final class InfoItemDialog { addEntry(StreamDialogDefaultEntry.ENQUEUE_NEXT); } } + return this; } /** * Adds the {@link StreamDialogDefaultEntry#START_HERE_ON_BACKGROUND}. * If the {@link #infoItem} is not a pure audio (live) stream, * {@link StreamDialogDefaultEntry#START_HERE_ON_POPUP} is added, too. + * @return the current {@link Builder} instance */ - public void addStartHereEntries() { + public Builder addStartHereEntries() { addEntry(StreamDialogDefaultEntry.START_HERE_ON_BACKGROUND); if (infoItem.getStreamType() != StreamType.AUDIO_STREAM && infoItem.getStreamType() != StreamType.AUDIO_LIVE_STREAM) { addEntry(StreamDialogDefaultEntry.START_HERE_ON_POPUP); } + return this; } /** * Adds {@link StreamDialogDefaultEntry.MARK_AS_WATCHED} if the watch history is enabled * and the stream is not a livestream. + * @return the current {@link Builder} instance */ - public void addMarkAsWatchedEntryIfNeeded() { + public Builder addMarkAsWatchedEntryIfNeeded() { final boolean isWatchHistoryEnabled = PreferenceManager .getDefaultSharedPreferences(context) .getBoolean(context.getString(R.string.enable_watch_history_key), false); @@ -249,12 +291,18 @@ public final class InfoItemDialog { && infoItem.getStreamType() != StreamType.AUDIO_LIVE_STREAM) { addEntry(StreamDialogDefaultEntry.MARK_AS_WATCHED); } + return this; } - public void addPlayWithKodiEntryIfNeeded() { + /** + * Adds the {@link StreamDialogDefaultEntry.PLAY_WITH_KODI} entry if it is needed. + * @return the current {@link Builder} instance + */ + public Builder addPlayWithKodiEntryIfNeeded() { if (KoreUtils.shouldShowPlayWithKodi(context, infoItem.getServiceId())) { addEntry(StreamDialogDefaultEntry.PLAY_WITH_KODI); } + return this; } /** @@ -262,16 +310,19 @@ public final class InfoItemDialog { *
* This method adds the "enqueue" (see {@link #addEnqueueEntriesIfNeeded()}) * and "start here" (see {@link #addStartHereEntries()} entries. + * @return the current {@link Builder} instance */ - public void addDefaultBeginningEntries() { + public Builder addDefaultBeginningEntries() { addEnqueueEntriesIfNeeded(); addStartHereEntries(); + return this; } /** * Add the entries which are usually at the bottom of the action list. + * @return the current {@link Builder} instance */ - public void addDefaultEndEntries() { + public Builder addDefaultEndEntries() { addAllEntries( StreamDialogDefaultEntry.APPEND_PLAYLIST, StreamDialogDefaultEntry.SHARE, @@ -280,6 +331,7 @@ public final class InfoItemDialog { addPlayWithKodiEntryIfNeeded(); addMarkAsWatchedEntryIfNeeded(); addEntry(StreamDialogDefaultEntry.SHOW_CHANNEL_DETAILS); + return this; } /** @@ -292,5 +344,14 @@ public final class InfoItemDialog { } return new InfoItemDialog(this.activity, this.fragment, this.infoItem, this.entries); } + + public static void reportErrorDuringInitialization(final Throwable throwable, + final InfoItem item) { + ErrorUtil.showSnackbar(App.getApp().getBaseContext(), new ErrorInfo( + throwable, + UserAction.OPEN_INFO_ITEM_DIALOG, + "none", + item.getServiceId())); + } } } diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 03c922ba4..832fb580f 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.local.history; -import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Parcelable; @@ -326,26 +325,28 @@ public class StatisticsPlaylistFragment private void showInfoItemDialog(final StreamStatisticsEntry item) { final Context context = getContext(); - final Activity activity = getActivity(); - if (context == null || context.getResources() == null || activity == null) { - return; - } final StreamInfoItem infoItem = item.toStreamInfoItem(); - final InfoItemDialog.Builder dialogBuilder = - new InfoItemDialog.Builder(activity, context, this, infoItem); + try { + final InfoItemDialog.Builder dialogBuilder = + new InfoItemDialog.Builder(getActivity(), context, this, infoItem); - // set entries in the middle; the others are added automatically - dialogBuilder.addEntry(StreamDialogDefaultEntry.DELETE); - - // set custom actions - dialogBuilder.setAction(StreamDialogDefaultEntry.START_HERE_ON_BACKGROUND, - (fragment, infoItemDuplicate) -> NavigationHelper - .playOnBackgroundPlayer(context, getPlayQueueStartingAt(item), true)); - dialogBuilder.setAction(StreamDialogDefaultEntry.DELETE, (fragment, infoItemDuplicate) -> - deleteEntry(Math.max(itemListAdapter.getItemsList().indexOf(item), 0))); - - dialogBuilder.create().show(); + // set entries in the middle; the others are added automatically + dialogBuilder + .addEntry(StreamDialogDefaultEntry.DELETE) + .setAction( + StreamDialogDefaultEntry.DELETE, + (f, i) -> deleteEntry( + Math.max(itemListAdapter.getItemsList().indexOf(item), 0))) + .setAction( + StreamDialogDefaultEntry.START_HERE_ON_BACKGROUND, + (f, i) -> NavigationHelper.playOnBackgroundPlayer( + context, getPlayQueueStartingAt(item), true)) + .create() + .show(); + } catch (final IllegalArgumentException e) { + InfoItemDialog.Builder.reportErrorDuringInitialization(e, infoItem); + } } private void deleteEntry(final int index) { diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 2b690ff7b..ed2b109b5 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -3,7 +3,6 @@ package org.schabi.newpipe.local.playlist; import static org.schabi.newpipe.ktx.ViewUtils.animate; import static org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout; -import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; @@ -740,33 +739,38 @@ public class LocalPlaylistFragment extends BaseLocalListFragmentNavigationHelper.playOnBackgroundPlayer( - context, getPlayQueueStartingAt(item), true)); - dialogBuilder.setAction(StreamDialogDefaultEntry.SET_AS_PLAYLIST_THUMBNAIL, - (fragment, infoItemDuplicate) -> - changeThumbnailUrl(item.getStreamEntity().getThumbnailUrl())); - dialogBuilder.setAction(StreamDialogDefaultEntry.DELETE, - (fragment, infoItemDuplicate) -> deleteItem(item)); - - dialogBuilder.create().show(); + // set custom actions + // all entries modified below have already been added within the builder + dialogBuilder + .setAction( + StreamDialogDefaultEntry.START_HERE_ON_BACKGROUND, + (f, i) -> NavigationHelper.playOnBackgroundPlayer( + context, getPlayQueueStartingAt(item), true)) + .setAction( + StreamDialogDefaultEntry.SET_AS_PLAYLIST_THUMBNAIL, + (f, i) -> + changeThumbnailUrl(item.getStreamEntity().getThumbnailUrl())) + .setAction( + StreamDialogDefaultEntry.DELETE, + (f, i) -> deleteItem(item)) + .create() + .show(); + } catch (final IllegalArgumentException e) { + InfoItemDialog.Builder.reportErrorDuringInitialization(e, infoItem); + } } private void setInitialData(final long pid, final String title) { diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java index e3d26c833..b9e1f17c5 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java @@ -1,13 +1,14 @@ package org.schabi.newpipe.util; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; +import static org.schabi.newpipe.util.StreamDialogEntry.fetchItemInfoIfSparse; +import static org.schabi.newpipe.util.StreamDialogEntry.openChannelFragment; import android.net.Uri; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.StringRes; -import androidx.fragment.app.Fragment; import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.R; @@ -15,11 +16,9 @@ import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; 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; import org.schabi.newpipe.util.external_communication.ShareUtils; @@ -73,32 +72,45 @@ public enum StreamDialogDefaultEntry { }), /** - * Enqueues the stream automatically to the current PlayerType.
- *
- * Info: Add this entry within showStreamDialog. + * Enqueues the stream automatically to the current PlayerType. */ ENQUEUE(R.string.enqueue_stream, (fragment, item) -> - NavigationHelper.enqueueOnPlayer(fragment.getContext(), new SinglePlayQueue(item)) + fetchItemInfoIfSparse(fragment.requireContext(), item, singlePlayQueue -> + NavigationHelper.enqueueOnPlayer(fragment.getContext(), singlePlayQueue)) ), + /** + * Enqueues the stream automatically to the current PlayerType + * after the currently playing stream. + */ ENQUEUE_NEXT(R.string.enqueue_next_stream, (fragment, item) -> - NavigationHelper.enqueueNextOnPlayer(fragment.getContext(), new SinglePlayQueue(item)) + fetchItemInfoIfSparse(fragment.requireContext(), item, singlePlayQueue -> + NavigationHelper.enqueueNextOnPlayer(fragment.getContext(), singlePlayQueue)) ), START_HERE_ON_BACKGROUND(R.string.start_here_on_background, (fragment, item) -> - NavigationHelper.playOnBackgroundPlayer(fragment.getContext(), - new SinglePlayQueue(item), true)), + fetchItemInfoIfSparse(fragment.requireContext(), item, singlePlayQueue -> + NavigationHelper.playOnBackgroundPlayer( + fragment.getContext(), singlePlayQueue, true))), START_HERE_ON_POPUP(R.string.start_here_on_popup, (fragment, item) -> - NavigationHelper.playOnPopupPlayer(fragment.getContext(), - new SinglePlayQueue(item), true)), + fetchItemInfoIfSparse(fragment.requireContext(), item, singlePlayQueue -> + NavigationHelper.playOnPopupPlayer(fragment.getContext(), singlePlayQueue, true))), SET_AS_PLAYLIST_THUMBNAIL(R.string.set_as_playlist_thumbnail, (fragment, item) -> { - }), // has to be set manually + throw new UnsupportedOperationException("This needs to be implemented manually " + + "by using InfoItemDialog.Builder.setAction()"); + }), DELETE(R.string.delete, (fragment, item) -> { - }), // has to be set manually + throw new UnsupportedOperationException("This needs to be implemented manually " + + "by using InfoItemDialog.Builder.setAction()"); + }), + /** + * Opens a {@link PlaylistDialog} to either append the stream to a playlist + * or create a new playlist if there are no local playlists. + */ APPEND_PLAYLIST(R.string.add_to_playlist, (fragment, item) -> PlaylistDialog.createCorrespondingDialog( fragment.getContext(), @@ -154,12 +166,4 @@ public enum StreamDialogDefaultEntry { return new StreamDialogEntry(resource, action); } - private static void openChannelFragment(@NonNull final Fragment fragment, - @NonNull final StreamInfoItem item, - final String uploaderUrl) { - // For some reason `getParentFragmentManager()` doesn't work, but this does. - NavigationHelper.openChannelFragment( - fragment.requireActivity().getSupportFragmentManager(), - item.getServiceId(), uploaderUrl, item.getUploaderName()); - } } diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java index bb59d0f29..24d616819 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java @@ -2,16 +2,22 @@ package org.schabi.newpipe.util; import android.content.Context; - import androidx.annotation.NonNull; import androidx.annotation.StringRes; import androidx.fragment.app.Fragment; +import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; +import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.stream.StreamInfoItem; +import org.schabi.newpipe.extractor.stream.StreamType; +import org.schabi.newpipe.local.history.HistoryRecordManager; +import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import java.util.function.Consumer; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.schedulers.Schedulers; public class StreamDialogEntry { @@ -33,4 +39,61 @@ public class StreamDialogEntry { public interface StreamDialogEntryAction { void onClick(Fragment fragment, StreamInfoItem infoItem); } + + public static void openChannelFragment(@NonNull final Fragment fragment, + @NonNull final StreamInfoItem item, + final String uploaderUrl) { + // For some reason `getParentFragmentManager()` doesn't work, but this does. + NavigationHelper.openChannelFragment( + fragment.requireActivity().getSupportFragmentManager(), + item.getServiceId(), uploaderUrl, item.getUploaderName()); + } + + /** + * Fetches a {@link StreamInfoItem} if it is incomplete and executes the callback. + *
+ * This method is required if the info has been fetched + * via a {@link org.schabi.newpipe.extractor.feed.FeedExtractor}. + * FeedExtractors provide a fast and lightweight method to fetch info, + * but the info might be incomplete + * (see {@link org.schabi.newpipe.local.feed.service.FeedLoadService} for more details). + * @param context + * @param item the item which is checked and eventually loaded completely + * @param callback + */ + public static void fetchItemInfoIfSparse(@NonNull final Context context, + @NonNull final StreamInfoItem item, + @NonNull final Consumercallback) { + if (!(item.getStreamType() == StreamType.LIVE_STREAM + || item.getStreamType() == StreamType.AUDIO_LIVE_STREAM) + && item.getDuration() < 0) { + // Sparse item: fetched by fast fetch + ExtractorHelper.getStreamInfo( + item.getServiceId(), + item.getUrl(), + false + ) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + final HistoryRecordManager recordManager = + new HistoryRecordManager(context); + recordManager.saveStreamState(result, 0) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnError(throwable -> ErrorUtil.showSnackbar( + context, + new ErrorInfo(throwable, UserAction.REQUESTED_STREAM, + item.getUrl(), item.getServiceId()))) + .subscribe(); + + callback.accept(new SinglePlayQueue(result)); + }, throwable -> ErrorUtil.createNotification(context, + new ErrorInfo(throwable, UserAction.REQUESTED_CHANNEL, + "Could not fetch missing stream info"))); + } else { + callback.accept(new SinglePlayQueue(item)); + } + } + } From a7d5d9a1d693e7794c8df03c4f0657f33040b6a9 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Sat, 19 Feb 2022 00:02:15 +0100 Subject: [PATCH 08/11] Fix rebase --- .../newpipe/info_list/InfoItemDialog.java | 2 +- .../util/StreamDialogDefaultEntry.java | 37 ++----------------- 2 files changed, 5 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java index 183b2d8d9..924c03cd8 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java @@ -252,7 +252,7 @@ public final class InfoItemDialog { * @return the current {@link Builder} instance */ public Builder addEnqueueEntriesIfNeeded() { - if (PlayerHolder.getInstance().isPlayerOpen()) { + if (PlayerHolder.getInstance().isPlayQueueReady()) { addEntry(StreamDialogDefaultEntry.ENQUEUE); if (PlayerHolder.getInstance().getQueueSize() > 1) { diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java index b9e1f17c5..a395d1ec1 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java @@ -1,21 +1,15 @@ package org.schabi.newpipe.util; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; import static org.schabi.newpipe.util.StreamDialogEntry.fetchItemInfoIfSparse; import static org.schabi.newpipe.util.StreamDialogEntry.openChannelFragment; import android.net.Uri; -import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.StringRes; -import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.R; import org.schabi.newpipe.database.stream.model.StreamEntity; -import org.schabi.newpipe.error.ErrorInfo; -import org.schabi.newpipe.error.ErrorUtil; -import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.local.history.HistoryRecordManager; @@ -25,7 +19,6 @@ import org.schabi.newpipe.util.external_communication.ShareUtils; import java.util.Collections; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; -import io.reactivex.rxjava3.schedulers.Schedulers; /** * @@ -44,32 +37,10 @@ import io.reactivex.rxjava3.schedulers.Schedulers; *
*/ public enum StreamDialogDefaultEntry { - SHOW_CHANNEL_DETAILS(R.string.show_channel_details, (fragment, item) -> { - if (isNullOrEmpty(item.getUploaderUrl())) { - final int serviceId = item.getServiceId(); - final String url = item.getUrl(); - Toast.makeText(fragment.getContext(), R.string.loading_channel_details, - Toast.LENGTH_SHORT).show(); - ExtractorHelper.getStreamInfo(serviceId, url, false) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - NewPipeDatabase.getInstance(fragment.requireContext()).streamDAO() - .setUploaderUrl(serviceId, url, result.getUploaderUrl()) - .subscribeOn(Schedulers.io()).subscribe(); - openChannelFragment(fragment, item, result.getUploaderUrl()); - }, throwable -> ErrorUtil.openActivity( - fragment.requireContext(), - new ErrorInfo( - throwable, - UserAction.REQUESTED_CHANNEL, - url, - serviceId - ))); - } else { - openChannelFragment(fragment, item, item.getUploaderUrl()); - } - }), + SHOW_CHANNEL_DETAILS(R.string.show_channel_details, (fragment, item) -> + SaveUploaderUrlHelper.saveUploaderUrlIfNeeded(fragment, item, + uploaderUrl -> openChannelFragment(fragment, item, uploaderUrl)) + ), /** * Enqueues the stream automatically to the current PlayerType. From 277f21d5b2ccc8e50241d5997a098e9022b3a1f0 Mon Sep 17 00:00:00 2001 From: TobiGrDate: Fri, 18 Feb 2022 23:46:23 +0100 Subject: [PATCH 09/11] Move Classes related to InfoItemDIalog into own package --- .../newpipe/fragments/list/BaseListFragment.java | 2 +- .../fragments/list/playlist/PlaylistFragment.java | 4 ++-- .../info_list/{ => dialog}/InfoItemDialog.java | 4 +--- .../dialog}/StreamDialogDefaultEntry.java | 12 +++++++----- .../dialog}/StreamDialogEntry.java | 4 +++- .../org/schabi/newpipe/local/feed/FeedFragment.kt | 2 +- .../local/history/StatisticsPlaylistFragment.java | 4 ++-- .../local/playlist/LocalPlaylistFragment.java | 4 ++-- 8 files changed, 19 insertions(+), 17 deletions(-) rename app/src/main/java/org/schabi/newpipe/info_list/{ => dialog}/InfoItemDialog.java (99%) rename app/src/main/java/org/schabi/newpipe/{util => info_list/dialog}/StreamDialogDefaultEntry.java (92%) rename app/src/main/java/org/schabi/newpipe/{util => info_list/dialog}/StreamDialogEntry.java (96%) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index b1fa0059c..db14fead9 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -29,8 +29,8 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.fragments.BaseStateFragment; import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; -import org.schabi.newpipe.info_list.InfoListAdapter; import org.schabi.newpipe.info_list.dialog.InfoItemDialog; +import org.schabi.newpipe.info_list.InfoListAdapter; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.OnClickGesture; import org.schabi.newpipe.util.StateSaver; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index 15110183c..50dd73ffc 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -35,7 +35,7 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.fragments.list.BaseListInfoFragment; -import org.schabi.newpipe.info_list.InfoItemDialog; +import org.schabi.newpipe.info_list.dialog.InfoItemDialog; import org.schabi.newpipe.local.playlist.RemotePlaylistManager; import org.schabi.newpipe.player.MainPlayer.PlayerType; import org.schabi.newpipe.player.playqueue.PlayQueue; @@ -44,7 +44,7 @@ import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PicassoHelper; -import org.schabi.newpipe.util.StreamDialogDefaultEntry; +import org.schabi.newpipe.info_list.dialog.StreamDialogDefaultEntry; import org.schabi.newpipe.util.external_communication.ShareUtils; import java.util.ArrayList; diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java b/app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java similarity index 99% rename from app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java rename to app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java index 924c03cd8..c573831b4 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java @@ -1,4 +1,4 @@ -package org.schabi.newpipe.info_list; +package org.schabi.newpipe.info_list.dialog; import static org.schabi.newpipe.MainActivity.DEBUG; @@ -24,8 +24,6 @@ import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.player.helper.PlayerHolder; -import org.schabi.newpipe.util.StreamDialogDefaultEntry; -import org.schabi.newpipe.util.StreamDialogEntry; import org.schabi.newpipe.util.external_communication.KoreUtils; import java.util.ArrayList; diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java b/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java similarity index 92% rename from app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java rename to app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java index a395d1ec1..66894ff88 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogDefaultEntry.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java @@ -1,7 +1,7 @@ -package org.schabi.newpipe.util; +package org.schabi.newpipe.info_list.dialog; -import static org.schabi.newpipe.util.StreamDialogEntry.fetchItemInfoIfSparse; -import static org.schabi.newpipe.util.StreamDialogEntry.openChannelFragment; +import static org.schabi.newpipe.info_list.dialog.StreamDialogEntry.fetchItemInfoIfSparse; +import static org.schabi.newpipe.info_list.dialog.StreamDialogEntry.openChannelFragment; import android.net.Uri; @@ -13,6 +13,8 @@ import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.local.history.HistoryRecordManager; +import org.schabi.newpipe.util.NavigationHelper; +import org.schabi.newpipe.util.SaveUploaderUrlHelper; import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.ShareUtils; @@ -23,7 +25,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; /** * * This enum provides entries that are accepted - * by the {@link org.schabi.newpipe.info_list.InfoItemDialog.Builder}. + * by the {@link InfoItemDialog.Builder}. *
** These entries contain a String {@link #resource} which is displayed in the dialog and @@ -31,7 +33,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; * when the entry is selected (via
diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogEntry.java similarity index 96% rename from app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java rename to app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogEntry.java index 24d616819..98c3d9aa3 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogEntry.java @@ -1,4 +1,4 @@ -package org.schabi.newpipe.util; +package org.schabi.newpipe.info_list.dialog; import android.content.Context; @@ -13,6 +13,8 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; +import org.schabi.newpipe.util.ExtractorHelper; +import org.schabi.newpipe.util.NavigationHelper; import java.util.function.Consumer; diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index e229a8789..8285d21e6 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -70,7 +70,7 @@ import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException import org.schabi.newpipe.extractor.stream.StreamInfoItem import org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty import org.schabi.newpipe.fragments.BaseStateFragment -import org.schabi.newpipe.info_list.InfoItemDialog +import org.schabi.newpipe.info_list.dialog.InfoItemDialog import org.schabi.newpipe.ktx.animate import org.schabi.newpipe.ktx.animateHideRecyclerViewAllowingScrolling import org.schabi.newpipe.ktx.slideUp diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 832fb580f..01df34292 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -28,14 +28,14 @@ import org.schabi.newpipe.databinding.StatisticPlaylistControlBinding; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.info_list.InfoItemDialog; +import org.schabi.newpipe.info_list.dialog.InfoItemDialog; import org.schabi.newpipe.local.BaseLocalListFragment; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.settings.HistorySettingsFragment; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.OnClickGesture; -import org.schabi.newpipe.util.StreamDialogDefaultEntry; +import org.schabi.newpipe.info_list.dialog.StreamDialogDefaultEntry; import java.util.ArrayList; import java.util.Collections; diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index ed2b109b5..9ea6c020d 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -40,7 +40,7 @@ import org.schabi.newpipe.databinding.PlaylistControlBinding; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.info_list.InfoItemDialog; +import org.schabi.newpipe.info_list.dialog.InfoItemDialog; import org.schabi.newpipe.local.BaseLocalListFragment; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.MainPlayer.PlayerType; @@ -49,7 +49,7 @@ import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.OnClickGesture; -import org.schabi.newpipe.util.StreamDialogDefaultEntry; +import org.schabi.newpipe.info_list.dialog.StreamDialogDefaultEntry; import java.util.ArrayList; import java.util.Collections; From ee477b25e55f2a90e9a75a897b98f6c78c5ec592 Mon Sep 17 00:00:00 2001 From: TobiGronClick()
). *
* They action can be overridden by using the Builder's - * {@link org.schabi.newpipe.info_list.InfoItemDialog.Builder#setAction( + * {@link InfoItemDialog.Builder#setAction( * StreamDialogDefaultEntry, StreamDialogEntry.StreamDialogEntryAction)} * method. *Date: Sun, 20 Feb 2022 20:26:23 +0100 Subject: [PATCH 10/11] Move StreamDialogEntry.openChannelFragment to NavigationHelper --- .../info_list/dialog/StreamDialogDefaultEntry.java | 2 +- .../newpipe/info_list/dialog/StreamDialogEntry.java | 10 ---------- .../java/org/schabi/newpipe/util/NavigationHelper.java | 10 ++++++++++ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java b/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java index 66894ff88..eda9e19bc 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogDefaultEntry.java @@ -1,7 +1,7 @@ package org.schabi.newpipe.info_list.dialog; import static org.schabi.newpipe.info_list.dialog.StreamDialogEntry.fetchItemInfoIfSparse; -import static org.schabi.newpipe.info_list.dialog.StreamDialogEntry.openChannelFragment; +import static org.schabi.newpipe.util.NavigationHelper.openChannelFragment; import android.net.Uri; diff --git a/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogEntry.java index 98c3d9aa3..a8d361447 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/dialog/StreamDialogEntry.java @@ -14,7 +14,6 @@ import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.util.ExtractorHelper; -import org.schabi.newpipe.util.NavigationHelper; import java.util.function.Consumer; @@ -42,15 +41,6 @@ public class StreamDialogEntry { void onClick(Fragment fragment, StreamInfoItem infoItem); } - public static void openChannelFragment(@NonNull final Fragment fragment, - @NonNull final StreamInfoItem item, - final String uploaderUrl) { - // For some reason `getParentFragmentManager()` doesn't work, but this does. - NavigationHelper.openChannelFragment( - fragment.requireActivity().getSupportFragmentManager(), - item.getServiceId(), uploaderUrl, item.getUploaderName()); - } - /** * Fetches a {@link StreamInfoItem} if it is incomplete and executes the callback. *
diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index 22e0a2dd0..2502bef8a 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -31,6 +31,7 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.stream.AudioStream; import org.schabi.newpipe.extractor.stream.Stream; import org.schabi.newpipe.extractor.stream.StreamInfo; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.fragments.MainFragment; import org.schabi.newpipe.fragments.detail.VideoDetailFragment; @@ -402,6 +403,15 @@ public final class NavigationHelper { .commit(); } + public static void openChannelFragment(@NonNull final Fragment fragment, + @NonNull final StreamInfoItem item, + final String uploaderUrl) { + // For some reason `getParentFragmentManager()` doesn't work, but this does. + openChannelFragment( + fragment.requireActivity().getSupportFragmentManager(), + item.getServiceId(), uploaderUrl, item.getUploaderName()); + } + public static void openPlaylistFragment(final FragmentManager fragmentManager, final int serviceId, final String url, @NonNull final String name) { From d3bc18497157572e758f73bfdf5a69a447027fe4 Mon Sep 17 00:00:00 2001 From: TobiGrDate: Mon, 21 Feb 2022 21:50:30 +0100 Subject: [PATCH 11/11] Clarify that only StramInfoItems are accepted by the builder --- .../schabi/newpipe/info_list/dialog/InfoItemDialog.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java b/app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java index c573831b4..2264ab370 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/dialog/InfoItemDialog.java @@ -86,7 +86,7 @@ public final class InfoItemDialog { } /** - * Builder to generate a {@link InfoItemDialog}.
+ *Builder to generate a {@link InfoItemDialog} for a {@link StreamInfoItem}.
* Use {@link #addEntry(StreamDialogDefaultEntry)} * and {@link #addAllEntries(StreamDialogDefaultEntry...)} to add options to the dialog. *
@@ -102,7 +102,8 @@ public final class InfoItemDialog { private final boolean addDefaultEntriesAutomatically; /** - *Create a Builder instance that automatically adds the some default entries + *
Create a {@link Builder builder} instance for a {@link StreamInfoItem} + * that automatically adds the some default entries * at the top and bottom of the dialog.
* The dialog has the following structure: *@@ -142,7 +143,7 @@ public final class InfoItemDialog { } /** - *Create an instance of this Builder.
+ *Create an instance of this {@link Builder} for a {@link StreamInfoItem}.
*If {@code addDefaultEntriesAutomatically} is set to {@code true}, * some default entries are added to the top and bottom of the dialog.
* The dialog has the following structure: