Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ import io.getstream.chat.android.client.api2.model.response.DraftMessageResponse
import io.getstream.chat.android.client.api2.model.response.MessageResponse
import io.getstream.chat.android.client.api2.model.response.MessagesResponse
import io.getstream.chat.android.client.api2.model.response.QueryDraftMessagesResponse
import io.getstream.chat.android.client.api2.model.response.QueryReactionsResponse
import io.getstream.chat.android.client.api2.model.response.ReactionResponse
import io.getstream.chat.android.client.api2.model.response.ReactionsResponse
import io.getstream.chat.android.client.call.RetrofitCall
import io.getstream.chat.android.network.models.GetReactionsResponse
import io.getstream.chat.android.network.models.MessageActionRequest
import io.getstream.chat.android.network.models.QueryDraftsRequest
import io.getstream.chat.android.network.models.QueryReactionsRequest
import io.getstream.chat.android.network.models.QueryReactionsResponse
import io.getstream.chat.android.network.models.Response
import io.getstream.chat.android.network.models.SendReactionRequest
import io.getstream.chat.android.network.models.TranslateMessageRequest
Expand Down Expand Up @@ -133,7 +133,7 @@ internal interface MessageApi {
@Path("id") messageId: String,
@Query("offset") offset: Int,
@Query("limit") limit: Int,
): RetrofitCall<ReactionsResponse>
): RetrofitCall<GetReactionsResponse>

@POST("/messages/{id}/reactions")
fun queryReactions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ import io.getstream.chat.android.network.models.PollVotesResponse
import io.getstream.chat.android.network.models.PrivacySettingsResponse
import io.getstream.chat.android.network.models.PushPreferencesResponse
import io.getstream.chat.android.network.models.QueryPollsResponse
import io.getstream.chat.android.network.models.ReactionResponse
import io.getstream.chat.android.network.models.UnreadCountsChannel
import io.getstream.chat.android.network.models.UnreadCountsChannelType
import io.getstream.chat.android.network.models.UnreadCountsThread
Expand All @@ -160,6 +161,9 @@ import io.getstream.chat.android.network.models.Role as RoleDto
import io.getstream.chat.android.network.models.ThreadParticipant as ThreadParticipantDto
import io.getstream.chat.android.network.models.UserGroupMember as UserGroupMemberDto

/** `emoji_code` is sent as custom data rather than a declared field, in both directions. */
internal const val EMOJI_CODE_KEY = "emoji_code"

