Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -267,18 +267,17 @@ public fun MessageItem(

val messageAlignment = ChatTheme.messageAlignmentProvider.provideMessageAlignment(messageItem)
val description = stringResource(id = R.string.stream_compose_cd_message_item)
val isSwipable = ChatTheme.messageOptionsTheme.optionVisibility
.canReplyToMessage(
message = message,
ownCapabilities = messageItem.ownCapabilities,
)
val optionVisibility = ChatTheme.messageOptionsTheme.optionVisibility
val isSwipeable = remember(message, messageItem.ownCapabilities, optionVisibility) {
optionVisibility.canReplyToMessage(message, messageItem.ownCapabilities)
}

// Remember the message to ensure updated values are captured in the onReply lambda
val replyMessage by rememberUpdatedState(message)
SwipeToReply(
modifier = modifier,
onReply = { onReply(replyMessage) },
isSwipeable = { isSwipable },
isSwipeable = isSwipeable,
swipeToReplyContent = swipeToReplyContent,
) {
Box(
Expand Down Expand Up @@ -735,7 +734,7 @@ private fun getMessageBubbleShape(position: List<MessagePosition>, ownsMessage:
*
* @param modifier Modifier for styling.
* @param onReply Handler when the user swipes to reply.
* @param isSwipeable Handler to determine if the message is swipeable.
* @param isSwipeable Indicator if swipe-to-reply is enabled.
* @param swipeToReplyContent The content to show when swiping to reply.
* @param content The swipeable content to show when not swiping to reply.
*/
Expand All @@ -744,7 +743,7 @@ private fun getMessageBubbleShape(position: List<MessagePosition>, ownsMessage:
private fun SwipeToReply(
modifier: Modifier = Modifier,
onReply: () -> Unit = {},
isSwipeable: () -> Boolean = { true },
isSwipeable: Boolean = true,
swipeToReplyContent: @Composable RowScope.() -> Unit,
content: @Composable () -> Unit,
) {
Expand Down Expand Up @@ -779,8 +778,8 @@ private fun SwipeToReply(
.fillMaxWidth()
.onSizeChanged { rowWidth = it.width.toFloat() }
.offset { IntOffset(x = offset.value.roundToInt(), y = 0) }
.pointerInput(swipeToReplyWidth) {
if (isSwipeable()) {
.pointerInput(swipeToReplyWidth, isSwipeable) {
if (isSwipeable) {
detectHorizontalDragGestures(
onHorizontalDrag = { change, dragAmount ->
// Only consume if horizontal drag dominates vertical
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import org.amshove.kluent.`should be`
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.Date

internal class MessageOptionItemVisibilityTest {

Expand Down Expand Up @@ -157,27 +158,38 @@ internal class MessageOptionItemVisibilityTest {

@JvmStatic
fun canReplyToMessageArguments() = listOf(
// case: reply disabled
Arguments.of(
MessageOptionItemVisibility(isReplyVisible = false),
randomMessage(),
randomMessage(deletedAt = null, deletedForMe = false),
randomChannelCapabilities(),
false,
),
// case: message not synced
Arguments.of(
MessageOptionItemVisibility(),
randomMessage(syncStatus = randomSyncStatus(exclude = listOf(SyncStatus.COMPLETED))),
randomChannelCapabilities(),
false,
),
// case: no QUOTE_MESSAGE capability
Arguments.of(
MessageOptionItemVisibility(),
randomMessage(),
randomMessage(deletedAt = null, deletedForMe = false),
randomChannelCapabilities(exclude = setOf(ChannelCapabilities.QUOTE_MESSAGE)),
false,
),
// case: message is deleted
Arguments.of(
MessageOptionItemVisibility(isReplyVisible = true),
randomMessage(syncStatus = SyncStatus.COMPLETED),
randomMessage(syncStatus = SyncStatus.COMPLETED, deletedAt = Date(), deletedForMe = false),
randomChannelCapabilities(include = setOf(ChannelCapabilities.QUOTE_MESSAGE)),
false,
),
// case: all conditions met
Arguments.of(
MessageOptionItemVisibility(isReplyVisible = true),
randomMessage(syncStatus = SyncStatus.COMPLETED, deletedAt = null, deletedForMe = false),
randomChannelCapabilities(include = setOf(ChannelCapabilities.QUOTE_MESSAGE)),
true,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package io.getstream.chat.android.ui.common.utils

import io.getstream.chat.android.client.utils.attachment.isGiphy
import io.getstream.chat.android.client.utils.message.hasSharedLocation
import io.getstream.chat.android.client.utils.message.isDeleted
import io.getstream.chat.android.client.utils.message.isThreadReply
import io.getstream.chat.android.models.AttachmentType
import io.getstream.chat.android.models.ChannelCapabilities
Expand Down Expand Up @@ -59,7 +60,10 @@ public fun canReplyToMessage(
replyEnabled: Boolean,
message: Message,
ownCapabilities: Set<String>,
): Boolean = replyEnabled && message.isSynced() && ownCapabilities.contains(ChannelCapabilities.QUOTE_MESSAGE)
): Boolean = replyEnabled &&
message.isSynced() &&
!message.isDeleted() &&
ownCapabilities.contains(ChannelCapabilities.QUOTE_MESSAGE)

/**
* Determines whether a thread reply can be made to the given message.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import org.amshove.kluent.`should be`
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.Date

internal class CapabilitiesHelperTest {

Expand Down Expand Up @@ -152,27 +153,38 @@ internal class CapabilitiesHelperTest {

@JvmStatic
fun canReplyToMessageArguments() = listOf(
// case: reply disabled
Arguments.of(
false,
randomMessage(),
randomChannelCapabilities(),
false,
),
// case: message not synced
Arguments.of(
randomBoolean(),
randomMessage(syncStatus = randomSyncStatus(exclude = listOf(SyncStatus.COMPLETED))),
randomChannelCapabilities(),
false,
),
// case: no QUOTE_MESSAGE capability
Arguments.of(
randomBoolean(),
randomMessage(),
randomMessage(deletedAt = null, deletedForMe = false),
randomChannelCapabilities(exclude = setOf(ChannelCapabilities.QUOTE_MESSAGE)),
false,
),
// case: message is deleted
Arguments.of(
true,
randomMessage(syncStatus = SyncStatus.COMPLETED),
randomMessage(syncStatus = SyncStatus.COMPLETED, deletedAt = Date(), deletedForMe = false),
randomChannelCapabilities(include = setOf(ChannelCapabilities.QUOTE_MESSAGE)),
false,
),
// case: all conditions met
Arguments.of(
true,
randomMessage(syncStatus = SyncStatus.COMPLETED, deletedAt = null, deletedForMe = false),
randomChannelCapabilities(include = setOf(ChannelCapabilities.QUOTE_MESSAGE)),
true,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import org.amshove.kluent.`should be`
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.Date

internal class MessageListViewExtensionsKtTest {

Expand Down Expand Up @@ -154,27 +155,42 @@ internal class MessageListViewExtensionsKtTest {

@JvmStatic
fun canReplyToMessageArguments() = listOf(
// case: reply disabled
Arguments.of(
randomMessageListViewStyle(replyEnabled = false),
randomMessage(),
randomMessage(deletedAt = null, deletedForMe = false),
randomChannelCapabilities(),
false,
),
// case: message not synced
Arguments.of(
randomMessageListViewStyle(),
randomMessage(syncStatus = randomSyncStatus(exclude = listOf(SyncStatus.COMPLETED))),
randomMessage(
syncStatus = randomSyncStatus(exclude = listOf(SyncStatus.COMPLETED)),
deletedAt = null,
deletedForMe = false,
),
randomChannelCapabilities(),
false,
),
// case: no QUOTE_MESSAGE capability
Arguments.of(
randomMessageListViewStyle(),
randomMessage(),
randomMessage(deletedAt = null, deletedForMe = false),
randomChannelCapabilities(exclude = setOf(ChannelCapabilities.QUOTE_MESSAGE)),
false,
),
// case: message is deleted
Arguments.of(
randomMessageListViewStyle(replyEnabled = true),
randomMessage(syncStatus = SyncStatus.COMPLETED),
randomMessage(syncStatus = SyncStatus.COMPLETED, deletedAt = Date(), deletedForMe = false),
randomChannelCapabilities(include = setOf(ChannelCapabilities.QUOTE_MESSAGE)),
false,
),
// case: all conditions met
Arguments.of(
randomMessageListViewStyle(replyEnabled = true),
randomMessage(syncStatus = SyncStatus.COMPLETED, deletedAt = null, deletedForMe = false),
randomChannelCapabilities(include = setOf(ChannelCapabilities.QUOTE_MESSAGE)),
true,
),
Expand Down
Loading