diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/GeneralApi.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/GeneralApi.kt index 64dc7e4343e..8b66de30052 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/GeneralApi.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/GeneralApi.kt @@ -19,7 +19,6 @@ package io.getstream.chat.android.client.api2.endpoint import io.getstream.chat.android.client.api.AuthenticatedApi import io.getstream.chat.android.client.api.QueryParams import io.getstream.chat.android.client.api2.UrlQueryPayload -import io.getstream.chat.android.client.api2.model.dto.UnreadDto import io.getstream.chat.android.client.api2.model.requests.QueryMembersRequest import io.getstream.chat.android.client.api2.model.requests.SyncHistoryRequest import io.getstream.chat.android.client.api2.model.response.QueryMembersResponse @@ -27,6 +26,7 @@ import io.getstream.chat.android.client.api2.model.response.SearchMessagesRespon import io.getstream.chat.android.client.api2.model.response.SyncHistoryResponse import io.getstream.chat.android.client.call.RetrofitCall import io.getstream.chat.android.network.models.SearchPayload +import io.getstream.chat.android.network.models.WrappedUnreadCountsResponse import okhttp3.ResponseBody import retrofit2.http.Body import retrofit2.http.GET @@ -56,5 +56,5 @@ internal interface GeneralApi { ): RetrofitCall @GET("/unread") - fun getUnreadCounts(): RetrofitCall + fun getUnreadCounts(): RetrofitCall } 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 0bbe50f886d..f769ce0eda9 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 @@ -57,10 +57,6 @@ import io.getstream.chat.android.client.api2.model.dto.PrivacySettingsDto import io.getstream.chat.android.client.api2.model.dto.ReadReceiptsDto import io.getstream.chat.android.client.api2.model.dto.SearchWarningDto import io.getstream.chat.android.client.api2.model.dto.TypingIndicatorsDto -import io.getstream.chat.android.client.api2.model.dto.UnreadChannelByTypeDto -import io.getstream.chat.android.client.api2.model.dto.UnreadChannelDto -import io.getstream.chat.android.client.api2.model.dto.UnreadDto -import io.getstream.chat.android.client.api2.model.dto.UnreadThreadDto import io.getstream.chat.android.client.api2.model.response.BannedUserResponse import io.getstream.chat.android.client.api2.model.response.MessageResponse import io.getstream.chat.android.client.api2.model.response.QueryPollVotesResponse @@ -135,7 +131,11 @@ import io.getstream.chat.android.network.models.AppResponseFields import io.getstream.chat.android.network.models.BlockUsersResponse import io.getstream.chat.android.network.models.DeviceResponse import io.getstream.chat.android.network.models.GetApplicationResponse +import io.getstream.chat.android.network.models.UnreadCountsChannel +import io.getstream.chat.android.network.models.UnreadCountsChannelType +import io.getstream.chat.android.network.models.UnreadCountsThread import io.getstream.chat.android.network.models.UserGroupResponse +import io.getstream.chat.android.network.models.WrappedUnreadCountsResponse import java.util.Date import io.getstream.chat.android.network.models.Command as CommandDto import io.getstream.chat.android.network.models.FileUploadConfig as UploadConfigDto @@ -897,32 +897,32 @@ internal class DomainMapping( next = next, ) - internal fun UnreadDto.toDomain(): UnreadCounts = UnreadCounts( - messagesCount = total_unread_count, - threadsCount = total_unread_threads_count, - messagesCountByTeam = total_unread_count_by_team.orEmpty(), + internal fun WrappedUnreadCountsResponse.toDomain(): UnreadCounts = UnreadCounts( + messagesCount = totalUnreadCount, + threadsCount = totalUnreadThreadsCount, + messagesCountByTeam = totalUnreadCountByTeam.orEmpty(), channels = channels.map { it.toDomain() }, threads = threads.map { it.toDomain() }, - channelsByType = channel_type.map { it.toDomain() }, + channelsByType = channelType.map { it.toDomain() }, ) - internal fun UnreadChannelDto.toDomain(): UnreadChannel = UnreadChannel( - cid = channel_id, - messagesCount = unread_count, - lastRead = last_read, + internal fun UnreadCountsChannel.toDomain(): UnreadChannel = UnreadChannel( + cid = channelId, + messagesCount = unreadCount, + lastRead = lastRead, ) - internal fun UnreadThreadDto.toDomain(): UnreadThread = UnreadThread( - parentMessageId = parent_message_id, - messagesCount = unread_count, - lastRead = last_read, - lastReadMessageId = last_read_message_id, + internal fun UnreadCountsThread.toDomain(): UnreadThread = UnreadThread( + parentMessageId = parentMessageId, + messagesCount = unreadCount, + lastRead = lastRead, + lastReadMessageId = lastReadMessageId, ) - internal fun UnreadChannelByTypeDto.toDomain(): UnreadChannelByType = UnreadChannelByType( - channelType = channel_type, - channelsCount = channel_count, - messagesCount = unread_count, + internal fun UnreadCountsChannelType.toDomain(): UnreadChannelByType = UnreadChannelByType( + channelType = channelType, + channelsCount = channelCount, + messagesCount = unreadCount, ) internal fun DownstreamPushPreferenceDto.toDomain(): PushPreference = PushPreference( diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/UnreadDtos.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/UnreadDtos.kt deleted file mode 100644 index ffeb08b35c5..00000000000 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/UnreadDtos.kt +++ /dev/null @@ -1,52 +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 UnreadDto( - val total_unread_count: Int = 0, - val total_unread_threads_count: Int = 0, - val total_unread_count_by_team: Map? = emptyMap(), - val channels: List = emptyList(), - val threads: List = emptyList(), - val channel_type: List = emptyList(), -) - -@JsonClass(generateAdapter = true) -internal data class UnreadChannelDto( - val channel_id: String, - val unread_count: Int, - val last_read: Date, -) - -@JsonClass(generateAdapter = true) -internal data class UnreadThreadDto( - val parent_message_id: String, - val unread_count: Int, - val last_read: Date, - val last_read_message_id: String, -) - -@JsonClass(generateAdapter = true) -internal data class UnreadChannelByTypeDto( - val channel_type: String, - val channel_count: Int, - val unread_count: Int, -) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UnreadCountsChannel.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UnreadCountsChannel.kt new file mode 100644 index 00000000000..bf568b1df42 --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UnreadCountsChannel.kt @@ -0,0 +1,41 @@ +/* + * 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 UnreadCountsChannel( + @Json(name = "channel_id") + internal val channelId: String, + + @Json(name = "last_read") + internal val lastRead: java.util.Date, + + @Json(name = "unread_count") + internal val unreadCount: Int, +) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UnreadCountsChannelType.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UnreadCountsChannelType.kt new file mode 100644 index 00000000000..a55f81accac --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UnreadCountsChannelType.kt @@ -0,0 +1,41 @@ +/* + * 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 UnreadCountsChannelType( + @Json(name = "channel_count") + internal val channelCount: Int, + + @Json(name = "channel_type") + internal val channelType: String, + + @Json(name = "unread_count") + internal val unreadCount: Int, +) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UnreadCountsThread.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UnreadCountsThread.kt new file mode 100644 index 00000000000..b6fff25d072 --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UnreadCountsThread.kt @@ -0,0 +1,44 @@ +/* + * 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 UnreadCountsThread( + @Json(name = "last_read") + internal val lastRead: java.util.Date, + + @Json(name = "last_read_message_id") + internal val lastReadMessageId: String, + + @Json(name = "parent_message_id") + internal val parentMessageId: String, + + @Json(name = "unread_count") + internal val unreadCount: Int, +) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/WrappedUnreadCountsResponse.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/WrappedUnreadCountsResponse.kt new file mode 100644 index 00000000000..0003382da1a --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/WrappedUnreadCountsResponse.kt @@ -0,0 +1,53 @@ +/* + * 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 + +/** + * Basic response information + */ +@com.squareup.moshi.JsonClass(generateAdapter = true) +internal data class WrappedUnreadCountsResponse( + @Json(name = "duration") + internal val duration: String, + + @Json(name = "total_unread_count") + internal val totalUnreadCount: Int, + + @Json(name = "total_unread_threads_count") + internal val totalUnreadThreadsCount: Int, + + @Json(name = "channel_type") + internal val channelType: List = emptyList(), + + @Json(name = "channels") + internal val channels: List = emptyList(), + + @Json(name = "threads") + internal val threads: List = emptyList(), + + @Json(name = "total_unread_count_by_team") + internal val totalUnreadCountByTeam: Map? = emptyMap(), +) 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 15c2fe5319d..10ec4e593a1 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 @@ -61,10 +61,6 @@ import io.getstream.chat.android.client.api2.model.dto.PrivacySettingsDto import io.getstream.chat.android.client.api2.model.dto.ReadReceiptsDto import io.getstream.chat.android.client.api2.model.dto.SearchWarningDto import io.getstream.chat.android.client.api2.model.dto.TypingIndicatorsDto -import io.getstream.chat.android.client.api2.model.dto.UnreadChannelByTypeDto -import io.getstream.chat.android.client.api2.model.dto.UnreadChannelDto -import io.getstream.chat.android.client.api2.model.dto.UnreadDto -import io.getstream.chat.android.client.api2.model.dto.UnreadThreadDto import io.getstream.chat.android.client.api2.model.response.BannedUserResponse import io.getstream.chat.android.client.api2.model.response.DraftMessageResponse import io.getstream.chat.android.client.api2.model.response.QueryDraftMessagesResponse @@ -103,7 +99,11 @@ import io.getstream.chat.android.network.models.DeviceResponse import io.getstream.chat.android.network.models.FileUploadConfig import io.getstream.chat.android.network.models.GetApplicationResponse import io.getstream.chat.android.network.models.UnblockUsersResponse +import io.getstream.chat.android.network.models.UnreadCountsChannel +import io.getstream.chat.android.network.models.UnreadCountsChannelType +import io.getstream.chat.android.network.models.UnreadCountsThread import io.getstream.chat.android.network.models.UserGroupResponse +import io.getstream.chat.android.network.models.WrappedUnreadCountsResponse import io.getstream.chat.android.positiveRandomInt import io.getstream.chat.android.randomBoolean import io.getstream.chat.android.randomCID @@ -1357,16 +1357,17 @@ internal object Mother { totalUnreadCount: Int = randomInt(), totalUnreadThreadsCount: Int = randomInt(), totalUnreadCountByTeam: Map = emptyMap(), - channels: List = emptyList(), - threads: List = emptyList(), - channelType: List = emptyList(), - ): UnreadDto = UnreadDto( - total_unread_count = totalUnreadCount, - total_unread_threads_count = totalUnreadThreadsCount, - total_unread_count_by_team = totalUnreadCountByTeam, + channels: List = emptyList(), + threads: List = emptyList(), + channelType: List = emptyList(), + ): WrappedUnreadCountsResponse = WrappedUnreadCountsResponse( + duration = randomString(), + totalUnreadCount = totalUnreadCount, + totalUnreadThreadsCount = totalUnreadThreadsCount, + totalUnreadCountByTeam = totalUnreadCountByTeam, channels = channels, threads = threads, - channel_type = channelType, + channelType = channelType, ) fun randomUnreadCountByTeamDto( @@ -1378,10 +1379,10 @@ internal object Mother { channelId: String = randomString(), unreadCount: Int = randomInt(), lastRead: Date = randomDate(), - ): UnreadChannelDto = UnreadChannelDto( - channel_id = channelId, - unread_count = unreadCount, - last_read = lastRead, + ): UnreadCountsChannel = UnreadCountsChannel( + channelId = channelId, + unreadCount = unreadCount, + lastRead = lastRead, ) fun randomUnreadThreadDto( @@ -1389,21 +1390,21 @@ internal object Mother { unreadCount: Int = randomInt(), lastRead: Date = randomDate(), lastReadMessageId: String = randomString(), - ): UnreadThreadDto = UnreadThreadDto( - parent_message_id = parentMessageId, - unread_count = unreadCount, - last_read = lastRead, - last_read_message_id = lastReadMessageId, + ): UnreadCountsThread = UnreadCountsThread( + parentMessageId = parentMessageId, + unreadCount = unreadCount, + lastRead = lastRead, + lastReadMessageId = lastReadMessageId, ) fun randomUnreadChannelByTypeDto( channelType: String = randomString(), channelCount: Int = randomInt(), unreadCount: Int = randomInt(), - ): UnreadChannelByTypeDto = UnreadChannelByTypeDto( - channel_type = channelType, - channel_count = channelCount, - unread_count = unreadCount, + ): UnreadCountsChannelType = UnreadCountsChannelType( + channelType = channelType, + channelCount = channelCount, + unreadCount = unreadCount, ) fun randomDownstreamPushPreferenceDto( diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/MoshiChatApiTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/MoshiChatApiTest.kt index 8c290fb3e84..5faae554767 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/MoshiChatApiTest.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/MoshiChatApiTest.kt @@ -42,7 +42,6 @@ import io.getstream.chat.android.client.api2.model.dto.AttachmentDto import io.getstream.chat.android.client.api2.model.dto.DownstreamChatPreferencesDto import io.getstream.chat.android.client.api2.model.dto.DownstreamLocationDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPushPreferenceDto -import io.getstream.chat.android.client.api2.model.dto.UnreadDto import io.getstream.chat.android.client.api2.model.dto.UpstreamChatPreferencesDto import io.getstream.chat.android.client.api2.model.dto.UpstreamPushPreferenceInputDto import io.getstream.chat.android.client.api2.model.requests.AcceptInviteRequest @@ -182,6 +181,7 @@ import io.getstream.chat.android.network.models.UpdateUserPartialRequest import io.getstream.chat.android.network.models.UpdateUsersPartialRequest import io.getstream.chat.android.network.models.UserRequest import io.getstream.chat.android.network.models.VoteData +import io.getstream.chat.android.network.models.WrappedUnreadCountsResponse import io.getstream.chat.android.positiveRandomInt import io.getstream.chat.android.randomBoolean import io.getstream.chat.android.randomCID @@ -3188,7 +3188,7 @@ internal class MoshiChatApiTest { @MethodSource("io.getstream.chat.android.client.api2.MoshiChatApiTestArguments#getUnreadCounts") fun testGetUnreadCounts( model: UnreadCounts, - dto: UnreadDto, + dto: WrappedUnreadCountsResponse, ) = runTest { val api = mock { on { getUnreadCounts() } doReturn RetroSuccess(dto).toRetrofitCall() diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/MoshiChatApiTestArguments.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/MoshiChatApiTestArguments.kt index 4b6b15a1eb3..bc45ff08607 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/MoshiChatApiTestArguments.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/MoshiChatApiTestArguments.kt @@ -721,29 +721,29 @@ internal object MoshiChatApiTestArguments { channelType = listOf(randomUnreadChannelByTypeDto()), ) val model = UnreadCounts( - messagesCount = dto.total_unread_count, - threadsCount = dto.total_unread_threads_count, - messagesCountByTeam = dto.total_unread_count_by_team!!, - channels = dto.channels.map { dto -> + messagesCount = dto.totalUnreadCount, + threadsCount = dto.totalUnreadThreadsCount, + messagesCountByTeam = dto.totalUnreadCountByTeam.orEmpty(), + channels = dto.channels.map { channel -> UnreadChannel( - cid = dto.channel_id, - messagesCount = dto.unread_count, - lastRead = dto.last_read, + cid = channel.channelId, + messagesCount = channel.unreadCount, + lastRead = channel.lastRead, ) }, - threads = dto.threads.map { dto -> + threads = dto.threads.map { thread -> UnreadThread( - parentMessageId = dto.parent_message_id, - messagesCount = dto.unread_count, - lastRead = dto.last_read, - lastReadMessageId = dto.last_read_message_id, + parentMessageId = thread.parentMessageId, + messagesCount = thread.unreadCount, + lastRead = thread.lastRead, + lastReadMessageId = thread.lastReadMessageId, ) }, - channelsByType = dto.channel_type.map { dto -> + channelsByType = dto.channelType.map { channelType -> UnreadChannelByType( - channelType = dto.channel_type, - channelsCount = dto.channel_count, - messagesCount = dto.unread_count, + channelType = channelType.channelType, + channelsCount = channelType.channelCount, + messagesCount = channelType.unreadCount, ) }, ) 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 54edd578268..01ae6b5368d 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 @@ -62,7 +62,6 @@ import io.getstream.chat.android.client.Mother.randomRoleDto import io.getstream.chat.android.client.Mother.randomSearchWarningDto import io.getstream.chat.android.client.Mother.randomUnreadChannelByTypeDto import io.getstream.chat.android.client.Mother.randomUnreadChannelDto -import io.getstream.chat.android.client.Mother.randomUnreadCountByTeamDto import io.getstream.chat.android.client.Mother.randomUnreadDto import io.getstream.chat.android.client.Mother.randomUnreadThreadDto import io.getstream.chat.android.client.Mother.randomUserGroupMemberDto @@ -1108,41 +1107,45 @@ internal class DomainMappingTest { } @Test - fun `UnreadDto is correctly mapped to UnreadCounts`() { + fun `WrappedUnreadCountsResponse is correctly mapped to UnreadCounts`() { + val lastRead = Date(1000) val input = randomUnreadDto( - totalUnreadCountByTeam = mapOf(randomUnreadCountByTeamDto()), - channels = listOf(randomUnreadChannelDto()), - threads = listOf(randomUnreadThreadDto()), - channelType = listOf(randomUnreadChannelByTypeDto()), + totalUnreadCount = 7, + totalUnreadThreadsCount = 3, + totalUnreadCountByTeam = mapOf("team-1" to 4), + channels = listOf( + randomUnreadChannelDto(channelId = "messaging:c1", unreadCount = 2, lastRead = lastRead), + ), + threads = listOf( + randomUnreadThreadDto( + parentMessageId = "parent-1", + unreadCount = 1, + lastRead = lastRead, + lastReadMessageId = "msg-1", + ), + ), + channelType = listOf( + randomUnreadChannelByTypeDto(channelType = "messaging", channelCount = 5, unreadCount = 6), + ), ) val sut = Fixture().get() val result = with(sut) { input.toDomain() } val expected = UnreadCounts( - messagesCount = input.total_unread_count, - threadsCount = input.total_unread_threads_count, - messagesCountByTeam = input.total_unread_count_by_team!!, - channels = input.channels.map { dto -> - UnreadChannel( - cid = dto.channel_id, - messagesCount = dto.unread_count, - lastRead = dto.last_read, - ) - }, - threads = input.threads.map { dto -> + messagesCount = 7, + threadsCount = 3, + messagesCountByTeam = mapOf("team-1" to 4), + channels = listOf(UnreadChannel(cid = "messaging:c1", messagesCount = 2, lastRead = lastRead)), + threads = listOf( UnreadThread( - parentMessageId = dto.parent_message_id, - messagesCount = dto.unread_count, - lastRead = dto.last_read, - lastReadMessageId = dto.last_read_message_id, - ) - }, - channelsByType = input.channel_type.map { dto -> - UnreadChannelByType( - channelType = dto.channel_type, - channelsCount = dto.channel_count, - messagesCount = dto.unread_count, - ) - }, + parentMessageId = "parent-1", + messagesCount = 1, + lastRead = lastRead, + lastReadMessageId = "msg-1", + ), + ), + channelsByType = listOf( + UnreadChannelByType(channelType = "messaging", channelsCount = 5, messagesCount = 6), + ), ) assertEquals(expected, result) } diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/UnreadCountsParsingTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/UnreadCountsParsingTest.kt new file mode 100644 index 00000000000..80b8bfcb34b --- /dev/null +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/UnreadCountsParsingTest.kt @@ -0,0 +1,95 @@ +/* + * 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.parser2 + +import io.getstream.chat.android.client.api2.mapping.DomainMapping +import io.getstream.chat.android.models.NoOpChannelTransformer +import io.getstream.chat.android.models.NoOpMessageTransformer +import io.getstream.chat.android.models.NoOpUserTransformer +import io.getstream.chat.android.models.UnreadChannel +import io.getstream.chat.android.models.UnreadChannelByType +import io.getstream.chat.android.models.UnreadThread +import io.getstream.chat.android.network.models.WrappedUnreadCountsResponse +import org.intellij.lang.annotations.Language +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import java.util.Date + +internal class UnreadCountsParsingTest { + + private val parser = ParserFactory.createMoshiChatParser() + + private val domainMapping = DomainMapping( + currentUserIdProvider = { "" }, + channelTransformer = NoOpChannelTransformer, + messageTransformer = NoOpMessageTransformer, + userTransformer = NoOpUserTransformer, + ) + + @Language("JSON") + private val json = + """{ + "duration": "1ms", + "total_unread_count": 7, + "total_unread_threads_count": 3, + "total_unread_count_by_team": { "team-1": 4 }, + "channels": [ + { "channel_id": "messaging:c1", "unread_count": 2, "last_read": "1970-01-01T00:00:01.000Z" } + ], + "threads": [ + { + "parent_message_id": "parent-1", + "unread_count": 1, + "last_read": "1970-01-01T00:00:01.000Z", + "last_read_message_id": "msg-1" + } + ], + "channel_type": [ + { "channel_type": "messaging", "channel_count": 5, "unread_count": 6 } + ] + }""" + + @Test + fun `deserializes the unread counts wire shape and maps it to UnreadCounts`() { + val dto = parser.fromJson(json, WrappedUnreadCountsResponse::class.java) + + val unreadCounts = with(domainMapping) { dto.toDomain() } + + assertEquals(7, unreadCounts.messagesCount) + assertEquals(3, unreadCounts.threadsCount) + assertEquals(mapOf("team-1" to 4), unreadCounts.messagesCountByTeam) + assertEquals( + listOf(UnreadChannel(cid = "messaging:c1", messagesCount = 2, lastRead = Date(1000))), + unreadCounts.channels, + ) + assertEquals( + listOf( + UnreadThread( + parentMessageId = "parent-1", + messagesCount = 1, + lastRead = Date(1000), + lastReadMessageId = "msg-1", + ), + ), + unreadCounts.threads, + ) + assertEquals( + listOf(UnreadChannelByType(channelType = "messaging", channelsCount = 5, messagesCount = 6)), + unreadCounts.channelsByType, + ) + } +} diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/UnreadDtoAdapterTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/UnreadDtoAdapterTest.kt deleted file mode 100644 index 1babad9a72b..00000000000 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/UnreadDtoAdapterTest.kt +++ /dev/null @@ -1,39 +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.parser2 - -import io.getstream.chat.android.client.api2.model.dto.UnreadDto -import io.getstream.chat.android.client.parser2.testdata.UnreadDtoTestData -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test - -internal class UnreadDtoAdapterTest { - - private val parser = ParserFactory.createMoshiChatParser() - - @Test - fun `deserialize JSON`() { - val dto = parser.fromJson(UnreadDtoTestData.json, UnreadDto::class.java) - assertEquals(UnreadDtoTestData.dto, dto) - } - - @Test - fun `serialize DTO`() { - val json = parser.toJson(UnreadDtoTestData.dto) - assertEquals(UnreadDtoTestData.json, json) - } -} diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/UnreadDtoTestData.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/UnreadDtoTestData.kt deleted file mode 100644 index add6fe38d1c..00000000000 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/UnreadDtoTestData.kt +++ /dev/null @@ -1,127 +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.parser2.testdata - -import io.getstream.chat.android.client.api2.model.dto.UnreadChannelByTypeDto -import io.getstream.chat.android.client.api2.model.dto.UnreadChannelDto -import io.getstream.chat.android.client.api2.model.dto.UnreadDto -import io.getstream.chat.android.client.api2.model.dto.UnreadThreadDto -import org.intellij.lang.annotations.Language -import java.time.ZonedDateTime -import java.util.Date - -internal object UnreadDtoTestData { - - @Language("JSON") - val json = """{ - "total_unread_count": 7, - "total_unread_threads_count": 15, - "total_unread_count_by_team": { - "team1": 3, - "team2": 4 - }, - "channels": [ - { - "channel_id": "channel1", - "unread_count": 4, - "last_read": "$LastReadString" - }, - { - "channel_id": "channel2", - "unread_count": 3, - "last_read": "$LastReadString" - } - ], - "threads": [ - { - "parent_message_id": "message1", - "unread_count": 7, - "last_read": "$LastReadString", - "last_read_message_id": "message1" - }, - { - "parent_message_id": "message2", - "unread_count": 8, - "last_read": "$LastReadString", - "last_read_message_id": "message2" - } - ], - "channel_type": [ - { - "channel_type": "messaging", - "channel_count": 9, - "unread_count": 10 - }, - { - "channel_type": "livestream", - "channel_count": 11, - "unread_count": 12 - } - ] - }""".withoutWhitespace() - - val dto = UnreadDto( - total_unread_count = 7, - total_unread_threads_count = 15, - total_unread_count_by_team = mapOf("team1" to 3, "team2" to 4), - channels = listOf( - UnreadChannelDto( - channel_id = "channel1", - unread_count = 4, - last_read = LastReadDate, - ), - UnreadChannelDto( - channel_id = "channel2", - unread_count = 3, - last_read = LastReadDate, - ), - ), - threads = listOf( - UnreadThreadDto( - parent_message_id = "message1", - unread_count = 7, - last_read = LastReadDate, - last_read_message_id = "message1", - ), - UnreadThreadDto( - parent_message_id = "message2", - unread_count = 8, - last_read = LastReadDate, - last_read_message_id = "message2", - ), - ), - channel_type = listOf( - UnreadChannelByTypeDto( - channel_type = "messaging", - channel_count = 9, - unread_count = 10, - ), - UnreadChannelByTypeDto( - channel_type = "livestream", - channel_count = 11, - unread_count = 12, - ), - ), - ) -} - -private const val LastReadString = "2025-08-15T07:15:00.000Z" - -private val LastReadDate = ZonedDateTime - .parse(LastReadString) - .toInstant() - .let { Date.from(it) }