@Suppress("TooManyFunctions", "LargeClass")
internal class DomainMapping(
val currentUserIdProvider: () -> UserId?,
Expand Down Expand Up @@ -490,6 +494,27 @@ internal class DomainMapping(
expires = expires,
)

/**
* Transforms [ReactionResponse] into [Reaction].
*
* `emoji_code` is custom data on the backend rather than a declared field, so it arrives inside
* [ReactionResponse.custom] and is promoted here, staying out of [Reaction.extraData].
*/
internal fun ReactionResponse.toDomain(): Reaction = Reaction(
createdAt = createdAt,
messageId = messageId,
score = score,
type = type,
updatedAt = updatedAt,
user = user.toDomain(),
userId = userId,
emojiCode = custom[EMOJI_CODE_KEY] as? String,
extraData = custom
.filterKeys { it != EMOJI_CODE_KEY }
.mapNotNull { (key, value) -> value?.let { key to it } }
.toMap(),
)

/**
* Transforms [DownstreamReactionDto] to [Reaction].
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ internal class DtoMapping(
createdAt = createdAt,
score = score,
updatedAt = updatedAt,
custom = if (emojiCode != null) extraData + ("emoji_code" to emojiCode) else extraData,
custom = if (emojiCode != null) extraData + (EMOJI_CODE_KEY to emojiCode) else extraData,
)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import io.getstream.chat.android.client.parser2.adapters.PollOptionInputAdapter
import io.getstream.chat.android.client.parser2.adapters.PollOptionRequestAdapter
import io.getstream.chat.android.client.parser2.adapters.PollOptionResponseDataAdapter
import io.getstream.chat.android.client.parser2.adapters.PollResponseDataAdapter
import io.getstream.chat.android.client.parser2.adapters.ReactionResponseAdapter
import io.getstream.chat.android.client.parser2.adapters.UpdatePollOptionRequestAdapter
import io.getstream.chat.android.client.parser2.adapters.UpdatePollRequestAdapter
import io.getstream.chat.android.client.parser2.adapters.UpstreamMemberDataDtoAdapter
Expand Down Expand Up @@ -131,6 +132,7 @@ internal class MoshiChatParser(
.add(GetOGResponseAdapter)
.add(PollOptionResponseDataAdapter)
.add(PollResponseDataAdapter)
.add(ReactionResponseAdapter)
.add(
CreatePollRequest.VotingVisibility::class.java,
CreatePollRequest.VotingVisibility.VotingVisibilityAdapter(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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.adapters

import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.ToJson
import io.getstream.chat.android.network.models.ReactionResponse

/**
* Collects the root-level custom fields of a reaction into `custom`, which is how the API sends
* them.
*/
internal object ReactionResponseAdapter :
CustomObjectDtoAdapter<ReactionResponse>(
ReactionResponse::class,
extraDataPropertyName = "custom",
) {

@FromJson
fun fromJson(
jsonReader: JsonReader,
mapAdapter: JsonAdapter<MutableMap<String, Any>>,
valueAdapter: JsonAdapter<ReactionResponse>,
): ReactionResponse? = parseWithExtraData(jsonReader, mapAdapter, valueAdapter)

@ToJson
@Suppress("UNUSED_PARAMETER")
fun toJson(jsonWriter: JsonWriter, value: ReactionResponse): Unit =
error("Can't convert this to Json")
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,25 @@
* limitations under the License.
*/

package io.getstream.chat.android.client.api2.model.response
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport",
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

package io.getstream.chat.android.network.models

import com.squareup.moshi.Json

import com.squareup.moshi.JsonClass
import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionDto
/**
*
*/
@com.squareup.moshi.JsonClass(generateAdapter = true)
internal data class GetReactionsResponse(
@Json(name = "duration")
internal val duration: String,

@JsonClass(generateAdapter = true)
internal data class ReactionsResponse(
val reactions: List<DownstreamReactionDto>,
@Json(name = "reactions")
internal val reactions: List<ReactionResponse> = emptyList(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,31 @@
* limitations under the License.
*/

package io.getstream.chat.android.client.api2.model.response
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport",
)

package io.getstream.chat.android.network.models

import com.squareup.moshi.JsonClass
import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionDto
import com.squareup.moshi.Json

/**
* Response for querying reactions on a message.
*
* @property reactions The list of reactions returned by the query.
* @property next The identifier for the next page of reactions.
* Basic response information
*/
@JsonClass(generateAdapter = true)
@com.squareup.moshi.JsonClass(generateAdapter = true)
internal data class QueryReactionsResponse(
val reactions: List<DownstreamReactionDto>,
val next: String?,
@Json(name = "duration")
internal val duration: String,

@Json(name = "reactions")
internal val reactions: List<ReactionResponse> = emptyList(),

@Json(name = "next")
internal val next: String? = null,

@Json(name = "prev")
internal val prev: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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 ReactionResponse(
@Json(name = "created_at")
internal val createdAt: java.util.Date,

@Json(name = "message_id")
internal val messageId: String,

@Json(name = "score")
internal val score: Int,

@Json(name = "type")
internal val type: String,

@Json(name = "updated_at")
internal val updatedAt: java.util.Date,

@Json(name = "user_id")
internal val userId: String,

@Json(name = "custom")
internal val custom: Map<String, Any?> = emptyMap(),

@Json(name = "user")
internal val user: UserResponse,
)
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ import io.getstream.chat.android.network.models.PollResponseData
import io.getstream.chat.android.network.models.PollVoteResponseData
import io.getstream.chat.android.network.models.PollVotesResponse
import io.getstream.chat.android.network.models.QueryPollsResponse
import io.getstream.chat.android.network.models.ReactionResponse
import io.getstream.chat.android.network.models.ThreadParticipant
import io.getstream.chat.android.network.models.UnblockUsersResponse
import io.getstream.chat.android.network.models.UnreadCountsChannel
Expand Down Expand Up @@ -1386,6 +1387,22 @@ internal object Mother {
next = next,
)

fun randomReactionResponse(
messageId: String = randomString(),
type: String = randomString(),
userId: String = randomString(),
custom: Map<String, Any?> = emptyMap(),
): ReactionResponse = ReactionResponse(
messageId = messageId,
type = type,
score = randomInt(),
createdAt = randomDate(),
updatedAt = randomDate(),
userId = userId,
user = randomUserResponse(id = userId),
custom = custom,
)

fun randomPollResponseData(
id: String = randomString(),
name: String = randomString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,9 @@ import io.getstream.chat.android.client.api2.model.response.QueryChannelsRespons
import io.getstream.chat.android.client.api2.model.response.QueryDraftMessagesResponse
import io.getstream.chat.android.client.api2.model.response.QueryGroupedChannelsGroup
import io.getstream.chat.android.client.api2.model.response.QueryGroupedChannelsResponse
import io.getstream.chat.android.client.api2.model.response.QueryReactionsResponse
import io.getstream.chat.android.client.api2.model.response.QueryRemindersResponse
import io.getstream.chat.android.client.api2.model.response.QueryThreadsResponse
import io.getstream.chat.android.client.api2.model.response.ReactionResponse
import io.getstream.chat.android.client.api2.model.response.ReactionsResponse
import io.getstream.chat.android.client.api2.model.response.ReminderResponse
import io.getstream.chat.android.client.api2.model.response.SearchMessagesResponse
import io.getstream.chat.android.client.api2.model.response.SyncHistoryResponse
Expand Down Expand Up @@ -128,6 +126,7 @@ import io.getstream.chat.android.network.models.EventRequest
import io.getstream.chat.android.network.models.GetApplicationResponse
import io.getstream.chat.android.network.models.GetBlockedUsersResponse
import io.getstream.chat.android.network.models.GetOGResponse
import io.getstream.chat.android.network.models.GetReactionsResponse
import io.getstream.chat.android.network.models.GetUserGroupResponse
import io.getstream.chat.android.network.models.GroupedChannelsGroupRequest
import io.getstream.chat.android.network.models.GroupedQueryChannelsRequest
Expand Down Expand Up @@ -156,6 +155,7 @@ import io.getstream.chat.android.network.models.QueryPollVotesRequest
import io.getstream.chat.android.network.models.QueryPollsRequest
import io.getstream.chat.android.network.models.QueryPollsResponse
import io.getstream.chat.android.network.models.QueryReactionsRequest
import io.getstream.chat.android.network.models.QueryReactionsResponse
import io.getstream.chat.android.network.models.QueryRemindersRequest
import io.getstream.chat.android.network.models.QueryUsersResponse
import io.getstream.chat.android.network.models.RemoveUserGroupMembersRequest
Expand Down Expand Up @@ -455,7 +455,7 @@ internal class MoshiChatApiTest {

@ParameterizedTest
@MethodSource("io.getstream.chat.android.client.api2.MoshiChatApiTestArguments#getReactionsInput")
fun testGetReactions(call: RetrofitCall<ReactionsResponse>, expected: KClass<*>) = runTest {
fun testGetReactions(call: RetrofitCall<GetReactionsResponse>, expected: KClass<*>) = runTest {
// given
val api = mock<MessageApi>()
whenever(api.getReactions(any(), any(), any())).doReturn(call)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@ import io.getstream.chat.android.client.api2.model.response.QueryChannelsRespons
import io.getstream.chat.android.client.api2.model.response.QueryDraftMessagesResponse
import io.getstream.chat.android.client.api2.model.response.QueryGroupedChannelsGroup
import io.getstream.chat.android.client.api2.model.response.QueryGroupedChannelsResponse
import io.getstream.chat.android.client.api2.model.response.QueryReactionsResponse
import io.getstream.chat.android.client.api2.model.response.QueryThreadsResponse
import io.getstream.chat.android.client.api2.model.response.ReactionResponse
import io.getstream.chat.android.client.api2.model.response.ReactionsResponse
import io.getstream.chat.android.client.api2.model.response.ReminderResponse
import io.getstream.chat.android.client.api2.model.response.SearchMessagesResponse
import io.getstream.chat.android.client.api2.model.response.SyncHistoryResponse
Expand All @@ -65,6 +63,7 @@ import io.getstream.chat.android.network.models.CreateUserGroupResponse
import io.getstream.chat.android.network.models.GetApplicationResponse
import io.getstream.chat.android.network.models.GetBlockedUsersResponse
import io.getstream.chat.android.network.models.GetOGResponse
import io.getstream.chat.android.network.models.GetReactionsResponse
import io.getstream.chat.android.network.models.GetUserGroupResponse
import io.getstream.chat.android.network.models.ListDevicesResponse
import io.getstream.chat.android.network.models.ListUserGroupsResponse
Expand All @@ -75,6 +74,7 @@ import io.getstream.chat.android.network.models.PollVoteResponse
import io.getstream.chat.android.network.models.PollVotesResponse
import io.getstream.chat.android.network.models.QueryBannedUsersResponse
import io.getstream.chat.android.network.models.QueryPollsResponse
import io.getstream.chat.android.network.models.QueryReactionsResponse
import io.getstream.chat.android.network.models.QueryUsersResponse
import io.getstream.chat.android.network.models.RemoveUserGroupMembersResponse
import io.getstream.chat.android.network.models.Response
Expand Down Expand Up @@ -189,18 +189,24 @@ internal object MoshiChatApiTestArguments {
@JvmStatic
fun getReactionsInput() = listOf(
Arguments.of(
RetroSuccess(ReactionsResponse(listOf(Mother.randomDownstreamReactionDto()))).toRetrofitCall(),
RetroSuccess(
GetReactionsResponse(
duration = randomString(),
reactions = listOf(Mother.randomReactionResponse()),
),
).toRetrofitCall(),
Result.Success::class,
),
Arguments.of(RetroError<ReactionsResponse>(statusCode = 500).toRetrofitCall(), Result.Failure::class),
Arguments.of(RetroError<GetReactionsResponse>(statusCode = 500).toRetrofitCall(), Result.Failure::class),
)

@JvmStatic
fun queryReactionsInput() = listOf(
Arguments.of(
RetroSuccess(
QueryReactionsResponse(
reactions = listOf(Mother.randomDownstreamReactionDto()),
duration = randomString(),
reactions = listOf(Mother.randomReactionResponse()),
next = randomString(),
),
).toRetrofitCall(),
Expand Down
Loading
Loading