feat: implement drag scroll functionality for desktop shelf

This commit is contained in:
tapframe 2026-06-09 14:45:22 +05:30
parent 64193ea410
commit 72595d45a2

View file

@ -15,8 +15,12 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.KeyboardArrowRight
@ -28,15 +32,19 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage
import com.nuvio.app.isDesktop
import nuvio.composeapp.generated.resources.Res
import nuvio.composeapp.generated.resources.home_view_all
import nuvio.composeapp.generated.resources.poster_logo_content_description
import org.jetbrains.compose.resources.stringResource
import kotlin.math.abs
enum class NuvioPosterShape {
Poster,
@ -64,6 +72,7 @@ fun <T> NuvioShelfSection(
itemContent: @Composable (T) -> Unit,
) {
val tokens = MaterialTheme.nuvio
val rowState = rememberLazyListState()
Column(
modifier = modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(tokens.spacing.controlGap + NuvioTokens.Space.s2),
@ -78,6 +87,8 @@ fun <T> NuvioShelfSection(
)
}
LazyRow(
state = rowState,
modifier = Modifier.desktopShelfDragScroll(rowState),
contentPadding = rowContentPadding,
horizontalArrangement = Arrangement.spacedBy(itemSpacing),
) {
@ -97,6 +108,47 @@ fun <T> NuvioShelfSection(
}
}
private fun Modifier.desktopShelfDragScroll(
state: LazyListState,
): Modifier {
if (!isDesktop) return this
return pointerInput(state) {
awaitEachGesture {
val down = awaitFirstDown(pass = PointerEventPass.Initial)
var totalDx = 0f
var totalDy = 0f
var dragging = false
while (true) {
val event = awaitPointerEvent(pass = PointerEventPass.Initial)
val change = event.changes.firstOrNull { it.id == down.id } ?: break
if (!change.pressed) break
val delta = change.position - change.previousPosition
totalDx += delta.x
totalDy += delta.y
if (!dragging) {
val horizontalDrag =
abs(totalDx) > viewConfiguration.touchSlop && abs(totalDx) > abs(totalDy)
val verticalDrag =
abs(totalDy) > viewConfiguration.touchSlop && abs(totalDy) > abs(totalDx)
when {
verticalDrag -> break
horizontalDrag -> dragging = true
else -> continue
}
}
state.dispatchRawDelta(-delta.x)
change.consume()
}
}
}
}
@Composable
fun NuvioPosterCard(
title: String,