Skip to content

Commit 3e0b982

Browse files
committed
Attempt to reduce swipe sensitivity (#810)
1 parent dca5ee8 commit 3e0b982

File tree

1 file changed

+58
-30
lines changed
  • features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components

1 file changed

+58
-30
lines changed

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,16 @@ import androidx.compose.foundation.layout.wrapContentHeight
3838
import androidx.compose.foundation.shape.RoundedCornerShape
3939
import androidx.compose.material3.MaterialTheme
4040
import androidx.compose.runtime.Composable
41+
import androidx.compose.runtime.CompositionLocalProvider
4142
import androidx.compose.runtime.remember
4243
import androidx.compose.runtime.rememberCoroutineScope
4344
import androidx.compose.ui.Alignment
4445
import androidx.compose.ui.Modifier
4546
import androidx.compose.ui.draw.clip
4647
import androidx.compose.ui.draw.clipToBounds
4748
import androidx.compose.ui.geometry.Offset
49+
import androidx.compose.ui.platform.LocalViewConfiguration
50+
import androidx.compose.ui.platform.ViewConfiguration
4851
import androidx.compose.ui.res.stringResource
4952
import androidx.compose.ui.text.style.TextAlign
5053
import androidx.compose.ui.text.style.TextOverflow
@@ -137,37 +140,39 @@ fun TimelineItemEventRow(
137140
val offset = state.offset.value
138141
val swipeThresholdPx = 40.dp.toPx()
139142
val thresholdCrossed = abs(offset) > swipeThresholdPx
140-
Box(Modifier.fillMaxWidth()) {
141-
Row(modifier = Modifier.matchParentSize()) {
142-
ReplySwipeIndicator({ offset / 120 })
143-
}
144-
TimelineItemEventRowContent(
145-
modifier = Modifier
146-
.absoluteOffset { IntOffset(x = offset.roundToInt(), y = 0) }
147-
.draggable(
148-
orientation = Orientation.Horizontal,
149-
enabled = !state.isResettingOnRelease,
150-
onDragStopped = {
151-
coroutineScope.launch {
152-
if (thresholdCrossed) {
153-
onSwipeToReply()
143+
SwipeSensitivity(3f) {
144+
Box(Modifier.fillMaxWidth()) {
145+
Row(modifier = Modifier.matchParentSize()) {
146+
ReplySwipeIndicator({ offset / 120 })
147+
}
148+
TimelineItemEventRowContent(
149+
modifier = Modifier
150+
.absoluteOffset { IntOffset(x = offset.roundToInt(), y = 0) }
151+
.draggable(
152+
orientation = Orientation.Horizontal,
153+
enabled = !state.isResettingOnRelease,
154+
onDragStopped = {
155+
coroutineScope.launch {
156+
if (thresholdCrossed) {
157+
onSwipeToReply()
158+
}
159+
state.resetOffset()
154160
}
155-
state.resetOffset()
156-
}
157-
},
158-
state = state.draggableState,
159-
),
160-
event = event,
161-
isHighlighted = isHighlighted,
162-
interactionSource = interactionSource,
163-
onClick = onClick,
164-
onLongClick = onLongClick,
165-
onTimestampClicked = onTimestampClicked,
166-
inReplyToClicked = ::inReplyToClicked,
167-
onUserDataClicked = ::onUserDataClicked,
168-
onReactionClicked = { emoji -> onReactionClick(emoji, event) },
169-
onMoreReactionsClicked = { onMoreReactionsClick(event) },
170-
)
161+
},
162+
state = state.draggableState,
163+
),
164+
event = event,
165+
isHighlighted = isHighlighted,
166+
interactionSource = interactionSource,
167+
onClick = onClick,
168+
onLongClick = onLongClick,
169+
onTimestampClicked = onTimestampClicked,
170+
inReplyToClicked = ::inReplyToClicked,
171+
onUserDataClicked = ::onUserDataClicked,
172+
onReactionClicked = { emoji -> onReactionClick(emoji, event) },
173+
onMoreReactionsClicked = { onMoreReactionsClick(event) },
174+
)
175+
}
171176
}
172177
} else {
173178
TimelineItemEventRowContent(
@@ -186,6 +191,29 @@ fun TimelineItemEventRow(
186191
}
187192
}
188193

194+
/**
195+
* Impact ViewConfiguration.touchSlop by [sensitivityFactor].
196+
* Inspired from https://issuetracker.google.com/u/1/issues/269627294.
197+
* @param sensitivityFactor the factor to multiply the touchSlop by. The highest value, the more the user will
198+
* have to drag to start the drag.
199+
* @param content the content to display.
200+
*/
201+
@Composable
202+
fun SwipeSensitivity(
203+
sensitivityFactor: Float,
204+
content: @Composable () -> Unit,
205+
) {
206+
val current = LocalViewConfiguration.current
207+
CompositionLocalProvider(
208+
LocalViewConfiguration provides object : ViewConfiguration by current {
209+
override val touchSlop: Float
210+
get() = current.touchSlop * sensitivityFactor
211+
}
212+
) {
213+
content()
214+
}
215+
}
216+
189217
@Composable
190218
private fun TimelineItemEventRowContent(
191219
event: TimelineItem.Event,

0 commit comments

Comments
 (0)