Parcourir la source

touch event fix

Milan Jurkulak il y a 3 ans
Parent
commit
2ce5d99d50

+ 22 - 12
app/src/main/kotlin/org/mjdev/tvapp/base/extensions/ModifierExt.kt

@@ -9,6 +9,7 @@
 package org.mjdev.tvapp.base.extensions
 
 import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.layout.aspectRatio
 import androidx.compose.runtime.MutableState
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusRequester
@@ -16,6 +17,7 @@ import androidx.compose.ui.focus.FocusState
 import androidx.compose.ui.focus.focusRequester
 import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.input.pointer.pointerInput
+import timber.log.Timber
 
 @Suppress("MemberVisibilityCanBePrivate")
 object ModifierExt {
@@ -30,8 +32,14 @@ object ModifierExt {
         }
     }
 
-    fun Modifier.aspectRatio(ratio: Float?): Modifier = conditional(ratio != null) {
-        aspectRatio(ratio!!)
+    fun Modifier.tvAspectRatio(
+        ratio: Float?,
+        matchHeightConstraintsFirst: Boolean = false
+    ): Modifier = conditional(ratio != null) {
+        aspectRatio(
+            ratio!!,
+            matchHeightConstraintsFirst
+        )
     }
 
     fun Modifier.focusState(
@@ -40,18 +48,20 @@ object ModifierExt {
         focusState.value = state
     }
 
-    fun Modifier.onTouch(onTouch: () -> Unit) = pointerInput(this) {
-        detectTapGestures {
-            onTouch()
-        }
-    }
-
     fun Modifier.requestFocusOnTouch(
-        focusRequester: FocusRequester
-    ): Modifier = focusRequester(
+        focusRequester: FocusRequester,
+        onTouch: () -> Unit = {}
+    ): Modifier = this then focusRequester(
         focusRequester
-    ).onTouch {
-        focusRequester.requestFocus()
+    ).pointerInput(this) {
+        detectTapGestures {
+            try {
+                onTouch()
+                focusRequester.requestFocus()
+            } catch (e: Throwable) {
+                Timber.e(e)
+            }
+        }
     }
 
 }

+ 0 - 4
app/src/main/kotlin/org/mjdev/tvapp/base/ui/components/badge/Badge.kt

@@ -36,13 +36,11 @@ fun Badge(
     contentPadding: Dp = 2.dp,
     onClick: () -> Unit = {}
 ) {
-
     FocusableBox(
         modifier = modifier.clip(CircleShape),
         shape = shape,
         onClick = onClick
     ) {
-
         CircleText(
             modifier = modifier.clip(CircleShape),
             contentPadding = contentPadding + borderSize,
@@ -53,7 +51,5 @@ fun Badge(
             borderColor = borderColor,
             borderSize = borderSize
         )
-
     }
-
 }

+ 8 - 7
app/src/main/kotlin/org/mjdev/tvapp/base/ui/components/card/Card.kt

@@ -11,6 +11,7 @@ package org.mjdev.tvapp.base.ui.components.card
 import android.annotation.SuppressLint
 import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.widthIn
@@ -34,7 +35,7 @@ import androidx.tv.material3.CardScale
 import androidx.tv.material3.CardShape
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.Glow
-import org.mjdev.tvapp.base.extensions.ModifierExt.aspectRatio
+import org.mjdev.tvapp.base.extensions.ModifierExt.tvAspectRatio
 
 @OptIn(ExperimentalTvMaterial3Api::class)
 @Preview
@@ -54,14 +55,17 @@ fun Card(
         focusGlowColor,
         unFocusGlowColor
     ),
-    aspectRatio : Float? =  16f / 9f,
+    aspectRatio: Float? = 16f / 9f,
     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
     content: @Composable ColumnScope.() -> Unit = {}
 ) = androidx.tv.material3.Card(
     onClick = onClick,
     modifier = modifier
         .widthIn(max = 320.dp)
-        .aspectRatio(aspectRatio),
+        .tvAspectRatio(aspectRatio)
+        .clickable {
+            onClick()
+        },
     onLongClick = onLongClick,
     shape = shape,
     colors = colors,
@@ -175,7 +179,4 @@ fun Modifier.rainbowBorder(
         ),
         shape
     )
-}
-
-@Suppress("unused")
-fun Modifier.tvAspectRatio() = aspectRatio(16f / 9f)
+}

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/base/ui/components/card/ItemCard.kt

