diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/MoshiChatApi.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/MoshiChatApi.kt index 2fc7d96ef3e..8d5dc042a59 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/MoshiChatApi.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/MoshiChatApi.kt @@ -1296,7 +1296,7 @@ constructor( channel.copy( watcherCount = response.watcher_count, read = response.read.map { - it.toDomain(lastReceivedEventDate = channel.lastMessageAt ?: it.last_read) + it.toDomain(lastReceivedEventDate = channel.lastMessageAt ?: it.lastRead) }, members = response.members.map { it.toDomain() }, membership = response.membership?.toDomain(), diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt index bfb80ec621d..3edf2687e95 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt @@ -23,7 +23,6 @@ import io.getstream.chat.android.TypingIndicators import io.getstream.chat.android.client.api2.model.dto.ChannelInfoDto import io.getstream.chat.android.client.api2.model.dto.DeviceDto import io.getstream.chat.android.client.api2.model.dto.DownstreamChannelDto -import io.getstream.chat.android.client.api2.model.dto.DownstreamChannelUserRead import io.getstream.chat.android.client.api2.model.dto.DownstreamDraftDto import io.getstream.chat.android.client.api2.model.dto.DownstreamFlagDto import io.getstream.chat.android.client.api2.model.dto.DownstreamLocationDto @@ -131,6 +130,7 @@ import io.getstream.chat.android.network.models.PushPreferencesResponse import io.getstream.chat.android.network.models.QueryPollsResponse import io.getstream.chat.android.network.models.ReactionGroupResponse import io.getstream.chat.android.network.models.ReactionResponse +import io.getstream.chat.android.network.models.ReadStateResponse import io.getstream.chat.android.network.models.UnreadCountsChannel import io.getstream.chat.android.network.models.UnreadCountsChannelType import io.getstream.chat.android.network.models.UnreadCountsThread @@ -201,7 +201,7 @@ internal class DomainMapping( watchers = watchers.map { it.toDomain() }, read = read.map { it.toDomain( - lastReceivedEventDate = last_message_at ?: it.last_read, + lastReceivedEventDate = last_message_at ?: it.lastRead, ) }, config = config?.toDomain() ?: Config(), @@ -707,21 +707,21 @@ internal class DomainMapping( } /** - * Transform [DownstreamChannelUserRead] to [ChannelUserRead]. + * Transform [ReadStateResponse] to [ChannelUserRead]. * * @param lastReceivedEventDate the last received event date. */ - internal fun DownstreamChannelUserRead.toDomain( + internal fun ReadStateResponse.toDomain( lastReceivedEventDate: Date, ): ChannelUserRead = ChannelUserRead( user = user.toDomain(), lastReceivedEventDate = lastReceivedEventDate, - lastRead = last_read, - unreadMessages = unread_messages, - lastReadMessageId = last_read_message_id, - lastDeliveredAt = last_delivered_at, - lastDeliveredMessageId = last_delivered_message_id, + lastRead = lastRead, + unreadMessages = unreadMessages, + lastReadMessageId = lastReadMessageId, + lastDeliveredAt = lastDeliveredAt, + lastDeliveredMessageId = lastDeliveredMessageId, ) /** diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ChannelDtos.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ChannelDtos.kt index 018ac27e1c9..81fc2d9ab40 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ChannelDtos.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ChannelDtos.kt @@ -19,6 +19,7 @@ package io.getstream.chat.android.client.api2.model.dto import com.squareup.moshi.JsonClass import io.getstream.chat.android.network.models.ChannelConfigWithInfo import io.getstream.chat.android.network.models.ChannelMemberResponse +import io.getstream.chat.android.network.models.ReadStateResponse import java.util.Date @JsonClass(generateAdapter = true) @@ -42,7 +43,7 @@ internal data class DownstreamChannelDto( val messages: List = emptyList(), val members: List = emptyList(), val watchers: List = emptyList(), - val read: List = emptyList(), + val read: List = emptyList(), // Absent for a channel whose type is no longer in the app config. val config: ChannelConfigWithInfo? = null, val created_by: DownstreamUserDto?, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/DownstreamChannelUserRead.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/DownstreamChannelUserRead.kt deleted file mode 100644 index 67b03f2c1e1..00000000000 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/DownstreamChannelUserRead.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2014-2026 Stream.io Inc. All rights reserved. - * - * Licensed under the Stream License; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.getstream.chat.android.client.api2.model.dto - -import com.squareup.moshi.JsonClass -import java.util.Date - -@JsonClass(generateAdapter = true) -internal data class DownstreamChannelUserRead( - val user: DownstreamUserDto, - val last_read: Date, - val unread_messages: Int, - val last_read_message_id: String?, - val last_delivered_at: Date? = null, - val last_delivered_message_id: String? = null, -) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ThreadDtos.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ThreadDtos.kt index e93476d06f4..6c2873ea3b7 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ThreadDtos.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/ThreadDtos.kt @@ -18,6 +18,7 @@ package io.getstream.chat.android.client.api2.model.dto import com.squareup.moshi.JsonClass import io.getstream.chat.android.network.models.ChannelResponse +import io.getstream.chat.android.network.models.ReadStateResponse import io.getstream.chat.android.network.models.ThreadParticipant import java.util.Date @@ -60,7 +61,7 @@ internal data class DownstreamThreadDto( val parent_message: DownstreamMessageDto, val parent_message_id: String, val participant_count: Int, - val read: List?, + val read: List?, val reply_count: Int?, val thread_participants: List?, val title: String, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/ChannelResponse.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/ChannelResponse.kt index 5123259ac9e..d6be7a20064 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/ChannelResponse.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/ChannelResponse.kt @@ -18,13 +18,13 @@ package io.getstream.chat.android.client.api2.model.response import com.squareup.moshi.JsonClass import io.getstream.chat.android.client.api2.model.dto.DownstreamChannelDto -import io.getstream.chat.android.client.api2.model.dto.DownstreamChannelUserRead import io.getstream.chat.android.client.api2.model.dto.DownstreamDraftDto import io.getstream.chat.android.client.api2.model.dto.DownstreamMessageDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPendingMessageDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPushPreferenceDto import io.getstream.chat.android.client.api2.model.dto.DownstreamUserDto import io.getstream.chat.android.network.models.ChannelMemberResponse +import io.getstream.chat.android.network.models.ReadStateResponse import java.util.Date @JsonClass(generateAdapter = true) @@ -37,7 +37,7 @@ internal data class ChannelResponse( val members: List = emptyList(), val membership: ChannelMemberResponse?, val watchers: List = emptyList(), - val read: List = emptyList(), + val read: List = emptyList(), val watcher_count: Int = 0, val hidden: Boolean?, val hide_messages_before: Date?, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/ReadStateResponse.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/ReadStateResponse.kt new file mode 100644 index 00000000000..4312c184e4c --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/ReadStateResponse.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014-2026 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport", +) + +package io.getstream.chat.android.network.models + +import com.squareup.moshi.Json + +/** + * + */ +@com.squareup.moshi.JsonClass(generateAdapter = true) +internal data class ReadStateResponse( + @Json(name = "last_read") + internal val lastRead: java.util.Date, + + @Json(name = "unread_messages") + internal val unreadMessages: Int, + + @Json(name = "user") + internal val user: io.getstream.chat.android.network.models.UserResponse, + + @Json(name = "last_delivered_at") + internal val lastDeliveredAt: java.util.Date? = null, + + @Json(name = "last_delivered_message_id") + internal val lastDeliveredMessageId: String? = null, + + @Json(name = "last_read_message_id") + internal val lastReadMessageId: String? = null, +) diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt index 206a8c34700..c867b0058ae 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt @@ -26,7 +26,6 @@ import io.getstream.chat.android.client.api.models.UpdatePollRequest import io.getstream.chat.android.client.api2.model.dto.ChannelInfoDto import io.getstream.chat.android.client.api2.model.dto.DeviceDto import io.getstream.chat.android.client.api2.model.dto.DownstreamChannelDto -import io.getstream.chat.android.client.api2.model.dto.DownstreamChannelUserRead import io.getstream.chat.android.client.api2.model.dto.DownstreamDraftDto import io.getstream.chat.android.client.api2.model.dto.DownstreamDraftMessageDto import io.getstream.chat.android.client.api2.model.dto.DownstreamFlagDto @@ -95,6 +94,7 @@ import io.getstream.chat.android.network.models.PrivacySettingsResponse import io.getstream.chat.android.network.models.QueryPollsResponse import io.getstream.chat.android.network.models.ReactionGroupResponse import io.getstream.chat.android.network.models.ReactionResponse +import io.getstream.chat.android.network.models.ReadStateResponse import io.getstream.chat.android.network.models.ThreadParticipant import io.getstream.chat.android.network.models.UnblockUsersResponse import io.getstream.chat.android.network.models.UnreadCountsChannel @@ -452,7 +452,7 @@ internal object Mother { messages: List = emptyList(), members: List = emptyList(), watchers: List = emptyList(), - read: List = emptyList(), + read: List = emptyList(), config: ChannelConfigWithInfo = randomChannelConfigWithInfo(), created_by: DownstreamUserDto? = randomDownstreamUserDto(), team: String = randomString(), @@ -707,20 +707,20 @@ internal object Mother { extraData = extraData, ) - fun randomDownstreamChannelUserRead( - user: DownstreamUserDto = randomDownstreamUserDto(), + fun randomReadStateResponse( + user: UserResponse = randomUserResponse(), lastRead: Date = randomDate(), unreadMessages: Int = randomInt(), lastReadMessageId: String? = randomStringOrNull(), lastDeliveredAt: Date? = randomDateOrNull(), lastDeliveredMessageId: String? = randomStringOrNull(), - ) = DownstreamChannelUserRead( + ) = ReadStateResponse( user = user, - last_read = lastRead, - unread_messages = unreadMessages, - last_read_message_id = lastReadMessageId, - last_delivered_at = lastDeliveredAt, - last_delivered_message_id = lastDeliveredMessageId, + lastRead = lastRead, + unreadMessages = unreadMessages, + lastReadMessageId = lastReadMessageId, + lastDeliveredAt = lastDeliveredAt, + lastDeliveredMessageId = lastDeliveredMessageId, ) fun randomGetOGResponse( @@ -931,7 +931,7 @@ internal object Mother { deletedAt: Date? = randomDateOrNull(), title: String = randomString(), latestReplies: List = listOf(randomDownstreamMessageDto()), - read: List = listOf(randomDownstreamChannelUserRead()), + read: List = listOf(randomReadStateResponse()), replyCount: Int = randomInt(), draft: DownstreamDraftDto? = randomDownstreamDraftDto(), extraData: Map = randomExtraData(maxPossibleEntries = 2), diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt index 71ae7e23f35..3f161338eb9 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt @@ -30,7 +30,6 @@ import io.getstream.chat.android.client.Mother.randomChannelResponse import io.getstream.chat.android.client.Mother.randomCommandDto import io.getstream.chat.android.client.Mother.randomDeviceResponse import io.getstream.chat.android.client.Mother.randomDownstreamChannelDto -import io.getstream.chat.android.client.Mother.randomDownstreamChannelUserRead import io.getstream.chat.android.client.Mother.randomDownstreamDraftDto import io.getstream.chat.android.client.Mother.randomDownstreamDraftMessageDto import io.getstream.chat.android.client.Mother.randomDownstreamFlagDto @@ -53,6 +52,7 @@ import io.getstream.chat.android.client.Mother.randomQueryPollsResponse import io.getstream.chat.android.client.Mother.randomQueryRemindersResponse import io.getstream.chat.android.client.Mother.randomReactionGroupResponse import io.getstream.chat.android.client.Mother.randomReactionResponse +import io.getstream.chat.android.client.Mother.randomReadStateResponse import io.getstream.chat.android.client.Mother.randomRoleDto import io.getstream.chat.android.client.Mother.randomSearchWarningDto import io.getstream.chat.android.client.Mother.randomThreadParticipantDto @@ -1067,21 +1067,21 @@ internal class DomainMappingTest { } @Test - fun `DownstreamChannelUserRead is correctly mapped to ChannelUserRead`() { - val downstreamChannelUserRead = randomDownstreamChannelUserRead() + fun `ReadStateResponse is correctly mapped to ChannelUserRead`() { + val readStateResponse = randomReadStateResponse() val lastReceivedEventDate = randomDate() val sut = Fixture().get() val channelUserRead = with(sut) { - downstreamChannelUserRead.toDomain(lastReceivedEventDate) + readStateResponse.toDomain(lastReceivedEventDate) } val expected = ChannelUserRead( - user = with(sut) { downstreamChannelUserRead.user.toDomain() }, - lastRead = downstreamChannelUserRead.last_read, - unreadMessages = downstreamChannelUserRead.unread_messages, - lastReadMessageId = downstreamChannelUserRead.last_read_message_id, + user = with(sut) { readStateResponse.user.toDomain() }, + lastRead = readStateResponse.lastRead, + unreadMessages = readStateResponse.unreadMessages, + lastReadMessageId = readStateResponse.lastReadMessageId, lastReceivedEventDate = lastReceivedEventDate, - lastDeliveredAt = downstreamChannelUserRead.last_delivered_at, - lastDeliveredMessageId = downstreamChannelUserRead.last_delivered_message_id, + lastDeliveredAt = readStateResponse.lastDeliveredAt, + lastDeliveredMessageId = readStateResponse.lastDeliveredMessageId, ) assertEquals(expected, channelUserRead) diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ChannelDtoTestData.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ChannelDtoTestData.kt index 919a268f0e3..04529b5d7a2 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ChannelDtoTestData.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ChannelDtoTestData.kt @@ -17,12 +17,12 @@ package io.getstream.chat.android.client.parser2.testdata import io.getstream.chat.android.client.api2.model.dto.DownstreamChannelDto -import io.getstream.chat.android.client.api2.model.dto.DownstreamChannelUserRead import io.getstream.chat.android.models.ChannelCapabilities import io.getstream.chat.android.network.models.ChannelConfigWithInfo import io.getstream.chat.android.network.models.ChannelMemberResponse import io.getstream.chat.android.network.models.ChannelOwnCapability import io.getstream.chat.android.network.models.ChannelResponse +import io.getstream.chat.android.network.models.ReadStateResponse import org.intellij.lang.annotations.Language import java.util.Date import io.getstream.chat.android.network.models.Command as CommandDto @@ -150,7 +150,7 @@ internal object ChannelDtoTestData { "watchers": [${UserDtoTestData.downstreamJson}], "read": [ { - "user": ${UserDtoTestData.downstreamJson}, + "user": ${UserDtoTestData.userResponseJson}, "last_read": "2020-06-10T11:04:31.0Z", "unread_messages": 1, "last_read_message_id": "messageId" @@ -216,11 +216,11 @@ internal object ChannelDtoTestData { ), watchers = listOf(UserDtoTestData.downstreamUser), read = listOf( - DownstreamChannelUserRead( - user = UserDtoTestData.downstreamUser, - last_read = Date(1591787071000), - unread_messages = 1, - last_read_message_id = "messageId", + ReadStateResponse( + user = UserDtoTestData.userResponse, + lastRead = Date(1591787071000), + unreadMessages = 1, + lastReadMessageId = "messageId", ), ), config = expectedConfig, diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ThreadDtoTestData.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ThreadDtoTestData.kt index cf41ecb85e5..e063b836b75 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ThreadDtoTestData.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/ThreadDtoTestData.kt @@ -18,6 +18,7 @@ package io.getstream.chat.android.client.parser2.testdata import io.getstream.chat.android.client.api2.model.dto.DownstreamThreadDto import io.getstream.chat.android.client.api2.model.dto.DownstreamThreadInfoDto +import io.getstream.chat.android.network.models.ReadStateResponse import io.getstream.chat.android.network.models.ThreadParticipant import org.intellij.lang.annotations.Language import java.util.Date @@ -40,7 +41,14 @@ internal object ThreadDtoTestData { "parent_message": ${MessageDtoTestData.downstreamJsonWithoutExtraData}, "parent_message_id": "parent_msg_id", "participant_count": 5, - "read": [], + "read": [ + { + "user": ${UserDtoTestData.userResponseJson}, + "last_read": "2020-06-10T11:04:31.0Z", + "unread_messages": 1, + "last_read_message_id": "messageId" + } + ], "reply_count": 10, "thread_participants": [ { @@ -86,7 +94,14 @@ internal object ThreadDtoTestData { parent_message = MessageDtoTestData.downstreamMessageWithoutExtraData, parent_message_id = "parent_msg_id", participant_count = 5, - read = emptyList(), + read = listOf( + ReadStateResponse( + user = UserDtoTestData.userResponse, + lastRead = Date(1591787071000), + unreadMessages = 1, + lastReadMessageId = "messageId", + ), + ), reply_count = 10, thread_participants = listOf( ThreadParticipant(