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 if activity, context
+ * or resources is null
*/
- 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 if activity, context
+ * or resources is null
*/
- 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 BaseLocalListFragment NavigationHelper.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 Consumer callback) {
+ 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: TobiGr
Date: 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 onClick()).
*
* 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.
*
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: TobiGr
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: TobiGr
Date: 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: