Use Context instead of Activity

Improve docs
This commit is contained in:
TobiGr 2021-12-26 15:34:36 +01:00
parent 50e2385e82
commit 962fe9c36d
8 changed files with 138 additions and 40 deletions

View file

@ -409,7 +409,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
return; return;
} }
new InfoItemDialog.Builder(activity, this, item).create().show(); new InfoItemDialog.Builder(activity, context, this, item).create().show();
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////

View file

@ -142,8 +142,8 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
return; return;
} }
final InfoItemDialog.Builder dialogBuilder = new InfoItemDialog.Builder( final InfoItemDialog.Builder dialogBuilder =
activity, this, item); new InfoItemDialog.Builder(activity, context, this, item);
dialogBuilder.setAction(StreamDialogDefaultEntry.START_HERE_ON_BACKGROUND, dialogBuilder.setAction(StreamDialogDefaultEntry.START_HERE_ON_BACKGROUND,
(fragment, infoItem) -> NavigationHelper.playOnBackgroundPlayer( (fragment, infoItem) -> NavigationHelper.playOnBackgroundPlayer(

View file

@ -1,8 +1,7 @@
package org.schabi.newpipe.info_list; package org.schabi.newpipe.info_list;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
@ -24,10 +23,18 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Dialog with actions for a {@link StreamInfoItem}. * Dialog for a {@link StreamInfoItem}.
* The dialog'S content are actions that can be performed on the {@link StreamInfoItem}.
* This dialog is mostly used for longpress context menus. * This dialog is mostly used for longpress context menus.
*/ */
public final class InfoItemDialog { public final class InfoItemDialog {
/**
* Ideally, {@link InfoItemDialog} would extend {@link AlertDialog}.
* However, extending {@link AlertDialog} requires many additional lines
* and brings more complexity to this class, especially the constructor.
* To circumvent this, an {@link AlertDialog.Builder} is used in the constructor.
* Its result is stored in this class variable to allow access via the {@link #show()} method.
*/
private final AlertDialog dialog; private final AlertDialog dialog;
private InfoItemDialog(@NonNull final Activity activity, private InfoItemDialog(@NonNull final Activity activity,
@ -76,38 +83,100 @@ public final class InfoItemDialog {
*/ */
public static class Builder { public static class Builder {
@NonNull private final Activity activity; @NonNull private final Activity activity;
@NonNull private final Context context;
@NonNull private final StreamInfoItem infoItem; @NonNull private final StreamInfoItem infoItem;
@NonNull private final Fragment fragment; @NonNull private final Fragment fragment;
@NonNull private final List<StreamDialogEntry> entries = new ArrayList<>(); @NonNull private final List<StreamDialogEntry> entries = new ArrayList<>();
private final boolean addDefaultEntriesAutomatically; private final boolean addDefaultEntriesAutomatically;
/**
* <p>Create a Builder instance that automatically adds the some default entries
* at the top and bottom of the dialog.</p>
* The dialog has the following structure:
* <pre>
* + - - - - - - - - - - - - - - - - - - - - - -+
* | 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 |
* + - - - - - - - - - - - - - - - - - - - - - -+
* </pre>
* 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, public Builder(@NonNull final Activity activity,
@NonNull final Context context,
@NonNull final Fragment fragment, @NonNull final Fragment fragment,
@NonNull final StreamInfoItem infoItem) { @NonNull final StreamInfoItem infoItem) {
this(activity, fragment, infoItem, true); this(activity, context, fragment, infoItem, true);
} }
/** /**
* <p>Create an instance of this Builder</p> * <p>Create an instance of this Builder.</p>
* <p>If {@code addDefaultEntriesAutomatically} is set to {@code true},
* some default entries are added to the top and bottom of the dialog.</p>
* The dialog has the following structure:
* <pre>
* + - - - - - - - - - - - - - - - - - - - - - -+
* | 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 |
* + - - - - - - - - - - - - - - - - - - - - - -+
* </pre>
* 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 activity
* @param context
* @param fragment * @param fragment
* @param infoItem * @param infoItem
* @param addDefaultEntriesAutomatically whether default entries added with * @param addDefaultEntriesAutomatically
* {@link #addDefaultEntriesAtBeginning()} and * whether default entries added with {@link #addDefaultBeginningEntries()}
* {@link #addDefaultEntriesAtEnd()} * and {@link #addDefaultEndEntries()} are added automatically when generating
* are added automatically when generating * the {@link InfoItemDialog}.
* the {@link InfoItemDialog}. * <br/>
* Entries added with {@link #addEntry(StreamDialogDefaultEntry)} and
* {@link #addAllEntries(StreamDialogDefaultEntry...)} are added in between.
*/ */
public Builder(@NonNull final Activity activity, public Builder(@NonNull final Activity activity,
@NonNull final Context context,
@NonNull final Fragment fragment, @NonNull final Fragment fragment,
@NonNull final StreamInfoItem infoItem, @NonNull final StreamInfoItem infoItem,
final boolean addDefaultEntriesAutomatically) { final boolean addDefaultEntriesAutomatically) {
this.activity = activity; this.activity = activity;
this.context = context;
this.fragment = fragment; this.fragment = fragment;
this.infoItem = infoItem; this.infoItem = infoItem;
this.addDefaultEntriesAutomatically = addDefaultEntriesAutomatically; this.addDefaultEntriesAutomatically = addDefaultEntriesAutomatically;
if (addDefaultEntriesAutomatically) { if (addDefaultEntriesAutomatically) {
addDefaultEntriesAtBeginning(); addDefaultBeginningEntries();
} }
} }
@ -139,12 +208,11 @@ public final class InfoItemDialog {
} }
} }
public void addChannelDetailsEntryIfPossible() { /**
if (!isNullOrEmpty(infoItem.getUploaderUrl())) { * Adds {@link StreamDialogDefaultEntry#ENQUEUE} if the player is open and
addEntry(StreamDialogDefaultEntry.SHOW_CHANNEL_DETAILS); * {@link StreamDialogDefaultEntry#ENQUEUE_NEXT} if there are multiple streams
} * in the play queue.
} */
public void addEnqueueEntriesIfNeeded() { public void addEnqueueEntriesIfNeeded() {
if (PlayerHolder.getInstance().isPlayerOpen()) { if (PlayerHolder.getInstance().isPlayerOpen()) {
addEntry(StreamDialogDefaultEntry.ENQUEUE); 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() { public void addStartHereEntries() {
addEntry(StreamDialogDefaultEntry.START_HERE_ON_BACKGROUND); addEntry(StreamDialogDefaultEntry.START_HERE_ON_BACKGROUND);
if (infoItem.getStreamType() != StreamType.AUDIO_STREAM if (infoItem.getStreamType() != StreamType.AUDIO_STREAM
@ -169,8 +242,8 @@ public final class InfoItemDialog {
*/ */
public void addMarkAsWatchedEntryIfNeeded() { public void addMarkAsWatchedEntryIfNeeded() {
final boolean isWatchHistoryEnabled = PreferenceManager final boolean isWatchHistoryEnabled = PreferenceManager
.getDefaultSharedPreferences(activity) .getDefaultSharedPreferences(context)
.getBoolean(activity.getString(R.string.enable_watch_history_key), false); .getBoolean(context.getString(R.string.enable_watch_history_key), false);
if (isWatchHistoryEnabled if (isWatchHistoryEnabled
&& infoItem.getStreamType() != StreamType.LIVE_STREAM && infoItem.getStreamType() != StreamType.LIVE_STREAM
&& infoItem.getStreamType() != StreamType.AUDIO_LIVE_STREAM) { && infoItem.getStreamType() != StreamType.AUDIO_LIVE_STREAM) {
@ -179,17 +252,26 @@ public final class InfoItemDialog {
} }
public void addPlayWithKodiEntryIfNeeded() { public void addPlayWithKodiEntryIfNeeded() {
if (KoreUtils.shouldShowPlayWithKodi(activity, infoItem.getServiceId())) { if (KoreUtils.shouldShowPlayWithKodi(context, infoItem.getServiceId())) {
addEntry(StreamDialogDefaultEntry.PLAY_WITH_KODI); addEntry(StreamDialogDefaultEntry.PLAY_WITH_KODI);
} }
} }
public void addDefaultEntriesAtBeginning() { /**
* Add the entries which are usually at the top of the action list.
* <br/>
* This method adds the "enqueue" (see {@link #addEnqueueEntriesIfNeeded()})
* and "start here" (see {@link #addStartHereEntries()} entries.
*/
public void addDefaultBeginningEntries() {
addEnqueueEntriesIfNeeded(); addEnqueueEntriesIfNeeded();
addStartHereEntries(); addStartHereEntries();
} }
public void addDefaultEntriesAtEnd() { /**
* Add the entries which are usually at the bottom of the action list.
*/
public void addDefaultEndEntries() {
addAllEntries( addAllEntries(
StreamDialogDefaultEntry.APPEND_PLAYLIST, StreamDialogDefaultEntry.APPEND_PLAYLIST,
StreamDialogDefaultEntry.SHARE, StreamDialogDefaultEntry.SHARE,
@ -197,7 +279,7 @@ public final class InfoItemDialog {
); );
addPlayWithKodiEntryIfNeeded(); addPlayWithKodiEntryIfNeeded();
addMarkAsWatchedEntryIfNeeded(); addMarkAsWatchedEntryIfNeeded();
addChannelDetailsEntryIfPossible(); addEntry(StreamDialogDefaultEntry.SHOW_CHANNEL_DETAILS);
} }
/** /**
@ -206,7 +288,7 @@ public final class InfoItemDialog {
*/ */
public InfoItemDialog create() { public InfoItemDialog create() {
if (addDefaultEntriesAutomatically) { if (addDefaultEntriesAutomatically) {
addDefaultEntriesAtEnd(); addDefaultEndEntries();
} }
return new InfoItemDialog(this.activity, this.fragment, this.infoItem, this.entries); return new InfoItemDialog(this.activity, this.fragment, this.infoItem, this.entries);
} }

View file

@ -357,7 +357,7 @@ class FeedFragment : BaseStateFragment<FeedState>() {
val activity: Activity? = getActivity() val activity: Activity? = getActivity()
if (context == null || context.resources == null || activity == null) return if (context == null || context.resources == null || activity == null) return
InfoItemDialog.Builder(activity, this, item).create().show() InfoItemDialog.Builder(activity, context, this, item).create().show()
} }
private val listenerStreamItem = object : OnItemClickListener, OnItemLongClickListener { private val listenerStreamItem = object : OnItemClickListener, OnItemLongClickListener {

View file

@ -332,8 +332,8 @@ public class StatisticsPlaylistFragment
} }
final StreamInfoItem infoItem = item.toStreamInfoItem(); final StreamInfoItem infoItem = item.toStreamInfoItem();
final InfoItemDialog.Builder dialogBuilder = new InfoItemDialog.Builder( final InfoItemDialog.Builder dialogBuilder =
activity, this, infoItem); new InfoItemDialog.Builder(activity, context, this, infoItem);
// set entries in the middle; the others are added automatically // set entries in the middle; the others are added automatically
dialogBuilder.addEntry(StreamDialogDefaultEntry.DELETE); dialogBuilder.addEntry(StreamDialogDefaultEntry.DELETE);

View file

@ -747,8 +747,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
} }
final StreamInfoItem infoItem = item.toStreamInfoItem(); final StreamInfoItem infoItem = item.toStreamInfoItem();
final InfoItemDialog.Builder dialogBuilder = new InfoItemDialog.Builder( final InfoItemDialog.Builder dialogBuilder =
activity, this, infoItem); new InfoItemDialog.Builder(activity, context, this, infoItem);
// add entries in the middle // add entries in the middle
dialogBuilder.addAllEntries( dialogBuilder.addAllEntries(

View file

@ -12,6 +12,9 @@ import androidx.fragment.app.Fragment;
import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.database.stream.model.StreamEntity; 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.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.local.dialog.PlaylistDialog;
@ -25,11 +28,23 @@ import java.util.Collections;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
/**
* <p>
* This enum provides entries that are accepted
* by the {@link org.schabi.newpipe.info_list.InfoItemDialog.Builder}.
* </p>
* <p>
* 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 <code>onClick()</code>).
* <br/>
* They action can be overridden by using the Builder's
* {@link org.schabi.newpipe.info_list.InfoItemDialog.Builder#setAction(
* StreamDialogDefaultEntry, StreamDialogEntry.StreamDialogEntryAction)}
* method.
* </p>
*/
public enum StreamDialogDefaultEntry { public enum StreamDialogDefaultEntry {
//////////////////////////////////////
// enum values with DEFAULT actions //
//////////////////////////////////////
SHOW_CHANNEL_DETAILS(R.string.show_channel_details, (fragment, item) -> { SHOW_CHANNEL_DETAILS(R.string.show_channel_details, (fragment, item) -> {
if (isNullOrEmpty(item.getUploaderUrl())) { if (isNullOrEmpty(item.getUploaderUrl())) {
final int serviceId = item.getServiceId(); final int serviceId = item.getServiceId();
@ -125,6 +140,7 @@ public enum StreamDialogDefaultEntry {
public final int resource; public final int resource;
@NonNull @NonNull
public final StreamDialogEntry.StreamDialogEntryAction action; public final StreamDialogEntry.StreamDialogEntryAction action;
StreamDialogDefaultEntry(@StringRes final int resource, StreamDialogDefaultEntry(@StringRes final int resource,
@NonNull final StreamDialogEntry.StreamDialogEntryAction action) { @NonNull final StreamDialogEntry.StreamDialogEntryAction action) {
this.resource = resource; this.resource = resource;
@ -136,10 +152,6 @@ public enum StreamDialogDefaultEntry {
return new StreamDialogEntry(resource, action); return new StreamDialogEntry(resource, action);
} }
/////////////////////////////////////////////
// private method to open channel fragment //
/////////////////////////////////////////////
private static void openChannelFragment(@NonNull final Fragment fragment, private static void openChannelFragment(@NonNull final Fragment fragment,
@NonNull final StreamInfoItem item, @NonNull final StreamInfoItem item,
final String uploaderUrl) { final String uploaderUrl) {

View file

@ -10,6 +10,10 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.ServiceList; import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
/**
* Util class that provides methods which are related to the Kodi Media Center and its Kore app.
* @see <a href="https://kodi.tv/">Kodi website</a>
*/
public final class KoreUtils { public final class KoreUtils {
private KoreUtils() { } private KoreUtils() { }