From 9c558d97e900d862606d1b4b7a0333b116e44435 Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 9 Feb 2026 13:42:56 +0100 Subject: [PATCH] Build LongPressAction lists using builder pattern --- .../ui/components/menu/LongPressMenuTest.kt | 20 +- .../ui/components/menu/LongPressAction.kt | 576 +++++++++--------- .../ui/components/menu/LongPressMenu.kt | 2 +- 3 files changed, 291 insertions(+), 307 deletions(-) diff --git a/app/src/androidTest/java/org/schabi/newpipe/ui/components/menu/LongPressMenuTest.kt b/app/src/androidTest/java/org/schabi/newpipe/ui/components/menu/LongPressMenuTest.kt index caa450e9c..aed3a48d4 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/ui/components/menu/LongPressMenuTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/ui/components/menu/LongPressMenuTest.kt @@ -100,7 +100,7 @@ class LongPressMenuTest { */ private fun setLongPressMenu( longPressable: LongPressable = getLongPressable(), - longPressActions: List = LongPressAction.Type.entries.map { it.buildAction { } }, + longPressActions: List = LongPressAction.Type.entries.map { LongPressAction(it) { } }, onDismissRequest: () -> Unit = {}, isHeaderEnabled: Boolean = true, actionArrangement: List = LongPressAction.Type.entries @@ -171,7 +171,7 @@ class LongPressMenuTest { setLongPressMenu( onDismissRequest = { dismissedCount += 1 }, longPressable = getLongPressable(uploader = "UpLoAdEr"), - longPressActions = listOf(ShowChannelDetails.buildAction { pressedCount += 1 }), + longPressActions = listOf(LongPressAction(ShowChannelDetails) { pressedCount += 1 }), actionArrangement = listOf() ) @@ -196,7 +196,7 @@ class LongPressMenuTest { setLongPressMenu( onDismissRequest = { dismissedCount += 1 }, longPressable = getLongPressable(uploader = null), - longPressActions = listOf(ShowChannelDetails.buildAction { pressedCount += 1 }), + longPressActions = listOf(LongPressAction(ShowChannelDetails) { pressedCount += 1 }), actionArrangement = listOf() ) @@ -227,7 +227,7 @@ class LongPressMenuTest { fun testShowChannelDetails4() { setLongPressMenu( longPressable = getLongPressable(uploader = "UpLoAdEr"), - longPressActions = listOf(ShowChannelDetails.buildAction {}), + longPressActions = listOf(LongPressAction(ShowChannelDetails) {}), actionArrangement = listOf(ShowChannelDetails) ) // a ShowChannelDetails button is already present among the actions, @@ -444,7 +444,7 @@ class LongPressMenuTest { expectedShownActions: List ) { setLongPressMenu( - longPressActions = availableActions.map { it.buildAction {} }, + longPressActions = availableActions.map { LongPressAction(it) {} }, // whether the header is enabled or not shouldn't influence the result, so enable it // at random (but still deterministically) isHeaderEnabled = ((expectedShownActions + availableActions).sumOf { it.id } % 2) == 0, @@ -603,8 +603,8 @@ class LongPressMenuTest { fun testEnabledDisabledActions() { setLongPressMenu( longPressActions = listOf( - ShowDetails.buildAction(enabled = { true }) {}, - Enqueue.buildAction(enabled = { false }) {} + LongPressAction(ShowDetails, enabled = { true }) {}, + LongPressAction(Enqueue, enabled = { false }) {} ) ) composeRule.onNodeWithText(ShowDetails.label) @@ -620,7 +620,7 @@ class LongPressMenuTest { var dismissedCount = 0 setLongPressMenu( onDismissRequest = { dismissedCount += 1 }, - longPressActions = listOf(PlayWithKodi.buildAction { pressedCount += 1 }) + longPressActions = listOf(LongPressAction(PlayWithKodi) { pressedCount += 1 }) ) composeRule.onNodeWithText(PlayWithKodi.label) @@ -634,7 +634,7 @@ class LongPressMenuTest { var dismissedCount = 0 setLongPressMenu( onDismissRequest = { dismissedCount += 1 }, - longPressActions = listOf(BackgroundShuffled.buildAction { delay(500) }) + longPressActions = listOf(LongPressAction(BackgroundShuffled) { delay(500) }) ) // test that the loading circle appears while the action is being performed; note that there @@ -659,7 +659,7 @@ class LongPressMenuTest { setLongPressMenu( onDismissRequest = { dismissedCount += 1 }, longPressActions = listOf( - BackgroundShuffled.buildAction { throw Throwable("Whatever") } + LongPressAction(BackgroundShuffled) { throw Throwable("Whatever") } ) ) diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressAction.kt b/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressAction.kt index 084f59687..c3455e576 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressAction.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressAction.kt @@ -71,11 +71,13 @@ import org.schabi.newpipe.util.NavigationHelper import org.schabi.newpipe.util.external_communication.KoreUtils import org.schabi.newpipe.util.external_communication.ShareUtils +typealias ActionList = MutableList + data class LongPressAction( val type: Type, + val enabled: () -> Boolean = { true }, @MainThread - val action: suspend (context: Context) -> Unit, - val enabled: () -> Boolean = { true } + val action: suspend (context: Context) -> Unit ) { enum class Type( /** @@ -111,45 +113,55 @@ data class LongPressAction( 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 }, - action: suspend (context: Context) -> Unit - ) = LongPressAction(this, action, enabled) + Remove(25, R.string.play_queue_remove, Icons.Default.Delete) } companion object { - private fun buildPlayerActionList( - queue: suspend (Context) -> PlayQueue - ): List { - return listOf( - // TODO once NewPlayer will be used, make it so that the enabled states of Enqueue - // and EnqueueNext are a State<> that changes realtime based on the actual evolving - // player state - Type.Enqueue.buildAction( - enabled = { PlayerHolder.isPlayQueueReady } - ) { context -> - NavigationHelper.enqueueOnPlayer(context, queue(context)) - }, - Type.EnqueueNext.buildAction( - enabled = { - PlayerHolder.isPlayQueueReady && - (PlayerHolder.queuePosition < PlayerHolder.queueSize - 1) - } - ) { context -> - NavigationHelper.enqueueNextOnPlayer(context, queue(context)) - }, - Type.Background.buildAction { context -> - NavigationHelper.playOnBackgroundPlayer(context, queue(context), true) - }, - Type.Popup.buildAction { context -> - NavigationHelper.playOnPopupPlayer(context, queue(context), true) - }, - Type.Play.buildAction { context -> - NavigationHelper.playOnMainPlayer(context, queue(context), false) - } - ) + + private fun ActionList.addAction( + type: Type, + enabled: () -> Boolean = { true }, + action: suspend (context: Context) -> Unit + ): ActionList { + this.add(LongPressAction(type, enabled, action)) + return this + } + + private fun ActionList.addActionIf( + condition: Boolean, + type: Type, + enabled: () -> Boolean = { true }, + action: suspend (context: Context) -> Unit + ): ActionList { + if (condition) { + addAction(type, enabled, action) + } + return this + } + + private fun ActionList.addPlayerActions(queue: suspend (Context) -> PlayQueue): ActionList { + // TODO once NewPlayer will be used, make it so that the enabled states of Enqueue + // and EnqueueNext are a State<> that changes in real time based on the actual evolving + // player state + addAction(Type.Enqueue, enabled = { PlayerHolder.isPlayQueueReady }) { context -> + NavigationHelper.enqueueOnPlayer(context, queue(context)) + } + addAction(Type.EnqueueNext, enabled = { + PlayerHolder.isPlayQueueReady && + (PlayerHolder.queuePosition < PlayerHolder.queueSize - 1) + }) { context -> + NavigationHelper.enqueueNextOnPlayer(context, queue(context)) + } + addAction(Type.Background) { context -> + NavigationHelper.playOnBackgroundPlayer(context, queue(context), true) + } + addAction(Type.Popup) { context -> + NavigationHelper.playOnPopupPlayer(context, queue(context), true) + } + addAction(Type.Play) { context -> + NavigationHelper.playOnMainPlayer(context, queue(context), false) + } + return this } /** @@ -160,21 +172,27 @@ data class LongPressAction( * fragments, but it's probably not possible to do because of all the different types of * the items involved. But this should be reconsidered if the types will be unified. */ - private fun buildPlayerFromHereActionList(queueFromHere: () -> PlayQueue): List { - return listOf( - Type.BackgroundFromHere.buildAction { context -> - NavigationHelper.playOnBackgroundPlayer(context, queueFromHere(), true) - }, - Type.PopupFromHere.buildAction { context -> - NavigationHelper.playOnPopupPlayer(context, queueFromHere(), true) - }, - Type.PlayFromHere.buildAction { context -> - NavigationHelper.playOnMainPlayer(context, queueFromHere(), false) - } - ) + private fun ActionList.addPlayerFromHereActions( + queueFromHere: (() -> PlayQueue)? + ): ActionList { + if (queueFromHere == null) { + return this + } + addAction(Type.BackgroundFromHere) { context -> + NavigationHelper.playOnBackgroundPlayer(context, queueFromHere(), true) + } + addAction(Type.PopupFromHere) { context -> + NavigationHelper.playOnPopupPlayer(context, queueFromHere(), true) + } + addAction(Type.PlayFromHere) { context -> + NavigationHelper.playOnMainPlayer(context, queueFromHere(), false) + } + return this } - private fun buildPlayerShuffledActionList(queue: suspend (Context) -> PlayQueue): List { + private fun ActionList.addPlayerShuffledActions( + queue: suspend (Context) -> PlayQueue + ): ActionList { val shuffledQueue: suspend (Context) -> PlayQueue = { context -> val q = queue(context) withContext(Dispatchers.IO) { @@ -182,95 +200,89 @@ data class LongPressAction( } q } - return listOf( - Type.BackgroundShuffled.buildAction { context -> - NavigationHelper.playOnBackgroundPlayer(context, shuffledQueue(context), true) - }, - Type.PopupShuffled.buildAction { context -> - NavigationHelper.playOnPopupPlayer(context, shuffledQueue(context), true) - }, - Type.PlayShuffled.buildAction { context -> - NavigationHelper.playOnMainPlayer(context, shuffledQueue(context), false) - } - ) + addAction(Type.BackgroundShuffled) { context -> + NavigationHelper.playOnBackgroundPlayer(context, shuffledQueue(context), true) + } + addAction(Type.PopupShuffled) { context -> + NavigationHelper.playOnPopupPlayer(context, shuffledQueue(context), true) + } + addAction(Type.PlayShuffled) { context -> + NavigationHelper.playOnMainPlayer(context, shuffledQueue(context), false) + } + return this } - private fun buildShareActionList(item: InfoItem): List { - return listOf( - Type.Share.buildAction { context -> - ShareUtils.shareText(context, item.name, item.url, item.thumbnails) - }, - Type.OpenInBrowser.buildAction { context -> - ShareUtils.openUrlInBrowser(context, item.url) - } - ) + private fun ActionList.addShareActions(item: InfoItem): ActionList { + addAction(Type.Share) { context -> + ShareUtils.shareText(context, item.name, item.url, item.thumbnails) + } + addAction(Type.OpenInBrowser) { context -> + ShareUtils.openUrlInBrowser(context, item.url) + } + return this } - private fun buildShareActionList(name: String, url: String, thumbnailUrl: String?): List { - return listOf( - Type.Share.buildAction { context -> - ShareUtils.shareText(context, name, url, thumbnailUrl) - }, - Type.OpenInBrowser.buildAction { context -> - ShareUtils.openUrlInBrowser(context, url) - } - ) + private fun ActionList.addShareActions( + name: String, + url: String, + thumbnailUrl: String? + ): ActionList { + addAction(Type.Share) { context -> + ShareUtils.shareText(context, name, url, thumbnailUrl) + } + addAction(Type.OpenInBrowser) { context -> + ShareUtils.openUrlInBrowser(context, url) + } + return this } - private fun buildAdditionalStreamActionList(item: StreamInfoItem): List { - return listOf( - Type.Download.buildAction { context -> - val info = fetchStreamInfoAndSaveToDatabase(context, item.serviceId, item.url) - val downloadDialog = DownloadDialog(context, info) - val fragmentManager = context.findFragmentActivity() - .supportFragmentManager - downloadDialog.show(fragmentManager, "downloadDialog") - }, - Type.AddToPlaylist.buildAction { context -> - LocalPlaylistManager(NewPipeDatabase.getInstance(context)) - .hasPlaylists() - val dialog = withContext(Dispatchers.IO) { - PlaylistDialog.createCorrespondingDialog( - context, - listOf(StreamEntity(item)) - ) - .awaitSingle() - } - val tag = if (dialog is PlaylistAppendDialog) "append" else "create" - dialog.show( - context.findFragmentActivity().supportFragmentManager, - "StreamDialogEntry@${tag}_playlist" - ) - }, - Type.ShowChannelDetails.buildAction { context -> - val uploaderUrl = fetchUploaderUrlIfSparse( - context, - item.serviceId, - item.url, - item.uploaderUrl - ) - NavigationHelper.openChannelFragmentUsingIntent( - context, - item.serviceId, - uploaderUrl, - item.uploaderName - ) - }, - Type.MarkAsWatched.buildAction { context -> - withContext(Dispatchers.IO) { - HistoryRecordManager(context).markAsWatched(item).await() - } + private fun ActionList.addAdditionalStreamActions(item: StreamInfoItem): ActionList { + addAction(Type.Download) { context -> + val info = fetchStreamInfoAndSaveToDatabase(context, item.serviceId, item.url) + val downloadDialog = DownloadDialog(context, info) + val fragmentManager = context.findFragmentActivity() + .supportFragmentManager + downloadDialog.show(fragmentManager, "downloadDialog") + } + addAction(Type.AddToPlaylist) { context -> + LocalPlaylistManager(NewPipeDatabase.getInstance(context)) + .hasPlaylists() + val dialog = withContext(Dispatchers.IO) { + PlaylistDialog.createCorrespondingDialog(context, listOf(StreamEntity(item))) + .awaitSingle() } - ) + - if (KoreUtils.isServiceSupportedByKore(item.serviceId)) { - listOf( - Type.PlayWithKodi.buildAction( - enabled = { KoreUtils.isServiceSupportedByKore(item.serviceId) } - ) { context -> KoreUtils.playWithKore(context, item.url.toUri()) } - ) - } else { - listOf() + val tag = if (dialog is PlaylistAppendDialog) "append" else "create" + dialog.show( + context.findFragmentActivity().supportFragmentManager, + "StreamDialogEntry@${tag}_playlist" + ) + } + addAction(Type.ShowChannelDetails) { context -> + val uploaderUrl = fetchUploaderUrlIfSparse( + context, + item.serviceId, + item.url, + item.uploaderUrl + ) + NavigationHelper.openChannelFragmentUsingIntent( + context, + item.serviceId, + uploaderUrl, + item.uploaderName + ) + } + addAction(Type.MarkAsWatched) { context -> + withContext(Dispatchers.IO) { + HistoryRecordManager(context).markAsWatched(item).await() } + } + if (KoreUtils.isServiceSupportedByKore(item.serviceId)) { + addAction( + Type.PlayWithKodi, + enabled = { KoreUtils.isServiceSupportedByKore(item.serviceId) } + ) { context -> KoreUtils.playWithKore(context, item.url.toUri()) } + } + return this } /** @@ -281,18 +293,19 @@ data class LongPressAction( fun fromStreamInfoItem( item: StreamInfoItem, queueFromHere: (() -> PlayQueue)? - ): List { - return buildPlayerActionList { context -> fetchItemInfoIfSparse(context, item) } + - (queueFromHere?.let { buildPlayerFromHereActionList(queueFromHere) } ?: listOf()) + - buildShareActionList(item) + - buildAdditionalStreamActionList(item) + ): ActionList { + return ArrayList() + .addPlayerActions { context -> fetchItemInfoIfSparse(context, item) } + .addPlayerFromHereActions(queueFromHere) + .addShareActions(item) + .addAdditionalStreamActions(item) } @JvmStatic fun fromStreamEntity( item: StreamEntity, queueFromHere: (() -> PlayQueue)? - ): List { + ): ActionList { // TODO decide if it's fine to just convert to StreamInfoItem here (it poses an // unnecessary dependency on the extractor, when we want to just look at data; maybe // using something like LongPressable would work) @@ -304,55 +317,46 @@ data class LongPressAction( item: PlayQueueItem, playQueueFromWhichToDelete: PlayQueue, showDetails: Boolean - ): List { + ): ActionList { // TODO decide if it's fine to just convert to StreamInfoItem here (it poses an // unnecessary dependency on the extractor, when we want to just look at data; maybe // using something like LongPressable would work) val streamInfoItem = item.toStreamInfoItem() - return buildShareActionList(streamInfoItem) + - buildAdditionalStreamActionList(streamInfoItem) + - if (showDetails) { - listOf( - Type.ShowDetails.buildAction { context -> - // playQueue is null since we don't want any queue change - NavigationHelper.openVideoDetail( - context, - item.serviceId, - item.url, - item.title, - null, - false - ) - } + return ArrayList() + .addShareActions(streamInfoItem) + .addAdditionalStreamActions(streamInfoItem) + .addActionIf(showDetails, Type.ShowDetails) { context -> + // playQueue is null since we don't want any queue change + NavigationHelper.openVideoDetail( + context, + item.serviceId, + item.url, + item.title, + null, + false ) - } else { - listOf() - } + - listOf( - Type.Remove.buildAction { - val index = playQueueFromWhichToDelete.indexOf(item) - playQueueFromWhichToDelete.remove(index) - } - ) + } + .addAction(Type.Remove) { + val index = playQueueFromWhichToDelete.indexOf(item) + playQueueFromWhichToDelete.remove(index) + } } @JvmStatic fun fromStreamStatisticsEntry( item: StreamStatisticsEntry, queueFromHere: (() -> PlayQueue)? - ): List { - return fromStreamInfoItem(item.streamEntity.toStreamInfoItem(), queueFromHere) + - listOf( - Type.Delete.buildAction { context -> - withContext(Dispatchers.IO) { - HistoryRecordManager(context) - .deleteStreamHistoryAndState(item.streamId) - .await() - } - Toast.makeText(context, R.string.one_item_deleted, Toast.LENGTH_SHORT) - .show() + ): ActionList { + return fromStreamInfoItem(item.streamEntity.toStreamInfoItem(), queueFromHere) + .addAction(Type.Delete) { context -> + withContext(Dispatchers.IO) { + HistoryRecordManager(context) + .deleteStreamHistoryAndState(item.streamId) + .await() } - ) + Toast.makeText(context, R.string.one_item_deleted, Toast.LENGTH_SHORT) + .show() + } } /** @@ -368,23 +372,21 @@ data class LongPressAction( queueFromHere: (() -> PlayQueue)?, playlistId: Long, onDelete: Runnable - ): List { - return fromStreamInfoItem(item.streamEntity.toStreamInfoItem(), queueFromHere) + - listOf( - Type.SetAsPlaylistThumbnail.buildAction { context -> - withContext(Dispatchers.IO) { - LocalPlaylistManager(NewPipeDatabase.getInstance(context)) - .changePlaylistThumbnail(playlistId, item.streamEntity.uid, true) - .awaitSingle() - } - Toast.makeText( - context, - R.string.playlist_thumbnail_change_success, - Toast.LENGTH_SHORT - ).show() - }, - Type.Delete.buildAction { onDelete.run() } - ) + ): ActionList { + return fromStreamInfoItem(item.streamEntity.toStreamInfoItem(), queueFromHere) + .addAction(Type.SetAsPlaylistThumbnail) { context -> + withContext(Dispatchers.IO) { + LocalPlaylistManager(NewPipeDatabase.getInstance(context)) + .changePlaylistThumbnail(playlistId, item.streamEntity.uid, true) + .awaitSingle() + } + Toast.makeText( + context, + R.string.playlist_thumbnail_change_success, + Toast.LENGTH_SHORT + ).show() + } + .addAction(Type.Delete) { onDelete.run() } } /** @@ -395,55 +397,55 @@ data class LongPressAction( item: PlaylistMetadataEntry, isThumbnailPermanent: Boolean, onDelete: Runnable - ): List { - return buildPlayerActionList { LocalPlaylistPlayQueue(item) } + - buildPlayerShuffledActionList { LocalPlaylistPlayQueue(item) } + - listOf( - Type.Rename.buildAction { context -> - // open the dialog and wait for its completion in the coroutine - val newName = suspendCoroutine { continuation -> - val dialogBinding = DialogEditTextBinding.inflate( - context.findFragmentActivity().layoutInflater - ) - dialogBinding.dialogEditText.setHint(R.string.name) - dialogBinding.dialogEditText.setInputType(InputType.TYPE_CLASS_TEXT) - dialogBinding.dialogEditText.setText(item.orderingName) - AlertDialog.Builder(context) - .setView(dialogBinding.getRoot()) - .setPositiveButton(R.string.rename_playlist) { _, _ -> - continuation.resume(dialogBinding.dialogEditText.getText().toString()) - } - .setNegativeButton(R.string.cancel) { _, _ -> - continuation.resume(null) - } - .setOnCancelListener { - continuation.resume(null) - } - .show() - } ?: return@buildAction + ): ActionList { + return ArrayList() + .addPlayerActions { LocalPlaylistPlayQueue(item) } + .addPlayerShuffledActions { LocalPlaylistPlayQueue(item) } + .addAction(Type.Rename) { context -> + // open the dialog and wait for its completion in the coroutine + val newName = suspendCoroutine { continuation -> + val dialogBinding = DialogEditTextBinding.inflate( + context.findFragmentActivity().layoutInflater + ) + dialogBinding.dialogEditText.setHint(R.string.name) + dialogBinding.dialogEditText.setInputType(InputType.TYPE_CLASS_TEXT) + dialogBinding.dialogEditText.setText(item.orderingName) + AlertDialog.Builder(context) + .setView(dialogBinding.getRoot()) + .setPositiveButton(R.string.rename_playlist) { _, _ -> + continuation.resume(dialogBinding.dialogEditText.getText().toString()) + } + .setNegativeButton(R.string.cancel) { _, _ -> + continuation.resume(null) + } + .setOnCancelListener { + continuation.resume(null) + } + .show() + } ?: return@addAction - withContext(Dispatchers.IO) { + withContext(Dispatchers.IO) { + LocalPlaylistManager(NewPipeDatabase.getInstance(context)) + .renamePlaylist(item.uid, newName) + .awaitSingle() + } + } + .addAction( + Type.UnsetPlaylistThumbnail, + enabled = { isThumbnailPermanent } + ) { context -> + withContext(Dispatchers.IO) { + val localPlaylistManager = LocalPlaylistManager(NewPipeDatabase.getInstance(context)) - .renamePlaylist(item.uid, newName) - .awaitSingle() - } - }, - Type.UnsetPlaylistThumbnail.buildAction( - enabled = { isThumbnailPermanent } - ) { context -> - withContext(Dispatchers.IO) { - val localPlaylistManager = - LocalPlaylistManager(NewPipeDatabase.getInstance(context)) - val thumbnailStreamId = localPlaylistManager - .getAutomaticPlaylistThumbnailStreamId(item.uid) - .awaitFirst() - localPlaylistManager - .changePlaylistThumbnail(item.uid, thumbnailStreamId, false) - .awaitSingle() - } - }, - Type.Delete.buildAction { onDelete.run() } - ) + val thumbnailStreamId = localPlaylistManager + .getAutomaticPlaylistThumbnailStreamId(item.uid) + .awaitFirst() + localPlaylistManager + .changePlaylistThumbnail(item.uid, thumbnailStreamId, false) + .awaitSingle() + } + } + .addAction(Type.Delete) { onDelete.run() } } /** @@ -453,74 +455,56 @@ data class LongPressAction( fun fromPlaylistRemoteEntity( item: PlaylistRemoteEntity, onDelete: Runnable - ): List { - return buildPlayerActionList { PlaylistPlayQueue(item.serviceId, item.url) } + - buildPlayerShuffledActionList { PlaylistPlayQueue(item.serviceId, item.url) } + - buildShareActionList( - item.orderingName ?: "", - item.orderingName ?: "", - item.thumbnailUrl - ) + - listOf( - Type.Delete.buildAction { onDelete.run() } - ) + ): ActionList { + return ArrayList() + .addPlayerActions { PlaylistPlayQueue(item.serviceId, item.url) } + .addPlayerShuffledActions { PlaylistPlayQueue(item.serviceId, item.url) } + .addShareActions(item.orderingName ?: "", item.url ?: "", item.thumbnailUrl) + .addAction(Type.Delete) { onDelete.run() } } @JvmStatic fun fromChannelInfoItem( item: ChannelInfoItem, isSubscribed: Boolean - ): List { - return buildPlayerActionList { ChannelTabPlayQueue(item.serviceId, item.url) } + - buildPlayerShuffledActionList { ChannelTabPlayQueue(item.serviceId, item.url) } + - buildShareActionList(item) + - listOf( - Type.ShowChannelDetails.buildAction { context -> - NavigationHelper.openChannelFragmentUsingIntent( - context, - item.serviceId, - item.url, - item.name - ) + ): ActionList { + return ArrayList() + .addPlayerActions { ChannelTabPlayQueue(item.serviceId, item.url) } + .addPlayerShuffledActions { ChannelTabPlayQueue(item.serviceId, item.url) } + .addShareActions(item) + .addAction(Type.ShowChannelDetails) { context -> + NavigationHelper.openChannelFragmentUsingIntent( + context, + item.serviceId, + item.url, + item.name + ) + } + .addActionIf(isSubscribed, Type.Unsubscribe) { context -> + withContext(Dispatchers.IO) { + SubscriptionManager(context) + .deleteSubscription(item.serviceId, item.url) + .await() } - ) + - if (isSubscribed) { - listOf( - Type.Unsubscribe.buildAction { context -> - withContext(Dispatchers.IO) { - SubscriptionManager(context) - .deleteSubscription(item.serviceId, item.url) - .await() - } - Toast.makeText( - context, - context.getString(R.string.channel_unsubscribed), - Toast.LENGTH_SHORT - ).show() - } - ) - } else { - 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() - } - ) + Toast.makeText(context, R.string.channel_unsubscribed, Toast.LENGTH_SHORT) + .show() + } + .addActionIf(!isSubscribed, Type.Subscribe) { context -> + withContext(Dispatchers.IO) { + SubscriptionManager(context) + .insertSubscription(SubscriptionEntity.from(item)) + } + Toast.makeText(context, R.string.subscribed_button_title, Toast.LENGTH_SHORT) + .show() } } @JvmStatic - fun fromPlaylistInfoItem(item: PlaylistInfoItem): List { - return buildPlayerActionList { PlaylistPlayQueue(item.serviceId, item.url) } + - buildPlayerShuffledActionList { PlaylistPlayQueue(item.serviceId, item.url) } + - buildShareActionList(item) + fun fromPlaylistInfoItem(item: PlaylistInfoItem): ActionList { + return ArrayList() + .addPlayerActions { PlaylistPlayQueue(item.serviceId, item.url) } + .addPlayerShuffledActions { PlaylistPlayQueue(item.serviceId, item.url) } + .addShareActions(item) } } } diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressMenu.kt b/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressMenu.kt index 9d442899a..4a3c4a57e 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressMenu.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressMenu.kt @@ -757,7 +757,7 @@ private fun LongPressMenuPreview( onUploaderClick = {}, actions = LongPressAction.Type.entries // disable Enqueue actions just to show it off - .map { t -> t.buildAction({ t != EnqueueNext }) { } }, + .map { t -> LongPressAction(t, { t != EnqueueNext }) {} }, runActionAndDismiss = {} ) }