Просмотр исходного кода

MangaChapterListItem: Increase swipe action touch slop (#9598)

Ivan Iskandar 1 год назад
Родитель
Сommit
9ec8d770ea

+ 185 - 174
app/src/main/java/eu/kanade/presentation/manga/components/MangaChapterListItem.kt

@@ -32,6 +32,7 @@ import androidx.compose.material3.ProvideTextStyle
 import androidx.compose.material3.Text
 import androidx.compose.material3.contentColorFor
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableIntStateOf
@@ -43,6 +44,8 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.alpha
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.LocalViewConfiguration
+import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
@@ -74,201 +77,209 @@ fun MangaChapterListItem(
     onDownloadClick: ((ChapterDownloadAction) -> Unit)?,
     onChapterSwipe: (LibraryPreferences.ChapterSwipeAction) -> Unit,
 ) {
-    val textAlpha = if (read) ReadItemAlpha else 1f
-    val textSubtitleAlpha = if (read) ReadItemAlpha else SecondaryItemAlpha
-
-    val chapterSwipeStartEnabled = chapterSwipeStartAction != LibraryPreferences.ChapterSwipeAction.Disabled
-    val chapterSwipeEndEnabled = chapterSwipeEndAction != LibraryPreferences.ChapterSwipeAction.Disabled
-
-    val dismissState = rememberDismissState()
-    val dismissDirections = remember { mutableSetOf<DismissDirection>() }
-    var lastDismissDirection: DismissDirection? by remember { mutableStateOf(null) }
-    if (lastDismissDirection == null) {
-        if (chapterSwipeStartEnabled) {
-            dismissDirections.add(DismissDirection.EndToStart)
-        }
-        if (chapterSwipeEndEnabled) {
-            dismissDirections.add(DismissDirection.StartToEnd)
-        }
-    }
-    val animateDismissContentAlpha by animateFloatAsState(
-        label = "animateDismissContentAlpha",
-        targetValue = if (lastDismissDirection != null) 1f else 0f,
-        animationSpec = tween(durationMillis = if (lastDismissDirection != null) 500 else 0),
-        finishedListener = {
-            lastDismissDirection = null
+    // Increase touch slop of swipe action to reduce accidental trigger
+    val configuration = LocalViewConfiguration.current
+    CompositionLocalProvider(
+        LocalViewConfiguration provides object : ViewConfiguration by configuration {
+            override val touchSlop: Float = configuration.touchSlop * 3f
         },
-    )
-    val dismissContentAlpha = if (lastDismissDirection != null) animateDismissContentAlpha else 1f
-    val backgroundColor = if (chapterSwipeEndEnabled && (dismissState.dismissDirection == DismissDirection.StartToEnd || lastDismissDirection == DismissDirection.StartToEnd)) {
-        MaterialTheme.colorScheme.primary
-    } else if (chapterSwipeStartEnabled && (dismissState.dismissDirection == DismissDirection.EndToStart || lastDismissDirection == DismissDirection.EndToStart)) {
-        MaterialTheme.colorScheme.primary
-    } else {
-        Color.Unspecified
-    }
+    ) {
+        val textAlpha = if (read) ReadItemAlpha else 1f
+        val textSubtitleAlpha = if (read) ReadItemAlpha else SecondaryItemAlpha
+
+        val chapterSwipeStartEnabled = chapterSwipeStartAction != LibraryPreferences.ChapterSwipeAction.Disabled
+        val chapterSwipeEndEnabled = chapterSwipeEndAction != LibraryPreferences.ChapterSwipeAction.Disabled
 
-    LaunchedEffect(dismissState.currentValue) {
-        when (dismissState.currentValue) {
-            DismissValue.DismissedToEnd -> {
-                lastDismissDirection = DismissDirection.StartToEnd
-                val dismissDirectionsCopy = dismissDirections.toSet()
-                dismissDirections.clear()
-                onChapterSwipe(chapterSwipeEndAction)
-                dismissState.snapTo(DismissValue.Default)
-                dismissDirections.addAll(dismissDirectionsCopy)
+        val dismissState = rememberDismissState()
+        val dismissDirections = remember { mutableSetOf<DismissDirection>() }
+        var lastDismissDirection: DismissDirection? by remember { mutableStateOf(null) }
+        if (lastDismissDirection == null) {
+            if (chapterSwipeStartEnabled) {
+                dismissDirections.add(DismissDirection.EndToStart)
             }
-            DismissValue.DismissedToStart -> {
-                lastDismissDirection = DismissDirection.EndToStart
-                val dismissDirectionsCopy = dismissDirections.toSet()
-                dismissDirections.clear()
-                onChapterSwipe(chapterSwipeStartAction)
-                dismissState.snapTo(DismissValue.Default)
-                dismissDirections.addAll(dismissDirectionsCopy)
+            if (chapterSwipeEndEnabled) {
+                dismissDirections.add(DismissDirection.StartToEnd)
             }
-            DismissValue.Default -> { }
         }
-    }
+        val animateDismissContentAlpha by animateFloatAsState(
+            label = "animateDismissContentAlpha",
+            targetValue = if (lastDismissDirection != null) 1f else 0f,
+            animationSpec = tween(durationMillis = if (lastDismissDirection != null) 500 else 0),
+            finishedListener = {
+                lastDismissDirection = null
+            },
+        )
+        val dismissContentAlpha = if (lastDismissDirection != null) animateDismissContentAlpha else 1f
+        val backgroundColor = if (chapterSwipeEndEnabled && (dismissState.dismissDirection == DismissDirection.StartToEnd || lastDismissDirection == DismissDirection.StartToEnd)) {
+            MaterialTheme.colorScheme.primary
+        } else if (chapterSwipeStartEnabled && (dismissState.dismissDirection == DismissDirection.EndToStart || lastDismissDirection == DismissDirection.EndToStart)) {
+            MaterialTheme.colorScheme.primary
+        } else {
+            Color.Unspecified
+        }
 
-    SwipeToDismiss(
-        state = dismissState,
-        directions = dismissDirections,
-        background = {
-            Box(
-                modifier = Modifier
-                    .fillMaxSize()
-                    .background(backgroundColor),
-            ) {
-                if (dismissState.dismissDirection in dismissDirections) {
-                    val downloadState = downloadStateProvider()
-                    SwipeBackgroundIcon(
-                        modifier = Modifier
-                            .padding(start = 16.dp)
-                            .align(Alignment.CenterStart)
-                            .alpha(
-                                if (dismissState.dismissDirection == DismissDirection.StartToEnd) 1f else 0f,
-                            ),
-                        tint = contentColorFor(backgroundColor),
-                        swipeAction = chapterSwipeEndAction,
-                        read = read,
-                        bookmark = bookmark,
-                        downloadState = downloadState,
-                    )
-                    SwipeBackgroundIcon(
-                        modifier = Modifier
-                            .padding(end = 16.dp)
-                            .align(Alignment.CenterEnd)
-                            .alpha(
-                                if (dismissState.dismissDirection == DismissDirection.EndToStart) 1f else 0f,
-                            ),
-                        tint = contentColorFor(backgroundColor),
-                        swipeAction = chapterSwipeStartAction,
-                        read = read,
-                        bookmark = bookmark,
-                        downloadState = downloadState,
-                    )
+        LaunchedEffect(dismissState.currentValue) {
+            when (dismissState.currentValue) {
+                DismissValue.DismissedToEnd -> {
+                    lastDismissDirection = DismissDirection.StartToEnd
+                    val dismissDirectionsCopy = dismissDirections.toSet()
+                    dismissDirections.clear()
+                    onChapterSwipe(chapterSwipeEndAction)
+                    dismissState.snapTo(DismissValue.Default)
+                    dismissDirections.addAll(dismissDirectionsCopy)
                 }
+                DismissValue.DismissedToStart -> {
+                    lastDismissDirection = DismissDirection.EndToStart
+                    val dismissDirectionsCopy = dismissDirections.toSet()
+                    dismissDirections.clear()
+                    onChapterSwipe(chapterSwipeStartAction)
+                    dismissState.snapTo(DismissValue.Default)
+                    dismissDirections.addAll(dismissDirectionsCopy)
+                }
+                DismissValue.Default -> { }
             }
-        },
-        dismissContent = {
-            Row(
-                modifier = modifier
-                    .background(
-                        MaterialTheme.colorScheme.background.copy(dismissContentAlpha),
-                    )
-                    .selectedBackground(selected)
-                    .alpha(dismissContentAlpha)
-                    .combinedClickable(
-                        onClick = onClick,
-                        onLongClick = onLongClick,
-                    )
-                    .padding(start = 16.dp, top = 12.dp, end = 8.dp, bottom = 12.dp),
-            ) {
-                Column(
-                    modifier = Modifier.weight(1f),
-                    verticalArrangement = Arrangement.spacedBy(6.dp),
+        }
+
+        SwipeToDismiss(
+            state = dismissState,
+            directions = dismissDirections,
+            background = {
+                Box(
+                    modifier = Modifier
+                        .fillMaxSize()
+                        .background(backgroundColor),
                 ) {
-                    Row(
-                        horizontalArrangement = Arrangement.spacedBy(2.dp),
-                        verticalAlignment = Alignment.CenterVertically,
-                    ) {
-                        var textHeight by remember { mutableIntStateOf(0) }
-                        if (!read) {
-                            Icon(
-                                imageVector = Icons.Filled.Circle,
-                                contentDescription = stringResource(R.string.unread),
-                                modifier = Modifier
-                                    .height(8.dp)
-                                    .padding(end = 4.dp),
-                                tint = MaterialTheme.colorScheme.primary,
-                            )
-                        }
-                        if (bookmark) {
-                            Icon(
-                                imageVector = Icons.Filled.Bookmark,
-                                contentDescription = stringResource(R.string.action_filter_bookmarked),
-                                modifier = Modifier
-                                    .sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }),
-                                tint = MaterialTheme.colorScheme.primary,
-                            )
-                        }
-                        Text(
-                            text = title,
-                            style = MaterialTheme.typography.bodyMedium,
-                            color = LocalContentColor.current.copy(alpha = textAlpha),
-                            maxLines = 1,
-                            overflow = TextOverflow.Ellipsis,
-                            onTextLayout = { textHeight = it.size.height },
+                    if (dismissState.dismissDirection in dismissDirections) {
+                        val downloadState = downloadStateProvider()
+                        SwipeBackgroundIcon(
+                            modifier = Modifier
+                                .padding(start = 16.dp)
+                                .align(Alignment.CenterStart)
+                                .alpha(
+                                    if (dismissState.dismissDirection == DismissDirection.StartToEnd) 1f else 0f,
+                                ),
+                            tint = contentColorFor(backgroundColor),
+                            swipeAction = chapterSwipeEndAction,
+                            read = read,
+                            bookmark = bookmark,
+                            downloadState = downloadState,
+                        )
+                        SwipeBackgroundIcon(
+                            modifier = Modifier
+                                .padding(end = 16.dp)
+                                .align(Alignment.CenterEnd)
+                                .alpha(
+                                    if (dismissState.dismissDirection == DismissDirection.EndToStart) 1f else 0f,
+                                ),
+                            tint = contentColorFor(backgroundColor),
+                            swipeAction = chapterSwipeStartAction,
+                            read = read,
+                            bookmark = bookmark,
+                            downloadState = downloadState,
                         )
                     }
-
-                    Row {
-                        ProvideTextStyle(
-                            value = MaterialTheme.typography.bodyMedium.copy(
-                                fontSize = 12.sp,
-                                color = LocalContentColor.current.copy(alpha = textSubtitleAlpha),
-                            ),
+                }
+            },
+            dismissContent = {
+                Row(
+                    modifier = modifier
+                        .background(
+                            MaterialTheme.colorScheme.background.copy(dismissContentAlpha),
+                        )
+                        .selectedBackground(selected)
+                        .alpha(dismissContentAlpha)
+                        .combinedClickable(
+                            onClick = onClick,
+                            onLongClick = onLongClick,
+                        )
+                        .padding(start = 16.dp, top = 12.dp, end = 8.dp, bottom = 12.dp),
+                ) {
+                    Column(
+                        modifier = Modifier.weight(1f),
+                        verticalArrangement = Arrangement.spacedBy(6.dp),
+                    ) {
+                        Row(
+                            horizontalArrangement = Arrangement.spacedBy(2.dp),
+                            verticalAlignment = Alignment.CenterVertically,
                         ) {
-                            if (date != null) {
-                                Text(
-                                    text = date,
-                                    maxLines = 1,
-                                    overflow = TextOverflow.Ellipsis,
+                            var textHeight by remember { mutableIntStateOf(0) }
+                            if (!read) {
+                                Icon(
+                                    imageVector = Icons.Filled.Circle,
+                                    contentDescription = stringResource(R.string.unread),
+                                    modifier = Modifier
+                                        .height(8.dp)
+                                        .padding(end = 4.dp),
+                                    tint = MaterialTheme.colorScheme.primary,
                                 )
-                                if (readProgress != null || scanlator != null) DotSeparatorText()
                             }
-                            if (readProgress != null) {
-                                Text(
-                                    text = readProgress,
-                                    maxLines = 1,
-                                    overflow = TextOverflow.Ellipsis,
-                                    modifier = Modifier.alpha(ReadItemAlpha),
+                            if (bookmark) {
+                                Icon(
+                                    imageVector = Icons.Filled.Bookmark,
+                                    contentDescription = stringResource(R.string.action_filter_bookmarked),
+                                    modifier = Modifier
+                                        .sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }),
+                                    tint = MaterialTheme.colorScheme.primary,
                                 )
-                                if (scanlator != null) DotSeparatorText()
                             }
-                            if (scanlator != null) {
-                                Text(
-                                    text = scanlator,
-                                    maxLines = 1,
-                                    overflow = TextOverflow.Ellipsis,
-                                )
+                            Text(
+                                text = title,
+                                style = MaterialTheme.typography.bodyMedium,
+                                color = LocalContentColor.current.copy(alpha = textAlpha),
+                                maxLines = 1,
+                                overflow = TextOverflow.Ellipsis,
+                                onTextLayout = { textHeight = it.size.height },
+                            )
+                        }
+
+                        Row {
+                            ProvideTextStyle(
+                                value = MaterialTheme.typography.bodyMedium.copy(
+                                    fontSize = 12.sp,
+                                    color = LocalContentColor.current.copy(alpha = textSubtitleAlpha),
+                                ),
+                            ) {
+                                if (date != null) {
+                                    Text(
+                                        text = date,
+                                        maxLines = 1,
+                                        overflow = TextOverflow.Ellipsis,
+                                    )
+                                    if (readProgress != null || scanlator != null) DotSeparatorText()
+                                }
+                                if (readProgress != null) {
+                                    Text(
+                                        text = readProgress,
+                                        maxLines = 1,
+                                        overflow = TextOverflow.Ellipsis,
+                                        modifier = Modifier.alpha(ReadItemAlpha),
+                                    )
+                                    if (scanlator != null) DotSeparatorText()
+                                }
+                                if (scanlator != null) {
+                                    Text(
+                                        text = scanlator,
+                                        maxLines = 1,
+                                        overflow = TextOverflow.Ellipsis,
+                                    )
+                                }
                             }
                         }
                     }
-                }
 
-                if (onDownloadClick != null) {
-                    ChapterDownloadIndicator(
-                        enabled = downloadIndicatorEnabled,
-                        modifier = Modifier.padding(start = 4.dp),
-                        downloadStateProvider = downloadStateProvider,
-                        downloadProgressProvider = downloadProgressProvider,
-                        onClick = onDownloadClick,
-                    )
+                    if (onDownloadClick != null) {
+                        ChapterDownloadIndicator(
+                            enabled = downloadIndicatorEnabled,
+                            modifier = Modifier.padding(start = 4.dp),
+                            downloadStateProvider = downloadStateProvider,
+                            downloadProgressProvider = downloadProgressProvider,
+                            onClick = onDownloadClick,
+                        )
+                    }
                 }
-            }
-        },
-    )
+            },
+        )
+    }
 }
 
 @Composable