Add Subscribe button to LongPressMenu

This commit is contained in:
Stypox 2026-02-09 12:58:05 +01:00
parent 920d630409
commit 08300951ed
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
6 changed files with 50 additions and 19 deletions

View File

@ -83,5 +83,17 @@ data class SubscriptionEntity(
subscriberCount = info.subscriberCount
)
}
@Ignore
fun from(info: ChannelInfoItem): SubscriptionEntity {
return SubscriptionEntity(
serviceId = info.serviceId,
url = info.url,
name = info.name,
avatarUrl = ImageStrategy.imageListToDbUrl(info.thumbnails),
description = info.description,
subscriberCount = info.subscriberCount
)
}
}
}

View File

@ -30,6 +30,7 @@ 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.ItemViewMode;
import org.schabi.newpipe.local.subscription.SubscriptionManager;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.ui.components.menu.LongPressAction;
import org.schabi.newpipe.ui.components.menu.LongPressable;
@ -293,11 +294,14 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
}
@Override
public void held(final ChannelInfoItem selectedItem) {
public void held(final ChannelInfoItem item) {
final boolean isSubscribed = new SubscriptionManager(requireContext())
.blockingIsSubscribed(item.getServiceId(), item.getUrl());
openLongPressMenuInActivity(
requireActivity(),
LongPressable.fromChannelInfoItem(selectedItem),
LongPressAction.fromChannelInfoItem(selectedItem, false)
LongPressable.fromChannelInfoItem(item),
LongPressAction.fromChannelInfoItem(item, isSubscribed)
);
}
});

View File

@ -361,13 +361,7 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo>
if (DEBUG) {
Log.d(TAG, "No subscription to this channel!");
}
final SubscriptionEntity channel = new SubscriptionEntity();
channel.setServiceId(info.getServiceId());
channel.setUrl(info.getUrl());
channel.setName(info.getName());
channel.setAvatarUrl(ImageStrategy.imageListToDbUrl(info.getAvatars()));
channel.setDescription(info.getDescription());
channel.setSubscriberCount(info.getSubscriberCount());
final SubscriptionEntity channel = SubscriptionEntity.from(info);
channelSubscription = null;
updateNotifyButton(null);
subscribeButtonMonitor = monitorSubscribeButton(mapOnSubscribe(channel));

View File

@ -119,6 +119,10 @@ class SubscriptionManager(context: Context) {
subscriptionTable.delete(subscriptionEntity)
}
fun blockingIsSubscribed(serviceId: Int, url: String): Boolean {
return !subscriptionTable.getSubscription(serviceId, url).isEmpty.blockingGet()
}
/**
* Fetches the list of videos for the provided channel and saves them in the database, so that
* they will be considered as "old"/"already seen" streams and the user will never be notified

View File

@ -8,6 +8,7 @@ import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.PlaylistAdd
import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material.icons.filled.AddToQueue
import androidx.compose.material.icons.filled.Cast
import androidx.compose.material.icons.filled.Delete
@ -23,6 +24,7 @@ import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.PictureInPicture
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.QueuePlayNext
import androidx.compose.material.icons.filled.RemoveCircle
import androidx.compose.material.icons.filled.Share
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.core.net.toUri
@ -40,6 +42,7 @@ import org.schabi.newpipe.database.playlist.PlaylistStreamEntry
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity
import org.schabi.newpipe.database.stream.StreamStatisticsEntry
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.database.subscription.SubscriptionEntity
import org.schabi.newpipe.databinding.DialogEditTextBinding
import org.schabi.newpipe.download.DownloadDialog
import org.schabi.newpipe.extractor.InfoItem
@ -105,9 +108,10 @@ data class LongPressAction(
Rename(19, R.string.rename, Icons.Default.Edit),
SetAsPlaylistThumbnail(20, R.string.set_as_playlist_thumbnail, Icons.Default.Image),
UnsetPlaylistThumbnail(21, R.string.unset_playlist_thumbnail, Icons.Default.HideImage),
Delete(22, R.string.delete, Icons.Default.Delete),
Unsubscribe(23, R.string.unsubscribe, Icons.Default.Delete),
Remove(24, R.string.play_queue_remove, Icons.Default.Delete);
Subscribe(22, R.string.subscribe_button_title, Icons.Default.AddCircle),
Unsubscribe(23, R.string.unsubscribe, Icons.Default.RemoveCircle),
Delete(24, R.string.delete, Icons.Default.Delete),
Remove(25, R.string.play_queue_remove, Icons.Default.Delete);
fun buildAction(
enabled: () -> Boolean = { true },
@ -465,7 +469,7 @@ data class LongPressAction(
@JvmStatic
fun fromChannelInfoItem(
item: ChannelInfoItem,
showUnsubscribe: Boolean
isSubscribed: Boolean
): List<LongPressAction> {
return buildPlayerActionList { ChannelTabPlayQueue(item.serviceId, item.url) } +
buildPlayerShuffledActionList { ChannelTabPlayQueue(item.serviceId, item.url) } +
@ -480,7 +484,7 @@ data class LongPressAction(
)
}
) +
if (showUnsubscribe) {
if (isSubscribed) {
listOf(
Type.Unsubscribe.buildAction { context ->
withContext(Dispatchers.IO) {
@ -496,7 +500,19 @@ data class LongPressAction(
}
)
} else {
listOf()
listOf(
Type.Subscribe.buildAction { context ->
withContext(Dispatchers.IO) {
SubscriptionManager(context)
.insertSubscription(SubscriptionEntity.from(item))
}
Toast.makeText(
context,
context.getString(R.string.subscribed_button_title),
Toast.LENGTH_SHORT
).show()
}
)
}
}

View File

@ -22,6 +22,7 @@ import org.schabi.newpipe.ui.components.menu.LongPressAction.Type.Rename
import org.schabi.newpipe.ui.components.menu.LongPressAction.Type.SetAsPlaylistThumbnail
import org.schabi.newpipe.ui.components.menu.LongPressAction.Type.Share
import org.schabi.newpipe.ui.components.menu.LongPressAction.Type.ShowDetails
import org.schabi.newpipe.ui.components.menu.LongPressAction.Type.Subscribe
import org.schabi.newpipe.ui.components.menu.LongPressAction.Type.UnsetPlaylistThumbnail
import org.schabi.newpipe.ui.components.menu.LongPressAction.Type.Unsubscribe
@ -43,9 +44,9 @@ fun storeIsHeaderEnabledToSettings(context: Context, enabled: Boolean) {
// also be done by clicking on the uploader name in the long press menu header.
// PlayWithKodi is only added by default if it is enabled in settings.
private val DefaultEnabledActions: List<LongPressAction.Type> = listOf(
ShowDetails, Enqueue, EnqueueNext, Background, Popup, BackgroundFromHere,
BackgroundShuffled, Download, AddToPlaylist, Share, OpenInBrowser, MarkAsWatched,
Rename, SetAsPlaylistThumbnail, UnsetPlaylistThumbnail, Delete, Unsubscribe, Remove
ShowDetails, Enqueue, EnqueueNext, Background, Popup, BackgroundFromHere, BackgroundShuffled,
Download, AddToPlaylist, Share, OpenInBrowser, MarkAsWatched, Rename, SetAsPlaylistThumbnail,
UnsetPlaylistThumbnail, Subscribe, Unsubscribe, Delete, Remove
)
private fun getShowPlayWithKodi(context: Context): Boolean {