Add long press actions to channels and playlists info items
This commit is contained in:
parent
a18933792b
commit
1d1688529d
@ -23,6 +23,8 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.error.ErrorUtil;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
||||
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;
|
||||
@ -258,7 +260,10 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||
infoListAdapter.setOnStreamSelectedListener(new OnClickGesture<>() {
|
||||
@Override
|
||||
public void selected(final StreamInfoItem selectedItem) {
|
||||
onStreamSelected(selectedItem);
|
||||
onItemSelected(selectedItem);
|
||||
NavigationHelper.openVideoDetailFragment(requireContext(), getFM(),
|
||||
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName(),
|
||||
null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -267,23 +272,50 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||
}
|
||||
});
|
||||
|
||||
infoListAdapter.setOnChannelSelectedListener(selectedItem -> {
|
||||
try {
|
||||
onItemSelected(selectedItem);
|
||||
NavigationHelper.openChannelFragment(getFM(), selectedItem.getServiceId(),
|
||||
selectedItem.getUrl(), selectedItem.getName());
|
||||
} catch (final Exception e) {
|
||||
ErrorUtil.showUiErrorSnackbar(this, "Opening channel fragment", e);
|
||||
infoListAdapter.setOnChannelSelectedListener(new OnClickGesture<>() {
|
||||
@Override
|
||||
public void selected(final ChannelInfoItem selectedItem) {
|
||||
try {
|
||||
onItemSelected(selectedItem);
|
||||
NavigationHelper.openChannelFragment(getFM(), selectedItem.getServiceId(),
|
||||
selectedItem.getUrl(), selectedItem.getName());
|
||||
} catch (final Exception e) {
|
||||
ErrorUtil.showUiErrorSnackbar(BaseListFragment.this, "Opening channel fragment",
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void held(final ChannelInfoItem selectedItem) {
|
||||
openLongPressMenuInActivity(
|
||||
requireActivity(),
|
||||
LongPressable.fromChannelInfoItem(selectedItem),
|
||||
LongPressAction.fromChannelInfoItem(selectedItem)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
infoListAdapter.setOnPlaylistSelectedListener(selectedItem -> {
|
||||
try {
|
||||
onItemSelected(selectedItem);
|
||||
NavigationHelper.openPlaylistFragment(getFM(), selectedItem.getServiceId(),
|
||||
selectedItem.getUrl(), selectedItem.getName());
|
||||
} catch (final Exception e) {
|
||||
ErrorUtil.showUiErrorSnackbar(this, "Opening playlist fragment", e);
|
||||
infoListAdapter.setOnPlaylistSelectedListener(new OnClickGesture<>() {
|
||||
@Override
|
||||
public void selected(final PlaylistInfoItem selectedItem) {
|
||||
try {
|
||||
BaseListFragment.this.onItemSelected(selectedItem);
|
||||
NavigationHelper.openPlaylistFragment(BaseListFragment.this.getFM(),
|
||||
selectedItem.getServiceId(),
|
||||
selectedItem.getUrl(), selectedItem.getName());
|
||||
} catch (final Exception e) {
|
||||
ErrorUtil.showUiErrorSnackbar(BaseListFragment.this,
|
||||
"Opening playlist fragment", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void held(final PlaylistInfoItem selectedItem) {
|
||||
openLongPressMenuInActivity(
|
||||
requireActivity(),
|
||||
LongPressable.fromPlaylistInfoItem(selectedItem),
|
||||
LongPressAction.fromPlaylistInfoItem(selectedItem)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -293,6 +325,14 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||
useNormalItemListScrollListener();
|
||||
}
|
||||
|
||||
protected void showInfoItemDialog(final StreamInfoItem item) {
|
||||
openLongPressMenuInActivity(
|
||||
requireActivity(),
|
||||
LongPressable.fromStreamInfoItem(item),
|
||||
LongPressAction.fromStreamInfoItem(item)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all listeners and adds the normal scroll listener to the {@link #itemsList}.
|
||||
*/
|
||||
@ -375,27 +415,12 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||
}
|
||||
}
|
||||
|
||||
private void onStreamSelected(final StreamInfoItem selectedItem) {
|
||||
onItemSelected(selectedItem);
|
||||
NavigationHelper.openVideoDetailFragment(requireContext(), getFM(),
|
||||
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName(),
|
||||
null, false);
|
||||
}
|
||||
|
||||
protected void onScrollToBottom() {
|
||||
if (hasMoreItems() && !isLoading.get()) {
|
||||
loadMoreItems();
|
||||
}
|
||||
}
|
||||
|
||||
protected void showInfoItemDialog(final StreamInfoItem item) {
|
||||
openLongPressMenuInActivity(
|
||||
requireActivity(),
|
||||
LongPressable.fromStreamInfoItem(item),
|
||||
LongPressAction.fromStreamInfoItem(item)
|
||||
);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Menu
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
package org.schabi.newpipe.player.playqueue;
|
||||
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.schabi.newpipe.extractor.Page;
|
||||
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabInfo;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.util.ChannelTabHelper;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -15,7 +19,8 @@ import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public final class ChannelTabPlayQueue extends AbstractInfoPlayQueue<ChannelTabInfo> {
|
||||
|
||||
final ListLinkHandler linkHandler;
|
||||
@Nullable
|
||||
ListLinkHandler linkHandler;
|
||||
|
||||
public ChannelTabPlayQueue(final int serviceId,
|
||||
final ListLinkHandler linkHandler,
|
||||
@ -31,6 +36,13 @@ public final class ChannelTabPlayQueue extends AbstractInfoPlayQueue<ChannelTabI
|
||||
this(serviceId, linkHandler, null, Collections.emptyList(), 0);
|
||||
}
|
||||
|
||||
// Plays the first
|
||||
public ChannelTabPlayQueue(final int serviceId,
|
||||
final String channelUrl) {
|
||||
super(serviceId, channelUrl, null, Collections.emptyList(), 0);
|
||||
linkHandler = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTag() {
|
||||
return "ChannelTabPlayQueue@" + Integer.toHexString(hashCode());
|
||||
@ -39,10 +51,29 @@ public final class ChannelTabPlayQueue extends AbstractInfoPlayQueue<ChannelTabI
|
||||
@Override
|
||||
public void fetch() {
|
||||
if (isInitial) {
|
||||
ExtractorHelper.getChannelTab(this.serviceId, this.linkHandler, false)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getHeadListObserver());
|
||||
if (linkHandler == null) {
|
||||
ExtractorHelper.getChannelInfo(this.serviceId, this.baseUrl, false)
|
||||
.flatMap(channelInfo -> {
|
||||
linkHandler = channelInfo.getTabs()
|
||||
.stream()
|
||||
.filter(ChannelTabHelper::isStreamsTab)
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new ExtractionException(
|
||||
"No playable channel tab found"));
|
||||
|
||||
return ExtractorHelper
|
||||
.getChannelTab(this.serviceId, this.linkHandler, false);
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getHeadListObserver());
|
||||
|
||||
} else {
|
||||
ExtractorHelper.getChannelTab(this.serviceId, this.linkHandler, false)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getHeadListObserver());
|
||||
}
|
||||
} else {
|
||||
ExtractorHelper.getMoreChannelTabItems(this.serviceId, this.linkHandler, this.nextPage)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@ -5,6 +5,7 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
@ -28,6 +29,11 @@ public final class PlaylistPlayQueue extends AbstractInfoPlayQueue<PlaylistInfo>
|
||||
super(serviceId, url, nextPage, streams, index);
|
||||
}
|
||||
|
||||
public PlaylistPlayQueue(final int serviceId,
|
||||
final String url) {
|
||||
this(serviceId, url, null, Collections.emptyList(), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTag() {
|
||||
return "PlaylistPlayQueue@" + Integer.toHexString(hashCode());
|
||||
|
||||
@ -33,12 +33,16 @@ import org.schabi.newpipe.error.ErrorInfo
|
||||
import org.schabi.newpipe.error.ErrorUtil
|
||||
import org.schabi.newpipe.error.UserAction
|
||||
import org.schabi.newpipe.extractor.InfoItem
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||
import org.schabi.newpipe.ktx.findFragmentActivity
|
||||
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.ChannelTabPlayQueue
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue
|
||||
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue
|
||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue
|
||||
import org.schabi.newpipe.util.NavigationHelper
|
||||
import org.schabi.newpipe.util.SparseItemUtil
|
||||
@ -258,14 +262,37 @@ data class LongPressAction(
|
||||
item: PlaylistRemoteEntity,
|
||||
onDelete: Runnable,
|
||||
): List<LongPressAction> {
|
||||
return buildShareActionList(
|
||||
item.orderingName ?: "",
|
||||
item.url ?: "",
|
||||
item.thumbnailUrl
|
||||
) +
|
||||
return buildPlayerActionList { PlaylistPlayQueue(item.serviceId, item.url) } +
|
||||
buildShareActionList(
|
||||
item.orderingName ?: "",
|
||||
item.orderingName ?: "",
|
||||
item.thumbnailUrl
|
||||
) +
|
||||
listOf(
|
||||
Type.Delete.buildAction { onDelete.run() },
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun fromChannelInfoItem(item: ChannelInfoItem): List<LongPressAction> {
|
||||
return buildPlayerActionList { ChannelTabPlayQueue(item.serviceId, item.url) } +
|
||||
buildShareActionList(item) +
|
||||
listOf(
|
||||
Type.ShowChannelDetails.buildAction { context ->
|
||||
NavigationHelper.openChannelFragment(
|
||||
context.findFragmentActivity().supportFragmentManager,
|
||||
item.serviceId,
|
||||
item.url,
|
||||
item.name,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun fromPlaylistInfoItem(item: PlaylistInfoItem): List<LongPressAction> {
|
||||
return buildPlayerActionList { PlaylistPlayQueue(item.serviceId, item.url) } +
|
||||
buildShareActionList(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@ import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry
|
||||
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity
|
||||
import org.schabi.newpipe.database.stream.model.StreamEntity
|
||||
import org.schabi.newpipe.extractor.ListExtractor
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||
import org.schabi.newpipe.extractor.stream.StreamType
|
||||
import org.schabi.newpipe.extractor.stream.StreamType.AUDIO_LIVE_STREAM
|
||||
@ -92,5 +94,29 @@ data class LongPressable(
|
||||
item.streamCount ?: ListExtractor.ITEM_COUNT_UNKNOWN
|
||||
),
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
fun fromChannelInfoItem(item: ChannelInfoItem) = LongPressable(
|
||||
title = item.name,
|
||||
url = item.url?.takeIf { it.isNotBlank() },
|
||||
thumbnailUrl = ImageStrategy.choosePreferredImage(item.thumbnails),
|
||||
uploader = null,
|
||||
uploaderUrl = item.url?.takeIf { it.isNotBlank() },
|
||||
viewCount = null,
|
||||
uploadDate = null,
|
||||
decoration = null,
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
fun fromPlaylistInfoItem(item: PlaylistInfoItem) = LongPressable(
|
||||
title = item.name,
|
||||
url = item.url?.takeIf { it.isNotBlank() },
|
||||
thumbnailUrl = ImageStrategy.choosePreferredImage(item.thumbnails),
|
||||
uploader = item.uploaderName.takeIf { it.isNotBlank() },
|
||||
uploaderUrl = item.uploaderUrl?.takeIf { it.isNotBlank() },
|
||||
viewCount = null,
|
||||
uploadDate = null,
|
||||
decoration = Decoration.Playlist(item.streamCount),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user