From 76cce3180f298cab4016ecf111cb7adebf83865e Mon Sep 17 00:00:00 2001 From: tapframe <85391825+tapframe@users.noreply.github.com> Date: Tue, 12 May 2026 23:28:18 +0530 Subject: [PATCH] feat: implement nuvioSecondaryClick modifier for secondary click handling --- .../core/ui/NuvioSecondaryClick.android.kt | 5 ++++ .../nuvio/app/core/ui/NuvioSecondaryClick.kt | 5 ++++ .../nuvio/app/core/ui/NuvioShelfComponents.kt | 9 +++---- .../details/components/DetailActionButtons.kt | 3 +++ .../details/components/DetailSeriesContent.kt | 3 +++ .../components/HomeContinueWatchingSection.kt | 2 ++ .../app/features/streams/StreamsScreen.kt | 2 ++ .../core/ui/NuvioSecondaryClick.desktop.kt | 24 +++++++++++++++++++ .../app/core/ui/NuvioSecondaryClick.ios.kt | 5 ++++ 9 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 composeApp/src/androidMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.android.kt create mode 100644 composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.kt create mode 100644 composeApp/src/desktopMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.desktop.kt create mode 100644 composeApp/src/iosMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.ios.kt diff --git a/composeApp/src/androidMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.android.kt b/composeApp/src/androidMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.android.kt new file mode 100644 index 00000000..fe87c835 --- /dev/null +++ b/composeApp/src/androidMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.android.kt @@ -0,0 +1,5 @@ +package com.nuvio.app.core.ui + +import androidx.compose.ui.Modifier + +internal actual fun Modifier.nuvioSecondaryClick(onSecondaryClick: (() -> Unit)?): Modifier = this diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.kt new file mode 100644 index 00000000..45fd96cb --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.kt @@ -0,0 +1,5 @@ +package com.nuvio.app.core.ui + +import androidx.compose.ui.Modifier + +internal expect fun Modifier.nuvioSecondaryClick(onSecondaryClick: (() -> Unit)?): Modifier diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioShelfComponents.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioShelfComponents.kt index ace10d77..624d817d 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioShelfComponents.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/NuvioShelfComponents.kt @@ -343,10 +343,11 @@ internal fun Modifier.posterCardClickable( onLongClick: (() -> Unit)?, ): Modifier = if (onClick != null || onLongClick != null) { - combinedClickable( - onClick = { onClick?.invoke() }, - onLongClick = onLongClick, - ) + nuvioSecondaryClick(onLongClick) + .combinedClickable( + onClick = { onClick?.invoke() }, + onLongClick = onLongClick, + ) } else { this } diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt index d5be0d59..07979a11 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt @@ -25,6 +25,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.nuvio.app.core.ui.AppIconResource import com.nuvio.app.core.ui.appIconPainter +import com.nuvio.app.core.ui.nuvioSecondaryClick import nuvio.composeapp.generated.resources.Res import nuvio.composeapp.generated.resources.action_play import nuvio.composeapp.generated.resources.action_save @@ -70,6 +71,7 @@ fun DetailActionButtons( Row( modifier = Modifier .fillMaxWidth() + .nuvioSecondaryClick(onPlayLongClick) .combinedClickable( onClick = onPlayClick, onLongClick = onPlayLongClick, @@ -104,6 +106,7 @@ fun DetailActionButtons( Row( modifier = Modifier .fillMaxWidth() + .nuvioSecondaryClick(onSaveLongClick) .combinedClickable( onClick = onSaveClick, onLongClick = onSaveLongClick, diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailSeriesContent.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailSeriesContent.kt index e5140b74..8e2596f2 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailSeriesContent.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailSeriesContent.kt @@ -64,6 +64,7 @@ import com.nuvio.app.core.format.formatReleaseDateForDisplay import com.nuvio.app.core.i18n.localizedSeasonEpisodeCode import com.nuvio.app.core.ui.NuvioAnimatedWatchedBadge import com.nuvio.app.core.ui.NuvioProgressBar +import com.nuvio.app.core.ui.nuvioSecondaryClick import com.nuvio.app.features.details.MetaDetails import com.nuvio.app.features.details.MetaEpisodeCardStyle import com.nuvio.app.features.details.MetaVideo @@ -656,6 +657,7 @@ private fun EpisodeHorizontalCard( color = Color.White.copy(alpha = 0.12f), shape = cardShape, ) + .nuvioSecondaryClick(onLongPress) .combinedClickable( enabled = onClick != null || onLongPress != null, onClick = { onClick?.invoke() }, @@ -1011,6 +1013,7 @@ private fun EpisodeListCard( color = Color.White.copy(alpha = 0.1f), shape = cardShape, ) + .nuvioSecondaryClick(onLongPress) .combinedClickable( enabled = onClick != null || onLongPress != null, onClick = { onClick?.invoke() }, diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeContinueWatchingSection.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeContinueWatchingSection.kt index 9bf4d92a..f0ec4874 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeContinueWatchingSection.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeContinueWatchingSection.kt @@ -41,6 +41,7 @@ import coil3.compose.AsyncImage import com.nuvio.app.core.ui.localizedContinueWatchingSubtitle import com.nuvio.app.core.ui.NuvioProgressBar import com.nuvio.app.core.ui.NuvioShelfSection +import com.nuvio.app.core.ui.nuvioSecondaryClick import com.nuvio.app.core.ui.posterCardClickable import com.nuvio.app.features.watchprogress.ContinueWatchingItem import com.nuvio.app.features.watchprogress.ContinueWatchingSectionStyle @@ -334,6 +335,7 @@ private fun ContinueWatchingWideCard( color = Color.White.copy(alpha = 0.15f), shape = RoundedCornerShape(layout.cardRadius), ) + .nuvioSecondaryClick(onLongClick) .combinedClickable( enabled = onClick != null || onLongClick != null, onClick = { onClick?.invoke() }, diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamsScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamsScreen.kt index 22e877bb..7ca24a43 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamsScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/streams/StreamsScreen.kt @@ -83,6 +83,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.rememberModalBottomSheetState import coil3.compose.AsyncImage +import com.nuvio.app.core.ui.nuvioSecondaryClick import com.nuvio.app.core.ui.nuvioSafeBottomPadding import com.nuvio.app.features.watchprogress.WatchProgressRepository import kotlinx.coroutines.launch @@ -963,6 +964,7 @@ private fun StreamCard( ) .clip(cardShape) .background(Color.White.copy(alpha = 0.05f)) + .nuvioSecondaryClick(if (isEnabled) onLongClick else null) .combinedClickable( enabled = isEnabled, onClick = onClick, diff --git a/composeApp/src/desktopMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.desktop.kt b/composeApp/src/desktopMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.desktop.kt new file mode 100644 index 00000000..c64bd3dc --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.desktop.kt @@ -0,0 +1,24 @@ +package com.nuvio.app.core.ui + +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.pointer.PointerEventPass +import androidx.compose.ui.input.pointer.PointerEventType +import androidx.compose.ui.input.pointer.isSecondary +import androidx.compose.ui.input.pointer.onPointerEvent + +@OptIn(ExperimentalComposeUiApi::class) +internal actual fun Modifier.nuvioSecondaryClick(onSecondaryClick: (() -> Unit)?): Modifier = + if (onSecondaryClick != null) { + onPointerEvent( + eventType = PointerEventType.Press, + pass = PointerEventPass.Initial, + ) { event -> + if (event.button?.isSecondary == true) { + event.changes.forEach { it.consume() } + onSecondaryClick() + } + } + } else { + this + } diff --git a/composeApp/src/iosMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.ios.kt b/composeApp/src/iosMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.ios.kt new file mode 100644 index 00000000..fe87c835 --- /dev/null +++ b/composeApp/src/iosMain/kotlin/com/nuvio/app/core/ui/NuvioSecondaryClick.ios.kt @@ -0,0 +1,5 @@ +package com.nuvio.app.core.ui + +import androidx.compose.ui.Modifier + +internal actual fun Modifier.nuvioSecondaryClick(onSecondaryClick: (() -> Unit)?): Modifier = this