Hide message delivery status indicators when read events are disabled… · GetStream/stream-chat-android@7e057ec · GitHub
Skip to content

Commit 7e057ec

Browse files
authored
Hide message delivery status indicators when read events are disabled (#6578)
* compose: Hide message delivery status indicators when read events are disabled * ui-components: Hide message delivery status indicators when read events are disabled
1 parent bbc01ad commit 7e057ec

15 files changed

Lines changed: 244 additions & 26 deletions

File tree

‎stream-chat-android-compose-sample/src/androidTestE2eDebug/kotlin/io/getstream/chat/android/compose/tests/MessageDeliveryStatusTests.kt‎

Lines changed: 0 additions & 7 deletions

‎stream-chat-android-compose/api/stream-chat-android-compose.api‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,7 @@ public final class io/getstream/chat/android/compose/ui/components/channels/Comp
13381338

13391339
public final class io/getstream/chat/android/compose/ui/components/channels/MessageReadStatusIconKt {
13401340
public static final fun MessageReadStatusIcon (Lio/getstream/chat/android/models/Channel;Lio/getstream/chat/android/models/Message;Lio/getstream/chat/android/models/User;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;II)V
1341-
public static final fun MessageReadStatusIcon (Lio/getstream/chat/android/models/Message;ZLandroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
1341+
public static final fun MessageReadStatusIcon (Lio/getstream/chat/android/models/Message;ZLandroidx/compose/ui/Modifier;ZZZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
13421342
}
13431343

13441344
public final class io/getstream/chat/android/compose/ui/components/channels/UnreadCountIndicatorKt {

‎stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/channels/MessageReadStatusIcon.kt‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public fun MessageReadStatusIcon(
6363
message = message,
6464
isMessageRead = isMessageRead,
6565
isMessageDelivered = isMessageDelivered,
66+
readEventsEnabled = channel.config.readEventsEnabled,
67+
deliveryEventsEnabled = channel.config.deliveryEventsEnabled,
6668
)
6769
}
6870

@@ -73,13 +75,19 @@ public fun MessageReadStatusIcon(
7375
* @param isMessageRead If the message is read by any member.
7476
* @param isMessageDelivered If the message is delivered to any member.
7577
* @param modifier Modifier for styling.
78+
* @param readEventsEnabled If read events are enabled for the channel. When disabled, the sent and read
79+
* icons are not shown.
80+
* @param deliveryEventsEnabled If delivery events are enabled for the channel. When disabled, the delivered
81+
* icon is not shown.
7682
*/
7783
@Composable
7884
public fun MessageReadStatusIcon(
7985
message: Message,
8086
isMessageRead: Boolean,
8187
modifier: Modifier = Modifier,
8288
isMessageDelivered: Boolean = false,
89+
readEventsEnabled: Boolean = true,
90+
deliveryEventsEnabled: Boolean = true,
8391
isReadIcon: @Composable () -> Unit = { IsReadIcon(modifier = modifier) },
8492
isPendingIcon: @Composable () -> Unit = { IsPendingIcon(modifier = modifier) },
8593
isSentIcon: @Composable () -> Unit = { IsSentIcon(modifier = modifier) },
@@ -94,9 +102,9 @@ public fun MessageReadStatusIcon(
94102
-> isPendingIcon()
95103

96104
SyncStatus.COMPLETED -> when {
97-
isMessageRead -> isReadIcon()
98-
isMessageDelivered -> isDeliveredIcon()
99-
else -> isSentIcon()
105+
isMessageRead -> if (readEventsEnabled) isReadIcon()
106+
isMessageDelivered -> if (deliveryEventsEnabled) isDeliveredIcon()
107+
else -> if (readEventsEnabled) isSentIcon()
100108
}
101109

102110
SyncStatus.FAILED_PERMANENTLY -> IsErrorIcon(modifier = modifier)

‎stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,8 @@ public interface ChatComponentFactory {
12501250
message = params.messageItem.message,
12511251
isMessageRead = params.messageItem.isMessageRead,
12521252
isMessageDelivered = params.messageItem.isMessageDelivered,
1253+
readEventsEnabled = params.messageItem.readEventsEnabled,
1254+
deliveryEventsEnabled = params.messageItem.deliveryEventsEnabled,
12531255
)
12541256
}
12551257

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright (c) 2014-2026 Stream.io Inc. All rights reserved.
3+
*
4+
* Licensed under the Stream License;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://github.com/GetStream/stream-chat-android/blob/main/LICENSE
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.getstream.chat.android.compose.ui.components.channels
18+
19+
import androidx.compose.ui.test.junit4.createComposeRule
20+
import androidx.compose.ui.test.onNodeWithTag
21+
import androidx.test.ext.junit.runners.AndroidJUnit4
22+
import io.getstream.chat.android.client.test.MockedChatClientTest
23+
import io.getstream.chat.android.compose.ui.theme.ChatTheme
24+
import io.getstream.chat.android.models.ConnectionState
25+
import io.getstream.chat.android.models.SyncStatus
26+
import io.getstream.chat.android.randomMessage
27+
import io.getstream.chat.android.randomUser
28+
import kotlinx.coroutines.flow.MutableStateFlow
29+
import org.junit.Before
30+
import org.junit.Rule
31+
import org.junit.Test
32+
import org.junit.runner.RunWith
33+
import org.mockito.kotlin.doReturn
34+
import org.mockito.kotlin.whenever
35+
import org.robolectric.annotation.Config
36+
37+
@RunWith(AndroidJUnit4::class)
38+
@Config(sdk = [33])
39+
internal class MessageReadStatusIconBehaviorTest : MockedChatClientTest {
40+
41+
@get:Rule
42+
val composeTestRule = createComposeRule()
43+
44+
@Before
45+
fun prepare() {
46+
whenever(mockClientState.user) doReturn MutableStateFlow(randomUser())
47+
whenever(mockClientState.connectionState) doReturn MutableStateFlow(ConnectionState.Connected)
48+
}
49+
50+
@Test
51+
fun `sent icon is shown when read events are enabled`() {
52+
setIconContent(readEventsEnabled = true)
53+
54+
composeTestRule
55+
.onNodeWithTag("Stream_MessageReadStatus_isSent", useUnmergedTree = true)
56+
.assertExists()
57+
}
58+
59+
@Test
60+
fun `sent icon is hidden when read events are disabled`() {
61+
setIconContent(readEventsEnabled = false)
62+
63+
composeTestRule
64+
.onNodeWithTag("Stream_MessageReadStatus_isSent", useUnmergedTree = true)
65+
.assertDoesNotExist()
66+
}
67+
68+
@Test
69+
fun `read icon is hidden when read events are disabled`() {
70+
setIconContent(isMessageRead = true, readEventsEnabled = false)
71+
72+
composeTestRule
73+
.onNodeWithTag("Stream_MessageReadStatus_isRead", useUnmergedTree = true)
74+
.assertDoesNotExist()
75+
}
76+
77+
@Test
78+
fun `delivered icon is hidden when delivery events are disabled`() {
79+
setIconContent(isMessageDelivered = true, deliveryEventsEnabled = false)
80+
81+
composeTestRule
82+
.onNodeWithTag("Stream_MessageReadStatus_isDelivered", useUnmergedTree = true)
83+
.assertDoesNotExist()
84+
}
85+
86+
@Test
87+
fun `pending icon is shown when read events are disabled`() {
88+
setIconContent(syncStatus = SyncStatus.IN_PROGRESS, readEventsEnabled = false)
89+
90+
composeTestRule
91+
.onNodeWithTag("Stream_MessageReadStatus_isPending", useUnmergedTree = true)
92+
.assertExists()
93+
}
94+
95+
@Test
96+
fun `error icon is shown when read events are disabled`() {
97+
setIconContent(syncStatus = SyncStatus.FAILED_PERMANENTLY, readEventsEnabled = false)
98+
99+
composeTestRule
100+
.onNodeWithTag("Stream_MessageReadStatus_isError", useUnmergedTree = true)
101+
.assertExists()
102+
}
103+
104+
private fun setIconContent(
105+
syncStatus: SyncStatus = SyncStatus.COMPLETED,
106+
isMessageRead: Boolean = false,
107+
isMessageDelivered: Boolean = false,
108+
readEventsEnabled: Boolean = true,
109+
deliveryEventsEnabled: Boolean = true,
110+
) {
111+
composeTestRule.setContent {
112+
ChatTheme {
113+
MessageReadStatusIcon(
114+
message = randomMessage(syncStatus = syncStatus),
115+
isMessageRead = isMessageRead,
116+
isMessageDelivered = isMessageDelivered,
117+
readEventsEnabled = readEventsEnabled,
118+
deliveryEventsEnabled = deliveryEventsEnabled,
119+
)
120+
}
121+
}
122+
}
123+
}

‎stream-chat-android-ui-common/api/stream-chat-android-ui-common.api‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2757,14 +2757,16 @@ public final class io/getstream/chat/android/ui/common/state/messages/list/Messa
27572757

27582758
public final class io/getstream/chat/android/ui/common/state/messages/list/MessageItemState : io/getstream/chat/android/ui/common/state/messages/list/HasMessageListItemState {
27592759
public static final field $stable I
2760-
public fun <init> (Lio/getstream/chat/android/models/Message;Ljava/lang/String;ZZZLio/getstream/chat/android/models/User;Lio/getstream/chat/android/ui/common/state/messages/list/MessagePosition;ZZLio/getstream/chat/android/ui/common/state/messages/list/MessageFocusState;Ljava/util/List;ZLjava/util/Set;Z)V
2761-
public synthetic fun <init> (Lio/getstream/chat/android/models/Message;Ljava/lang/String;ZZZLio/getstream/chat/android/models/User;Lio/getstream/chat/android/ui/common/state/messages/list/MessagePosition;ZZLio/getstream/chat/android/ui/common/state/messages/list/MessageFocusState;Ljava/util/List;ZLjava/util/Set;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
2760+
public fun <init> (Lio/getstream/chat/android/models/Message;Ljava/lang/String;ZZZLio/getstream/chat/android/models/User;Lio/getstream/chat/android/ui/common/state/messages/list/MessagePosition;ZZLio/getstream/chat/android/ui/common/state/messages/list/MessageFocusState;Ljava/util/List;ZLjava/util/Set;ZZZ)V
2761+
public synthetic fun <init> (Lio/getstream/chat/android/models/Message;Ljava/lang/String;ZZZLio/getstream/chat/android/models/User;Lio/getstream/chat/android/ui/common/state/messages/list/MessagePosition;ZZLio/getstream/chat/android/ui/common/state/messages/list/MessageFocusState;Ljava/util/List;ZLjava/util/Set;ZZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
27622762
public final fun component1 ()Lio/getstream/chat/android/models/Message;
27632763
public final fun component10 ()Lio/getstream/chat/android/ui/common/state/messages/list/MessageFocusState;
27642764
public final fun component11 ()Ljava/util/List;
27652765
public final fun component12 ()Z
27662766
public final fun component13 ()Ljava/util/Set;
27672767
public final fun component14 ()Z
2768+
public final fun component15 ()Z
2769+
public final fun component16 ()Z
27682770
public final fun component2 ()Ljava/lang/String;
27692771
public final fun component3 ()Z
27702772
public final fun component4 ()Z
@@ -2773,16 +2775,18 @@ public final class io/getstream/chat/android/ui/common/state/messages/list/Messa
27732775
public final fun component7 ()Lio/getstream/chat/android/ui/common/state/messages/list/MessagePosition;
27742776
public final fun component8 ()Z
27752777
public final fun component9 ()Z
2776-
public final fun copy (Lio/getstream/chat/android/models/Message;Ljava/lang/String;ZZZLio/getstream/chat/android/models/User;Lio/getstream/chat/android/ui/common/state/messages/list/MessagePosition;ZZLio/getstream/chat/android/ui/common/state/messages/list/MessageFocusState;Ljava/util/List;ZLjava/util/Set;Z)Lio/getstream/chat/android/ui/common/state/messages/list/MessageItemState;
2777-
public static synthetic fun copy$default (Lio/getstream/chat/android/ui/common/state/messages/list/MessageItemState;Lio/getstream/chat/android/models/Message;Ljava/lang/String;ZZZLio/getstream/chat/android/models/User;Lio/getstream/chat/android/ui/common/state/messages/list/MessagePosition;ZZLio/getstream/chat/android/ui/common/state/messages/list/MessageFocusState;Ljava/util/List;ZLjava/util/Set;ZILjava/lang/Object;)Lio/getstream/chat/android/ui/common/state/messages/list/MessageItemState;
2778+
public final fun copy (Lio/getstream/chat/android/models/Message;Ljava/lang/String;ZZZLio/getstream/chat/android/models/User;Lio/getstream/chat/android/ui/common/state/messages/list/MessagePosition;ZZLio/getstream/chat/android/ui/common/state/messages/list/MessageFocusState;Ljava/util/List;ZLjava/util/Set;ZZZ)Lio/getstream/chat/android/ui/common/state/messages/list/MessageItemState;
2779+
public static synthetic fun copy$default (Lio/getstream/chat/android/ui/common/state/messages/list/MessageItemState;Lio/getstream/chat/android/models/Message;Ljava/lang/String;ZZZLio/getstream/chat/android/models/User;Lio/getstream/chat/android/ui/common/state/messages/list/MessagePosition;ZZLio/getstream/chat/android/ui/common/state/messages/list/MessageFocusState;Ljava/util/List;ZLjava/util/Set;ZZZILjava/lang/Object;)Lio/getstream/chat/android/ui/common/state/messages/list/MessageItemState;
27782780
public fun equals (Ljava/lang/Object;)Z
27792781
public final fun getCurrentUser ()Lio/getstream/chat/android/models/User;
2782+
public final fun getDeliveryEventsEnabled ()Z
27802783
public final fun getFocusState ()Lio/getstream/chat/android/ui/common/state/messages/list/MessageFocusState;
27812784
public final fun getGroupPosition ()Lio/getstream/chat/android/ui/common/state/messages/list/MessagePosition;
27822785
public fun getMessage ()Lio/getstream/chat/android/models/Message;
27832786
public final fun getMessageReadBy ()Ljava/util/List;
27842787
public final fun getOwnCapabilities ()Ljava/util/Set;
27852788
public final fun getParentMessageId ()Ljava/lang/String;
2789+
public final fun getReadEventsEnabled ()Z
27862790
public final fun getShowMessageFooter ()Z
27872791
public final fun getShowOriginalText ()Z
27882792
public fun hashCode ()I

‎stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListController.kt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,7 @@ public class MessageListController(
905905
): List<MessageListItemState> {
906906
val parentMessageId = (_mode.value as? MessageMode.MessageThread)?.parentMessage?.id
907907
val currentUser = user.value
908+
val channelConfig = channelState.value?.channelConfig?.value
908909
val groupedMessages = mutableListOf<MessageListItemState>()
909910
val membersMap = members.associateBy { it.user.id }
910911
val sortedReads = reads
@@ -1006,6 +1007,8 @@ public class MessageListController(
10061007
focusState = if (isMessageFocused) MessageFocused else null,
10071008
ownCapabilities = ownCapabilities,
10081009
showOriginalText = messagesInOriginalLanguage.contains(message.id),
1010+
readEventsEnabled = channelConfig?.readEventsEnabled ?: true,
1011+
deliveryEventsEnabled = channelConfig?.deliveryEventsEnabled ?: true,
10091012
),
10101013
)
10111014
}

‎stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/state/messages/list/MessageListItemState.kt‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public sealed class HasMessageListItemState : MessageListItemState() {
7171
* the message was auto-translated).
7272
* @param ownCapabilities The capabilities of the current user in the channel.
7373
* @param isPreviewMode Whether the message is displayed as a preview (e.g. inside the selected message menu).
74+
* @param readEventsEnabled Whether read events are enabled for the channel.
75+
* @param deliveryEventsEnabled Whether delivery events are enabled for the channel.
7476
*/
7577
public data class MessageItemState(
7678
public override val message: Message = Message(),
@@ -87,6 +89,8 @@ public data class MessageItemState(
8789
public val showOriginalText: Boolean = false,
8890
public val ownCapabilities: Set<String>,
8991
public val isPreviewMode: Boolean = false,
92+
public val readEventsEnabled: Boolean = true,
93+
public val deliveryEventsEnabled: Boolean = true,
9094
) : HasMessageListItemState()
9195

9296
/**

‎stream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListControllerTests.kt‎

Lines changed: 28 additions & 1 deletion

0 commit comments

Comments
 (0)