From 51654e4b96a4d58c43d02d4c145eadb304173684 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 17 Nov 2023 16:32:00 +0100 Subject: [PATCH] Send state: show if null and is last message. Read receipt: Also show the send state even if the flag for read receipt is set to false. --- .../messages/impl/timeline/TimelineView.kt | 5 +++ .../components/TimelineItemEventRow.kt | 44 ++++++++++++------- .../receipt/ReadReceiptViewState.kt | 1 + .../receipt/ReadReceiptViewStateProvider.kt | 2 + .../receipt/TimelineItemReadReceiptView.kt | 44 ++++++++----------- 5 files changed, 54 insertions(+), 42 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 7e4030a7c3..1d831e5e21 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -128,6 +128,8 @@ fun TimelineView( TimelineItemRow( timelineItem = timelineItem, showReadReceipts = state.showReadReceipts, + isLastOutgoingMessage = (timelineItem as? TimelineItem.Event)?.isMine == true + && state.timelineItems.first().identifier() == timelineItem.identifier(), highlightedItem = state.highlightedEventId?.value, userHasPermissionToSendMessage = state.userHasPermissionToSendMessage, onClick = onMessageClicked, @@ -173,6 +175,7 @@ fun TimelineView( private fun TimelineItemRow( timelineItem: TimelineItem, showReadReceipts: Boolean, + isLastOutgoingMessage: Boolean, highlightedItem: String?, userHasPermissionToSendMessage: Boolean, sessionState: SessionState, @@ -211,6 +214,7 @@ private fun TimelineItemRow( TimelineItemEventRow( event = timelineItem, showReadReceipts = showReadReceipts, + isLastOutgoingMessage = isLastOutgoingMessage, isHighlighted = highlightedItem == timelineItem.identifier(), canReply = userHasPermissionToSendMessage && timelineItem.content.canBeRepliedTo(), onClick = { onClick(timelineItem) }, @@ -252,6 +256,7 @@ private fun TimelineItemRow( TimelineItemRow( timelineItem = subGroupEvent, showReadReceipts = showReadReceipts, + isLastOutgoingMessage = isLastOutgoingMessage, highlightedItem = highlightedItem, sessionState = sessionState, userHasPermissionToSendMessage = false, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 5c816bef7b..839501e429 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -117,6 +117,7 @@ import kotlin.math.roundToInt fun TimelineItemEventRow( event: TimelineItem.Event, showReadReceipts: Boolean, + isLastOutgoingMessage: Boolean, isHighlighted: Boolean, canReply: Boolean, onClick: () -> Unit, @@ -178,6 +179,7 @@ fun TimelineItemEventRow( ), event = event, showReadReceipts = showReadReceipts, + isLastOutgoingMessage = isLastOutgoingMessage, isHighlighted = isHighlighted, interactionSource = interactionSource, onClick = onClick, @@ -197,6 +199,7 @@ fun TimelineItemEventRow( TimelineItemEventRowContent( event = event, showReadReceipts = showReadReceipts, + isLastOutgoingMessage = isLastOutgoingMessage, isHighlighted = isHighlighted, interactionSource = interactionSource, onClick = onClick, @@ -241,6 +244,7 @@ private fun SwipeSensitivity( private fun TimelineItemEventRowContent( event: TimelineItem.Event, showReadReceipts: Boolean, + isLastOutgoingMessage: Boolean, isHighlighted: Boolean, interactionSource: MutableInteractionSource, onClick: () -> Unit, @@ -339,23 +343,23 @@ private fun TimelineItemEventRowContent( } // Read receipts / Send state - if (showReadReceipts) { - TimelineItemReadReceiptView( - state = ReadReceiptViewState( - sendState = event.localSendState, - receipts = event.readReceiptState.receipts, - ), - onReadReceiptsClicked = onReadReceiptsClicked, - modifier = Modifier - .constrainAs(readReceipts) { - if (event.reactionsState.reactions.isNotEmpty()) { - top.linkTo(reactions.bottom, margin = 4.dp) - } else { - top.linkTo(message.bottom, margin = 4.dp) - } + TimelineItemReadReceiptView( + state = ReadReceiptViewState( + sendState = event.localSendState, + isLastOutgoingMessage = isLastOutgoingMessage, + receipts = event.readReceiptState.receipts, + ), + showReadReceipts = showReadReceipts, + onReadReceiptsClicked = onReadReceiptsClicked, + modifier = Modifier + .constrainAs(readReceipts) { + if (event.reactionsState.reactions.isNotEmpty()) { + top.linkTo(reactions.bottom, margin = 4.dp) + } else { + top.linkTo(message.bottom, margin = 4.dp) } - ) - } + } + ) } } @@ -685,6 +689,7 @@ internal fun TimelineItemEventRowPreview() = ElementPreview { groupPosition = TimelineItemGroupPosition.First, ), showReadReceipts = false, + isLastOutgoingMessage = false, isHighlighted = false, canReply = true, onClick = {}, @@ -708,6 +713,7 @@ internal fun TimelineItemEventRowPreview() = ElementPreview { groupPosition = TimelineItemGroupPosition.Last, ), showReadReceipts = false, + isLastOutgoingMessage = false, isHighlighted = false, canReply = true, onClick = {}, @@ -749,6 +755,7 @@ internal fun TimelineItemEventRowWithReplyPreview() = ElementPreview { groupPosition = TimelineItemGroupPosition.First, ), showReadReceipts = false, + isLastOutgoingMessage = false, isHighlighted = false, canReply = true, onClick = {}, @@ -774,6 +781,7 @@ internal fun TimelineItemEventRowWithReplyPreview() = ElementPreview { groupPosition = TimelineItemGroupPosition.Last, ), showReadReceipts = false, + isLastOutgoingMessage = false, isHighlighted = false, canReply = true, onClick = {}, @@ -827,6 +835,7 @@ internal fun TimelineItemEventRowTimestampPreview( senderDisplayName = if (useDocument) "Document case" else "Text case", ), showReadReceipts = false, + isLastOutgoingMessage = false, isHighlighted = false, canReply = true, onClick = {}, @@ -861,6 +870,7 @@ internal fun TimelineItemEventRowWithManyReactionsPreview() = ElementPreview { timelineItemReactions = aTimelineItemReactions(count = 20), ), showReadReceipts = false, + isLastOutgoingMessage = false, isHighlighted = false, canReply = true, onClick = {}, @@ -888,6 +898,7 @@ internal fun TimelineItemEventRowLongSenderNamePreview() = ElementPreviewLight { senderDisplayName = "a long sender display name to test single line and ellipsis at the end of the line", ), showReadReceipts = false, + isLastOutgoingMessage = false, isHighlighted = false, canReply = true, onClick = {}, @@ -911,6 +922,7 @@ internal fun TimelineItemEventTimestampBelowPreview() = ElementPreviewLight { TimelineItemEventRow( event = aTimelineItemEvent(content = aTimelineItemPollContent()), showReadReceipts = false, + isLastOutgoingMessage = false, isHighlighted = false, canReply = true, onClick = {}, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewState.kt index 2bf1d524ae..a15ecc781b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewState.kt @@ -22,5 +22,6 @@ import kotlinx.collections.immutable.ImmutableList data class ReadReceiptViewState( val sendState: LocalEventSendState?, + val isLastOutgoingMessage: Boolean, val receipts: ImmutableList, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateProvider.kt index 06520b1808..e0f72b010d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/ReadReceiptViewStateProvider.kt @@ -56,9 +56,11 @@ class ReadReceiptViewStateProvider : PreviewParameterProvider = emptyList(), ) = ReadReceiptViewState( sendState = sendState, + isLastOutgoingMessage = isLastOutgoingMessage, receipts = receipts.toImmutableList(), ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt index 3f35a10392..8725b365d0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt @@ -58,11 +58,23 @@ import kotlinx.collections.immutable.ImmutableList @Composable fun TimelineItemReadReceiptView( state: ReadReceiptViewState, + showReadReceipts: Boolean, onReadReceiptsClicked: () -> Unit, modifier: Modifier = Modifier, ) { - when (state.sendState) { - LocalEventSendState.Canceled -> Unit + if (state.receipts.isNotEmpty()) { + if (showReadReceipts) { + ReadReceiptsRow(modifier = modifier) { + ReadReceiptsAvatars( + receipts = state.receipts, + modifier = Modifier + .clip(RoundedCornerShape(4.dp)) + .clickable { onReadReceiptsClicked() } + .padding(2.dp) + ) + } + } + } else when (state.sendState) { LocalEventSendState.NotSentYet -> { ReadReceiptsRow(modifier) { Icon( @@ -73,11 +85,13 @@ fun TimelineItemReadReceiptView( ) } } + LocalEventSendState.Canceled -> Unit is LocalEventSendState.SendingFailed -> { // Error? The timestamp is already displayed in red } + null, is LocalEventSendState.Sent -> { - if (state.receipts.isEmpty()) { + if (state.isLastOutgoingMessage) { ReadReceiptsRow(modifier = modifier) { Icon( modifier = Modifier.padding(2.dp), @@ -86,29 +100,6 @@ fun TimelineItemReadReceiptView( tint = ElementTheme.colors.iconSecondary ) } - } else { - ReadReceiptsRow(modifier = modifier) { - ReadReceiptsAvatars( - receipts = state.receipts, - modifier = Modifier - .clip(RoundedCornerShape(4.dp)) - .clickable { onReadReceiptsClicked() } - .padding(2.dp) - ) - } - } - } - null -> { - if (state.receipts.isNotEmpty()) { - ReadReceiptsRow(modifier = modifier) { - ReadReceiptsAvatars( - receipts = state.receipts, - modifier = Modifier - .clip(RoundedCornerShape(4.dp)) - .clickable { onReadReceiptsClicked() } - .padding(2.dp) - ) - } } } } @@ -214,6 +205,7 @@ internal fun TimelineItemReactionsViewPreview( ) = ElementPreview { TimelineItemReadReceiptView( state = state, + showReadReceipts = true, onReadReceiptsClicked = {}, ) }