Skip to content

Commit 2413fe8

Browse files
committed
Add ChatClient.markMessagesAsDelivered function to mark messages as delivered
1 parent 040f926 commit 2413fe8

File tree

9 files changed

+139
-0
lines changed

9 files changed

+139
-0
lines changed

stream-chat-android-client/api/stream-chat-android-client.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ public final class io/getstream/chat/android/client/ChatClient {
112112
public static synthetic fun keystroke$default (Lio/getstream/chat/android/client/ChatClient;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lio/getstream/result/call/Call;
113113
public final fun markAllRead ()Lio/getstream/result/call/Call;
114114
public final fun markMessageRead (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lio/getstream/result/call/Call;
115+
public final fun markMessagesAsDelivered (Ljava/util/List;)Lio/getstream/result/call/Call;
115116
public final fun markRead (Ljava/lang/String;Ljava/lang/String;)Lio/getstream/result/call/Call;
116117
public final fun markThreadRead (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lio/getstream/result/call/Call;
117118
public final fun markThreadUnread (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lio/getstream/result/call/Call;

stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2882,6 +2882,22 @@ internal constructor(
28822882
}
28832883
}
28842884

2885+
/**
2886+
* Marks the given messages as delivered.
2887+
*
2888+
* @param messages The list of messages to mark as delivered.
2889+
*/
2890+
@CheckResult
2891+
public fun markMessagesAsDelivered(messages: List<Message>): Call<Unit> {
2892+
return api.markDelivered(messages)
2893+
.doOnStart(userScope) {
2894+
logger.d { "[markMessagesAsDelivered] #doOnStart; messages: ${messages.size}" }
2895+
}
2896+
.doOnResult(userScope) { result ->
2897+
logger.v { "[markMessagesAsDelivered] #doOnResult; completed: $result" }
2898+
}
2899+
}
2900+
28852901
/**
28862902
* Marks a given thread as read.
28872903
*

stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/ChatApi.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ internal interface ChatApi {
338338
messageId: String = "",
339339
): Call<Unit>
340340

341+
@CheckResult
342+
fun markDelivered(
343+
messages: List<Message>,
344+
): Call<Unit>
345+
341346
@CheckResult
342347
fun markThreadRead(
343348
channelType: String,

stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/MoshiChatApi.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import io.getstream.chat.android.client.api2.model.requests.FlagUserRequest
5757
import io.getstream.chat.android.client.api2.model.requests.GuestUserRequest
5858
import io.getstream.chat.android.client.api2.model.requests.HideChannelRequest
5959
import io.getstream.chat.android.client.api2.model.requests.InviteMembersRequest
60+
import io.getstream.chat.android.client.api2.model.requests.MarkDeliveredRequest
6061
import io.getstream.chat.android.client.api2.model.requests.MarkReadRequest
6162
import io.getstream.chat.android.client.api2.model.requests.MarkUnreadRequest
6263
import io.getstream.chat.android.client.api2.model.requests.MuteChannelRequest
@@ -960,6 +961,11 @@ constructor(
960961
).toUnitCall()
961962
}
962963

964+
override fun markDelivered(messages: List<Message>): Call<Unit> =
965+
channelApi.markDelivered(
966+
request = MarkDeliveredRequest.create(messages),
967+
).toUnitCall()
968+
963969
override fun markThreadRead(channelType: String, channelId: String, threadId: String): Call<Unit> {
964970
return channelApi.markRead(
965971
channelType = channelType,

stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/ChannelApi.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import io.getstream.chat.android.client.api2.model.requests.AcceptInviteRequest
2323
import io.getstream.chat.android.client.api2.model.requests.AddMembersRequest
2424
import io.getstream.chat.android.client.api2.model.requests.HideChannelRequest
2525
import io.getstream.chat.android.client.api2.model.requests.InviteMembersRequest
26+
import io.getstream.chat.android.client.api2.model.requests.MarkDeliveredRequest
2627
import io.getstream.chat.android.client.api2.model.requests.MarkReadRequest
2728
import io.getstream.chat.android.client.api2.model.requests.MarkUnreadRequest
2829
import io.getstream.chat.android.client.api2.model.requests.PinnedMessagesRequest
@@ -211,4 +212,9 @@ internal interface ChannelApi {
211212
@Path("id") channelId: String,
212213
@UrlQueryPayload @Query("payload") payload: PinnedMessagesRequest,
213214
): RetrofitCall<MessagesResponse>
215+
216+
@POST("/channels/delivered")
217+
fun markDelivered(
218+
@Body request: MarkDeliveredRequest,
219+
): RetrofitCall<CompletableResponse>
214220
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2014-2025 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.client.api2.model.requests
18+
19+
import com.squareup.moshi.JsonClass
20+
import io.getstream.chat.android.models.Message
21+
22+
@JsonClass(generateAdapter = true)
23+
internal data class MarkDeliveredRequest(
24+
val latest_delivered_messages: List<DeliveredMessageDto>,
25+
) {
26+
companion object {
27+
fun create(messages: List<Message>) = MarkDeliveredRequest(
28+
latest_delivered_messages = messages.map { info ->
29+
DeliveredMessageDto(
30+
cid = info.cid,
31+
id = info.id,
32+
)
33+
},
34+
)
35+
}
36+
}
37+
38+
@JsonClass(generateAdapter = true)
39+
internal data class DeliveredMessageDto(
40+
val cid: String,
41+
val id: String,
42+
)

stream-chat-android-client/src/test/java/io/getstream/chat/android/client/ChatClientChannelApiTests.kt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import io.getstream.chat.android.randomExtraData
4444
import io.getstream.chat.android.randomInt
4545
import io.getstream.chat.android.randomMember
4646
import io.getstream.chat.android.randomMessage
47+
import io.getstream.chat.android.randomMessageList
4748
import io.getstream.chat.android.randomString
4849
import io.getstream.chat.android.randomUser
4950
import io.getstream.result.Error
@@ -987,6 +988,33 @@ internal class ChatClientChannelApiTests : BaseChatClientTest() {
987988
verifyNetworkError(result, errorCode)
988989
}
989990

991+
@Test
992+
fun markMessagesAsDeliveredSuccess() = runTest {
993+
// given
994+
val messages = randomMessageList(10)
995+
val sut = Fixture()
996+
.givenMarkDeliveredResult(RetroSuccess(Unit).toRetrofitCall())
997+
.get()
998+
// when
999+
val result = sut.markMessagesAsDelivered(messages).await()
1000+
// then
1001+
verifySuccess(result, Unit)
1002+
}
1003+
1004+
@Test
1005+
fun markMessagesAsDeliveredError() = runTest {
1006+
// given
1007+
val messages = randomMessageList(10)
1008+
val errorCode = positiveRandomInt()
1009+
val sut = Fixture()
1010+
.givenMarkDeliveredResult(RetroError<Unit>(errorCode).toRetrofitCall())
1011+
.get()
1012+
// when
1013+
val result = sut.markMessagesAsDelivered(messages).await()
1014+
// then
1015+
verifyNetworkError(result, errorCode)
1016+
}
1017+
9901018
@Test
9911019
fun markReadSuccess() = runTest {
9921020
// given
@@ -1528,6 +1556,10 @@ internal class ChatClientChannelApiTests : BaseChatClientTest() {
15281556
whenever(api.markRead(any(), any(), any())).thenReturn(result)
15291557
}
15301558

1559+
fun givenMarkDeliveredResult(result: Call<Unit>) = apply {
1560+
whenever(api.markDelivered(any())).thenReturn(result)
1561+
}
1562+
15311563
fun givenMarkUnreadResult(result: Call<Unit>) = apply {
15321564
whenever(api.markUnread(any(), any(), any())).thenReturn(result)
15331565
}

stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/MoshiChatApiTest.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@ import io.getstream.chat.android.client.api2.model.requests.AcceptInviteRequest
4646
import io.getstream.chat.android.client.api2.model.requests.AddDeviceRequest
4747
import io.getstream.chat.android.client.api2.model.requests.BanUserRequest
4848
import io.getstream.chat.android.client.api2.model.requests.BlockUserRequest
49+
import io.getstream.chat.android.client.api2.model.requests.DeliveredMessageDto
4950
import io.getstream.chat.android.client.api2.model.requests.FlagMessageRequest
5051
import io.getstream.chat.android.client.api2.model.requests.FlagUserRequest
5152
import io.getstream.chat.android.client.api2.model.requests.GuestUserRequest
5253
import io.getstream.chat.android.client.api2.model.requests.HideChannelRequest
54+
import io.getstream.chat.android.client.api2.model.requests.MarkDeliveredRequest
5355
import io.getstream.chat.android.client.api2.model.requests.MarkReadRequest
5456
import io.getstream.chat.android.client.api2.model.requests.MarkUnreadRequest
5557
import io.getstream.chat.android.client.api2.model.requests.MuteChannelRequest
@@ -147,6 +149,7 @@ import io.getstream.chat.android.randomInt
147149
import io.getstream.chat.android.randomMember
148150
import io.getstream.chat.android.randomMemberData
149151
import io.getstream.chat.android.randomMessage
152+
import io.getstream.chat.android.randomMessageList
150153
import io.getstream.chat.android.randomPollConfig
151154
import io.getstream.chat.android.randomReaction
152155
import io.getstream.chat.android.randomString
@@ -1389,6 +1392,31 @@ internal class MoshiChatApiTest {
13891392
verify(api, times(1)).markRead(channelType, channelId, expectedRequest)
13901393
}
13911394

1395+
@ParameterizedTest
1396+
@MethodSource("io.getstream.chat.android.client.api2.MoshiChatApiTestArguments#markDeliveredInput")
1397+
fun testMarkDelivered(call: RetrofitCall<CompletableResponse>, expected: KClass<*>) = runTest {
1398+
// given
1399+
val api = mock<ChannelApi>()
1400+
whenever(api.markDelivered(any())).doReturn(call)
1401+
val sut = Fixture()
1402+
.withChannelApi(api)
1403+
.get()
1404+
// when
1405+
val messages = randomMessageList(10)
1406+
val result = sut.markDelivered(messages).await()
1407+
// then
1408+
val expectedRequest = MarkDeliveredRequest(
1409+
latest_delivered_messages = messages.map { messageInfo ->
1410+
DeliveredMessageDto(
1411+
cid = messageInfo.cid,
1412+
id = messageInfo.id,
1413+
)
1414+
},
1415+
)
1416+
result `should be instance of` expected
1417+
verify(api, times(1)).markDelivered(expectedRequest)
1418+
}
1419+
13921420
@ParameterizedTest
13931421
@MethodSource("io.getstream.chat.android.client.api2.MoshiChatApiTestArguments#markThreadReadInput")
13941422
fun testMarkThreadRead(call: RetrofitCall<CompletableResponse>, expected: KClass<*>) = runTest {

stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/MoshiChatApiTestArguments.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,9 @@ internal object MoshiChatApiTestArguments {
304304
@JvmStatic
305305
fun markReadInput() = completableResponseArguments()
306306

307+
@JvmStatic
308+
fun markDeliveredInput() = completableResponseArguments()
309+
307310
@JvmStatic
308311
fun markThreadReadInput() = completableResponseArguments()
309312

0 commit comments

Comments
 (0)