@@ -23,7 +23,7 @@ import androidx.tv.material3.CardGlow
 import androidx.tv.material3.CardScale
 import androidx.tv.material3.CardShape
 import androidx.tv.material3.ExperimentalTvMaterial3Api
-import org.mjdev.tvapp.base.extensions.ModifierExt.aspectRatio
+import org.mjdev.tvapp.base.extensions.ModifierExt.tvAspectRatio
 import org.mjdev.tvapp.base.interfaces.ItemWithDescription
 import org.mjdev.tvapp.base.interfaces.ItemWithImage
 import org.mjdev.tvapp.base.ui.components.complex.FocusableCard
@@ -46,7 +46,7 @@ fun ItemCard(
     aspectRatio: Float? = 16f / 9f,
     imageRenderer: @Composable (modifier: Modifier) -> Unit = {
         ImageAny(
-            modifier = modifier.aspectRatio(aspectRatio),
+            modifier = modifier.tvAspectRatio(aspectRatio),
             src = (item as? ItemWithImage)?.imageUrl,
             contentDescription = (item as? ItemWithDescription)?.description?.toString(),
             contentScale = contentScale,

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/base/ui/components/card/PreviewCard.kt

@@ -50,7 +50,7 @@ import coil.compose.AsyncImage
 import coil.compose.rememberAsyncImagePainter
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
-import org.mjdev.tvapp.base.extensions.ModifierExt.aspectRatio
+import org.mjdev.tvapp.base.extensions.ModifierExt.tvAspectRatio
 
 @OptIn(ExperimentalTvMaterial3Api::class)
 @Suppress("unused")
@@ -68,7 +68,7 @@ fun PreviewCard(
     thumbnailUrl: String? = null
 ) {
     Card(
-        modifier = modifier.aspectRatio(aspectRatio)
+        modifier = modifier.tvAspectRatio(aspectRatio)
     ) {
         val context = LocalContext.current
         var currentlyPlaying by remember { mutableStateOf(false) }

+ 12 - 2
app/src/main/kotlin/org/mjdev/tvapp/base/ui/components/complex/FocusableBox.kt

@@ -12,6 +12,7 @@ import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.FocusState
@@ -25,7 +26,10 @@ import androidx.tv.material3.Border
 import androidx.tv.material3.ClickableSurfaceDefaults
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.Surface
+import org.mjdev.tvapp.base.extensions.ComposeExt.isFocused
 import org.mjdev.tvapp.base.extensions.ComposeExt.rememberFocusRequester
+import org.mjdev.tvapp.base.extensions.ComposeExt.rememberFocusState
+import org.mjdev.tvapp.base.extensions.ModifierExt.focusState
 import org.mjdev.tvapp.base.extensions.ModifierExt.requestFocusOnTouch
 
 @OptIn(ExperimentalTvMaterial3Api::class)
@@ -43,7 +47,8 @@ fun FocusableBox(
     shape: Shape = RoundedCornerShape(roundCornerSize),
     borderColor: Color = Color.Transparent,
     borderSize: Dp = 0.dp,
-    focusRequester :FocusRequester= rememberFocusRequester(),
+    focusRequester: FocusRequester = rememberFocusRequester(),
+    focusState: MutableState<FocusState?> = rememberFocusState(),
     onFocusChange: (state: FocusState) -> Unit = {},
     onClick: () -> Unit = {},
     content: @Composable BoxScope.() -> Unit = {}
@@ -51,8 +56,13 @@ fun FocusableBox(
     Surface(
         onClick = onClick,
         modifier = modifier
+            .focusState(focusState)
             .onFocusChanged { state -> onFocusChange(state) }
-            .requestFocusOnTouch(focusRequester),
+            .requestFocusOnTouch(focusRequester) {
+                if (focusState.isFocused) {
+                    onClick()
+                }
+            },
         onLongClick = null,
         enabled = enabled,
         tonalElevation = tonalElevation,

+ 15 - 3
app/src/main/kotlin/org/mjdev/tvapp/base/ui/components/complex/FocusableCard.kt

@@ -12,6 +12,7 @@ import android.annotation.SuppressLint
 import androidx.compose.foundation.layout.defaultMinSize
 import androidx.compose.foundation.layout.padding
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.FocusState
@@ -29,7 +30,10 @@ import androidx.tv.material3.CardShape
 import androidx.tv.material3.CompactCard
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import org.mjdev.tvapp.base.extensions.ComposeExt
+import org.mjdev.tvapp.base.extensions.ComposeExt.isFocused
+import org.mjdev.tvapp.base.extensions.ComposeExt.rememberFocusState
 import org.mjdev.tvapp.base.extensions.ModifierExt.conditional
+import org.mjdev.tvapp.base.extensions.ModifierExt.focusState
 import org.mjdev.tvapp.base.extensions.ModifierExt.requestFocusOnTouch
 import org.mjdev.tvapp.base.interfaces.ItemWithDescription
 import org.mjdev.tvapp.base.interfaces.ItemWithImage
@@ -63,7 +67,8 @@ fun FocusableCard(
             placeholder = placeholder
         )
     },
-    focusRequester : FocusRequester = ComposeExt.rememberFocusRequester(),
+    focusRequester: FocusRequester = ComposeExt.rememberFocusRequester(),
+    focusState: MutableState<FocusState?> = rememberFocusState(),
     onFocusChange: (state: FocusState) -> Unit = {},
     onClick: (item: Any?) -> Unit = {},
 ) {
@@ -75,8 +80,15 @@ fun FocusableCard(
         border = border,
         glow = glow,
         modifier = modifier
-            .onFocusChanged { state -> onFocusChange(state) }
-            .requestFocusOnTouch(focusRequester)
+            .focusState(focusState)
+            .onFocusChanged { state ->
+                onFocusChange(state)
+            }
+            .requestFocusOnTouch(focusRequester) {
+                if (focusState.isFocused) {
+                    onClick(item)
+                }
+            }
             .conditional(isEdit) {
                 defaultMinSize(80.dp)
             },

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/base/ui/components/complex/TouchBox.kt

@@ -12,7 +12,6 @@ import android.annotation.SuppressLint
 import androidx.compose.foundation.gestures.detectDragGestures
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxScope
-import androidx.compose.foundation.layout.aspectRatio
 import androidx.compose.foundation.layout.defaultMinSize
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
@@ -26,6 +25,7 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.foundation.lazy.list.TvLazyListState
 import org.mjdev.tvapp.base.extensions.ComposeExt
 import org.mjdev.tvapp.base.extensions.ModifierExt.conditional
+import org.mjdev.tvapp.base.extensions.ModifierExt.tvAspectRatio
 
 @SuppressLint("AutoboxingStateValueProperty")
 @Preview
@@ -42,7 +42,7 @@ fun TouchBox(
     Box(
         modifier = modifier
             .conditional(isEdit) {
-                aspectRatio(16f / 9f).defaultMinSize(80.dp)
+                tvAspectRatio(16f / 9f).defaultMinSize(80.dp)
             }
             .pointerInput(Unit) {
                 detectDragGestures { _, dragAmount ->

+ 0 - 3
app/src/main/kotlin/org/mjdev/tvapp/base/ui/components/image/CircleImage.kt

@@ -38,7 +38,6 @@ fun CircleImage(
     contentPadding: Dp = 2.dp,
     src: Any? = R.drawable.milanj
 ) {
-
     Box(
         modifier = modifier.padding(contentPadding),
         contentAlignment = Alignment.Center,
@@ -59,7 +58,5 @@ fun CircleImage(
             contentDescription = contentDescription,
             contentScale = ContentScale.Crop,
         )
-
     }
-
 }

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/base/ui/components/text/CircleText.kt

@@ -13,7 +13,6 @@ import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.aspectRatio
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.shape.CircleShape
@@ -31,6 +30,7 @@ import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.MaterialTheme
+import org.mjdev.tvapp.base.extensions.ModifierExt.tvAspectRatio
 
 @OptIn(ExperimentalTvMaterial3Api::class)
 @SuppressLint("ModifierParameter")
@@ -51,7 +51,7 @@ fun CircleText(
         modifier = modifier
             .size(textSize.value.dp * 2)
             .padding(contentPadding)
-            .aspectRatio(1f)
+            .tvAspectRatio(1f)
             .clip(CircleShape)
             .background(backGroundColor, CircleShape)
             .border(

+ 0 - 2
app/src/main/kotlin/org/mjdev/tvapp/base/ui/components/tv/UserPic.kt

@@ -43,7 +43,6 @@ fun UserPic(
     shape = shape,
     onClick = onClick
 ) {
-
     val isEdit = isEditMode()
     CircleImage(
         modifier = modifier
@@ -56,5 +55,4 @@ fun UserPic(
         contentPadding = contentPadding + borderSize,
         src = src,
     )
-
 }