feat: secondary click instead of hold

This commit is contained in:
tapframe 2026-06-08 20:58:41 +05:30
parent b755da04ef
commit d196902b24
9 changed files with 59 additions and 6 deletions

View file

@ -0,0 +1,5 @@
package com.nuvio.app.core.ui
import androidx.compose.ui.Modifier
internal actual fun Modifier.secondaryClick(onClick: (() -> Unit)?): Modifier = this

View file

@ -344,6 +344,7 @@ internal fun Modifier.posterCardClickable(
onClick = { onClick?.invoke() },
onLongClick = onLongClick,
)
.secondaryClick(onLongClick)
} else {
this
}

View file

@ -0,0 +1,5 @@
package com.nuvio.app.core.ui
import androidx.compose.ui.Modifier
internal expect fun Modifier.secondaryClick(onClick: (() -> Unit)?): Modifier

View file

@ -40,6 +40,7 @@ import androidx.compose.ui.unit.Dp
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.secondaryClick
import nuvio.composeapp.generated.resources.Res
import nuvio.composeapp.generated.resources.action_play
import org.jetbrains.compose.resources.stringResource
@ -107,6 +108,7 @@ fun DetailActionButtons(
onLongClick = onPlayLongClick,
role = Role.Button,
)
.secondaryClick(onPlayLongClick)
.height(buttonHeight),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
@ -249,7 +251,8 @@ private fun DetailIconAction(
onClick = onClick,
onLongClick = onLongClick,
role = Role.Button,
),
)
.secondaryClick(onLongClick),
contentAlignment = Alignment.Center,
) {
Icon(

View file

@ -65,6 +65,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.secondaryClick
import com.nuvio.app.features.details.MetaDetails
import com.nuvio.app.features.details.MetaEpisodeCardStyle
import com.nuvio.app.features.details.MetaVideo
@ -408,6 +409,7 @@ private fun SeasonTextChipScrollRow(
) {
items(seasons, key = { season -> season }) { season ->
val isSelected = season == currentSeason
val onSecondaryClick = onLongPress?.let { handler -> { handler(season) } }
Box(
modifier = Modifier
.clip(RoundedCornerShape(sizing.seasonChipRadius))
@ -420,8 +422,9 @@ private fun SeasonTextChipScrollRow(
)
.combinedClickable(
onClick = { onSelect(season) },
onLongClick = onLongPress?.let { handler -> { handler(season) } },
onLongClick = onSecondaryClick,
)
.secondaryClick(onSecondaryClick)
.padding(
horizontal = sizing.seasonChipHorizontalPadding,
vertical = sizing.seasonChipVerticalPadding,
@ -508,7 +511,8 @@ private fun SeasonPosterButton(
.combinedClickable(
onClick = onClick,
onLongClick = onLongClick,
),
)
.secondaryClick(onLongClick),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Box(
@ -677,7 +681,8 @@ private fun EpisodeHorizontalCard(
enabled = onClick != null || onLongPress != null,
onClick = { onClick?.invoke() },
onLongClick = onLongPress,
),
)
.secondaryClick(onLongPress),
) {
val imageUrl = video.thumbnail ?: fallbackImage
val shouldBlurArtwork = blurUnwatchedEpisodes && !isWatched
@ -1045,7 +1050,8 @@ private fun EpisodeListCard(
enabled = onClick != null || onLongPress != null,
onClick = { onClick?.invoke() },
onLongClick = onLongPress,
),
)
.secondaryClick(onLongPress),
) {
Row(
modifier = Modifier.fillMaxSize(),

View file

@ -53,6 +53,7 @@ import com.nuvio.app.core.ui.landscapePosterHeightForWidth
import com.nuvio.app.core.ui.landscapePosterWidth
import com.nuvio.app.core.ui.posterCardClickable
import com.nuvio.app.core.ui.rememberPosterCardStyleUiState
import com.nuvio.app.core.ui.secondaryClick
import com.nuvio.app.features.cloud.CloudLibraryContentType
import com.nuvio.app.features.cloud.cloudLibraryDisplayArtworkUrl
import com.nuvio.app.features.home.HomeCatalogSettingsRepository
@ -803,7 +804,8 @@ private fun ContinueWatchingWideCard(
enabled = onClick != null || onLongClick != null,
onClick = { onClick?.invoke() },
onLongClick = onLongClick,
),
)
.secondaryClick(onLongClick),
) {
val shouldBlurArtwork = blurNextUp && useEpisodeThumbnails && item.isNextUp
val artworkUrl = item.continueWatchingArtworkUrl(useEpisodeThumbnails)

View file

@ -84,6 +84,7 @@ import com.nuvio.app.core.ui.NuvioBottomSheetDivider
import com.nuvio.app.core.ui.NuvioModalBottomSheet
import com.nuvio.app.core.ui.NuvioToastController
import com.nuvio.app.core.ui.dismissNuvioBottomSheet
import com.nuvio.app.core.ui.secondaryClick
import com.nuvio.app.features.downloads.DownloadsRepository
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.compose.material3.ExperimentalMaterial3Api
@ -1039,6 +1040,7 @@ private fun StreamCard(
onClick = onClick,
onLongClick = onLongClick,
)
.secondaryClick(if (enabled) onLongClick else null)
.padding(14.dp),
verticalAlignment = Alignment.Top,
) {

View file

@ -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.PointerButton
import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.pointerInput
@OptIn(ExperimentalComposeUiApi::class)
internal actual fun Modifier.secondaryClick(onClick: (() -> Unit)?): Modifier {
if (onClick == null) return this
return pointerInput(onClick) {
awaitPointerEventScope {
while (true) {
val event = awaitPointerEvent()
if (event.type == PointerEventType.Press && event.button == PointerButton.Secondary) {
event.changes.forEach { change -> change.consume() }
onClick()
}
}
}
}
}

View file

@ -0,0 +1,5 @@
package com.nuvio.app.core.ui
import androidx.compose.ui.Modifier
internal actual fun Modifier.secondaryClick(onClick: (() -> Unit)?): Modifier = this