From 11fddab0313291507b3e74841473e1ca31a0c5f1 Mon Sep 17 00:00:00 2001 From: VelikovPetar Date: Wed, 10 Dec 2025 15:45:55 +0100 Subject: [PATCH 1/2] Add QueryReactions. --- .../api/stream-chat-android-client.api | 2 + .../chat/android/client/ChatClient.kt | 21 +++++++++ .../chat/android/client/api/ChatApi.kt | 10 +++++ .../chat/android/client/api2/MoshiChatApi.kt | 23 ++++++++++ .../client/api2/endpoint/MessageApi.kt | 8 ++++ .../model/requests/QueryReactionsRequest.kt | 35 +++++++++++++++ .../model/response/QueryReactionsResponse.kt | 32 ++++++++++++++ .../client/ChatClientMessageApiTests.kt | 43 +++++++++++++++++++ .../android/client/api2/MoshiChatApiTest.kt | 30 +++++++++++++ .../client/api2/MoshiChatApiTestArguments.kt | 15 +++++++ .../api/stream-chat-android-core.api | 16 ++++++- .../android/models/QueryReactionsResult.kt | 28 ++++++++++++ .../getstream/chat/android/models/Reaction.kt | 10 ++++- 13 files changed, 271 insertions(+), 2 deletions(-) create mode 100644 stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/QueryReactionsRequest.kt create mode 100644 stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/QueryReactionsResponse.kt create mode 100644 stream-chat-android-core/src/main/java/io/getstream/chat/android/models/QueryReactionsResult.kt diff --git a/stream-chat-android-client/api/stream-chat-android-client.api b/stream-chat-android-client/api/stream-chat-android-client.api index d624ceca46f..26eec1551f2 100644 --- a/stream-chat-android-client/api/stream-chat-android-client.api +++ b/stream-chat-android-client/api/stream-chat-android-client.api @@ -169,6 +169,8 @@ public final class io/getstream/chat/android/client/ChatClient { public static synthetic fun queryPollVotes$default (Lio/getstream/chat/android/client/ChatClient;Ljava/lang/String;Lio/getstream/chat/android/models/FilterObject;Ljava/lang/Integer;Ljava/lang/String;Lio/getstream/chat/android/models/querysort/QuerySorter;ILjava/lang/Object;)Lio/getstream/result/call/Call; public final fun queryPolls (Lio/getstream/chat/android/models/FilterObject;Ljava/lang/Integer;Ljava/lang/String;Lio/getstream/chat/android/models/querysort/QuerySorter;)Lio/getstream/result/call/Call; public static synthetic fun queryPolls$default (Lio/getstream/chat/android/client/ChatClient;Lio/getstream/chat/android/models/FilterObject;Ljava/lang/Integer;Ljava/lang/String;Lio/getstream/chat/android/models/querysort/QuerySorter;ILjava/lang/Object;)Lio/getstream/result/call/Call; + public final fun queryReactions (Ljava/lang/String;Lio/getstream/chat/android/models/FilterObject;Ljava/lang/Integer;Ljava/lang/String;Lio/getstream/chat/android/models/querysort/QuerySorter;)Lio/getstream/result/call/Call; + public static synthetic fun queryReactions$default (Lio/getstream/chat/android/client/ChatClient;Ljava/lang/String;Lio/getstream/chat/android/models/FilterObject;Ljava/lang/Integer;Ljava/lang/String;Lio/getstream/chat/android/models/querysort/QuerySorter;ILjava/lang/Object;)Lio/getstream/result/call/Call; public final fun queryReminders (Lio/getstream/chat/android/models/FilterObject;ILjava/lang/String;Lio/getstream/chat/android/models/querysort/QuerySorter;)Lio/getstream/result/call/Call; public static synthetic fun queryReminders$default (Lio/getstream/chat/android/client/ChatClient;Lio/getstream/chat/android/models/FilterObject;ILjava/lang/String;Lio/getstream/chat/android/models/querysort/QuerySorter;ILjava/lang/Object;)Lio/getstream/result/call/Call; public final fun queryThreads (Lio/getstream/chat/android/client/api/models/QueryThreadsRequest;)Lio/getstream/result/call/Call; diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt index c51597c50ee..b744770f919 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt @@ -198,6 +198,7 @@ import io.getstream.chat.android.models.PushPreferenceLevel import io.getstream.chat.android.models.QueryDraftsResult import io.getstream.chat.android.models.QueryPollVotesResult import io.getstream.chat.android.models.QueryPollsResult +import io.getstream.chat.android.models.QueryReactionsResult import io.getstream.chat.android.models.QueryRemindersResult import io.getstream.chat.android.models.QueryThreadsResult import io.getstream.chat.android.models.Reaction @@ -1144,6 +1145,26 @@ internal constructor( return api.getReactions(messageId, offset, limit) } + /** + * Queries reactions for a given message. + * + * @param messageId The ID of the message to which the reactions belong. + * @param filter The filter to apply to the reactions. + * @param limit The maximum number of reactions to retrieve. + * @param next The pagination token for fetching the next set of results. + * @param sort The sorting criteria for the reactions. + */ + @CheckResult + public fun queryReactions( + messageId: String, + filter: FilterObject? = null, + limit: Int? = null, + next: String? = null, + sort: QuerySorter? = null, + ): Call { + return api.queryReactions(messageId, filter, limit, next, sort) + } + /** * Deletes the reaction associated with the message with the given message id. * [cid] parameter is being used in side effect functions executed by plugins. diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/ChatApi.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/ChatApi.kt index a0ad156a655..b06a07d36b6 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/ChatApi.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/ChatApi.kt @@ -53,6 +53,7 @@ import io.getstream.chat.android.models.PushPreferenceLevel import io.getstream.chat.android.models.QueryDraftsResult import io.getstream.chat.android.models.QueryPollVotesResult import io.getstream.chat.android.models.QueryPollsResult +import io.getstream.chat.android.models.QueryReactionsResult import io.getstream.chat.android.models.QueryRemindersResult import io.getstream.chat.android.models.QueryThreadsResult import io.getstream.chat.android.models.Reaction @@ -177,6 +178,15 @@ internal interface ChatApi { limit: Int, ): Call> + @CheckResult + fun queryReactions( + messageId: String, + filter: FilterObject?, + limit: Int?, + next: String?, + sort: QuerySorter?, + ): Call + @CheckResult fun sendReaction(reaction: Reaction, enforceUnique: Boolean, skipPush: Boolean): Call 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 ecfe1175cdf..837ee6f3f02 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 @@ -75,6 +75,7 @@ import io.getstream.chat.android.client.api2.model.requests.QueryDraftMessagesRe import io.getstream.chat.android.client.api2.model.requests.QueryDraftsRequest import io.getstream.chat.android.client.api2.model.requests.QueryPollVotesRequest import io.getstream.chat.android.client.api2.model.requests.QueryPollsRequest +import io.getstream.chat.android.client.api2.model.requests.QueryReactionsRequest import io.getstream.chat.android.client.api2.model.requests.QueryRemindersRequest import io.getstream.chat.android.client.api2.model.requests.ReactionRequest import io.getstream.chat.android.client.api2.model.requests.RejectInviteRequest @@ -141,6 +142,7 @@ import io.getstream.chat.android.models.PushPreferenceLevel import io.getstream.chat.android.models.QueryDraftsResult import io.getstream.chat.android.models.QueryPollVotesResult import io.getstream.chat.android.models.QueryPollsResult +import io.getstream.chat.android.models.QueryReactionsResult import io.getstream.chat.android.models.QueryRemindersResult import io.getstream.chat.android.models.QueryThreadsResult import io.getstream.chat.android.models.Reaction @@ -405,6 +407,27 @@ constructor( } } + override fun queryReactions( + messageId: String, + filter: FilterObject?, + limit: Int?, + next: String?, + sort: QuerySorter?, + ): Call { + val body = QueryReactionsRequest( + filter = filter?.toMap(), + limit = limit, + next = next, + sort = sort?.toDto(), + ) + return messageApi.queryReactions(messageId, body).mapDomain { + QueryReactionsResult( + reactions = it.reactions.map { reaction -> reaction.toDomain() }, + next = it.next, + ) + } + } + override fun sendReaction(reaction: Reaction, enforceUnique: Boolean, skipPush: Boolean): Call { return messageApi.sendReaction( messageId = reaction.messageId, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/MessageApi.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/MessageApi.kt index 089aa6c25ab..67931826c10 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/MessageApi.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/MessageApi.kt @@ -20,6 +20,7 @@ import io.getstream.chat.android.client.api.AuthenticatedApi import io.getstream.chat.android.client.api2.model.requests.PartialUpdateMessageRequest import io.getstream.chat.android.client.api2.model.requests.QueryDraftMessagesRequest import io.getstream.chat.android.client.api2.model.requests.QueryDraftsRequest +import io.getstream.chat.android.client.api2.model.requests.QueryReactionsRequest import io.getstream.chat.android.client.api2.model.requests.ReactionRequest import io.getstream.chat.android.client.api2.model.requests.SendActionRequest import io.getstream.chat.android.client.api2.model.requests.SendMessageRequest @@ -29,6 +30,7 @@ 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.api2.model.response.TranslateMessageRequest @@ -133,6 +135,12 @@ internal interface MessageApi { @Query("limit") limit: Int, ): RetrofitCall + @POST("/messages/{id}/reactions") + fun queryReactions( + @Path("id") messageId: String, + @Body body: QueryReactionsRequest, + ): RetrofitCall + @POST("/messages/{messageId}/translate") fun translate( @Path("messageId") messageId: String, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/QueryReactionsRequest.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/QueryReactionsRequest.kt new file mode 100644 index 00000000000..ddf0dcc8feb --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/QueryReactionsRequest.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2025 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.requests + +import com.squareup.moshi.JsonClass + +/** + * Request for querying reactions on a message. + * + * @property filter The filter criteria. + * @property limit The maximum number of reactions to return. + * @property next The pagination token for fetching the next set of results. + * @property sort The sorting criteria to apply. + */ +@JsonClass(generateAdapter = true) +internal data class QueryReactionsRequest( + val filter: Map<*, *>? = null, + val limit: Int? = null, + val next: String? = null, + val sort: List>? = null, +) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/QueryReactionsResponse.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/QueryReactionsResponse.kt new file mode 100644 index 00000000000..45f52697443 --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/QueryReactionsResponse.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014-2025 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.response + +import com.squareup.moshi.JsonClass +import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionDto + +/** + * 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. + */ +@JsonClass(generateAdapter = true) +internal data class QueryReactionsResponse( + val reactions: List, + val next: String?, +) diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/ChatClientMessageApiTests.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/ChatClientMessageApiTests.kt index f15078ea2b8..f06536fcf24 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/ChatClientMessageApiTests.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/ChatClientMessageApiTests.kt @@ -24,8 +24,10 @@ import io.getstream.chat.android.client.plugin.Plugin import io.getstream.chat.android.client.utils.RetroError import io.getstream.chat.android.client.utils.verifyNetworkError import io.getstream.chat.android.client.utils.verifySuccess +import io.getstream.chat.android.models.Filters import io.getstream.chat.android.models.Message import io.getstream.chat.android.models.PendingMessage +import io.getstream.chat.android.models.QueryReactionsResult import io.getstream.chat.android.models.Reaction import io.getstream.chat.android.models.User import io.getstream.chat.android.models.querysort.QuerySortByField @@ -615,6 +617,43 @@ internal class ChatClientMessageApiTests : BaseChatClientTest() { verifyNetworkError(result, errorCode) } + @Test + fun queryReactionsSuccess() = runTest { + // given + val messageId = randomString() + val filter = Filters.neutral() + val limit = positiveRandomInt() + val next = randomString() + val sort = QuerySortByField() + val reactions = listOf(randomReaction(messageId = messageId)) + val queryResult = QueryReactionsResult(reactions = reactions, next = randomString()) + val sut = Fixture() + .givenQueryReactionsResult(queryResult.asCall()) + .get() + // when + val result = sut.queryReactions(messageId, filter, limit, next, sort).await() + // then + verifySuccess(result, queryResult) + } + + @Test + fun queryReactionsError() = runTest { + // given + val messageId = randomString() + val filter = Filters.neutral() + val limit = positiveRandomInt() + val next = randomString() + val sort = QuerySortByField() + val errorCode = positiveRandomInt() + val sut = Fixture() + .givenQueryReactionsResult(RetroError(errorCode).toRetrofitCall()) + .get() + // when + val result = sut.queryReactions(messageId, filter, limit, next, sort).await() + // then + verifyNetworkError(result, errorCode) + } + @Test fun updateMessageSuccess() = runTest { // given @@ -892,6 +931,10 @@ internal class ChatClientMessageApiTests : BaseChatClientTest() { whenever(api.getReactions(any(), any(), any())).thenReturn(result) } + fun givenQueryReactionsResult(result: Call) = apply { + whenever(api.queryReactions(any(), any(), any(), any(), any())).thenReturn(result) + } + fun givenUpdateMessageResult(result: Call) = apply { whenever(api.updateMessage(any())).thenReturn(result) } 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 9f915827904..5cc4992f94d 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 @@ -66,6 +66,7 @@ import io.getstream.chat.android.client.api2.model.requests.PollVoteRequest import io.getstream.chat.android.client.api2.model.requests.QueryBannedUsersRequest import io.getstream.chat.android.client.api2.model.requests.QueryPollVotesRequest import io.getstream.chat.android.client.api2.model.requests.QueryPollsRequest +import io.getstream.chat.android.client.api2.model.requests.QueryReactionsRequest import io.getstream.chat.android.client.api2.model.requests.QueryRemindersRequest import io.getstream.chat.android.client.api2.model.requests.RejectInviteRequest import io.getstream.chat.android.client.api2.model.requests.ReminderRequest @@ -102,6 +103,7 @@ import io.getstream.chat.android.client.api2.model.response.QueryDraftMessagesRe import io.getstream.chat.android.client.api2.model.response.QueryMembersResponse import io.getstream.chat.android.client.api2.model.response.QueryPollVotesResponse import io.getstream.chat.android.client.api2.model.response.QueryPollsResponse +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 @@ -137,6 +139,7 @@ import io.getstream.chat.android.models.NoOpMessageTransformer import io.getstream.chat.android.models.NoOpUserTransformer import io.getstream.chat.android.models.Poll import io.getstream.chat.android.models.PushPreferenceLevel +import io.getstream.chat.android.models.Reaction import io.getstream.chat.android.models.UnreadCounts import io.getstream.chat.android.models.UploadedFile import io.getstream.chat.android.models.Vote @@ -413,6 +416,33 @@ internal class MoshiChatApiTest { verify(api, times(1)).getReactions(messageId, offset, limit) } + @ParameterizedTest + @MethodSource("io.getstream.chat.android.client.api2.MoshiChatApiTestArguments#queryReactionsInput") + fun testQueryReactions(call: RetrofitCall, expected: KClass<*>) = runTest { + // given + val api = mock() + whenever(api.queryReactions(any(), any())).doReturn(call) + val sut = Fixture() + .withMessageApi(api) + .get() + // when + val messageId = randomString() + val filter = Filters.neutral() + val limit = randomInt() + val next = randomString() + val sort = QuerySortByField() + val result = sut.queryReactions(messageId, filter, limit, next, sort).await() + // then + val expectedRequest = QueryReactionsRequest( + filter = filter.toMap(), + limit = limit, + next = next, + sort = sort.toDto(), + ) + result `should be instance of` expected + verify(api, times(1)).queryReactions(messageId, expectedRequest) + } + @ParameterizedTest @MethodSource("io.getstream.chat.android.client.api2.MoshiChatApiTestArguments#sendReactionInput") fun testSendReaction(call: RetrofitCall, expected: KClass<*>) = runTest { 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 ca77cc0bc78..5a9fdf4b9b4 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 @@ -52,6 +52,7 @@ import io.getstream.chat.android.client.api2.model.response.QueryDraftMessagesRe import io.getstream.chat.android.client.api2.model.response.QueryMembersResponse import io.getstream.chat.android.client.api2.model.response.QueryPollVotesResponse import io.getstream.chat.android.client.api2.model.response.QueryPollsResponse +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 @@ -180,6 +181,20 @@ internal object MoshiChatApiTestArguments { Arguments.of(RetroError(statusCode = 500).toRetrofitCall(), Result.Failure::class), ) + @JvmStatic + fun queryReactionsInput() = listOf( + Arguments.of( + RetroSuccess( + QueryReactionsResponse( + reactions = listOf(Mother.randomDownstreamReactionDto()), + next = randomString(), + ), + ).toRetrofitCall(), + Result.Success::class, + ), + Arguments.of(RetroError(statusCode = 500).toRetrofitCall(), Result.Failure::class), + ) + @JvmStatic fun sendReactionInput() = listOf( Arguments.of( diff --git a/stream-chat-android-core/api/stream-chat-android-core.api b/stream-chat-android-core/api/stream-chat-android-core.api index a3a4e444eaa..69f109fb6dd 100644 --- a/stream-chat-android-core/api/stream-chat-android-core.api +++ b/stream-chat-android-core/api/stream-chat-android-core.api @@ -1924,6 +1924,19 @@ public final class io/getstream/chat/android/models/QueryPollsResult { public fun toString ()Ljava/lang/String; } +public final class io/getstream/chat/android/models/QueryReactionsResult { + public fun (Ljava/util/List;Ljava/lang/String;)V + public final fun component1 ()Ljava/util/List; + public final fun component2 ()Ljava/lang/String; + public final fun copy (Ljava/util/List;Ljava/lang/String;)Lio/getstream/chat/android/models/QueryReactionsResult; + public static synthetic fun copy$default (Lio/getstream/chat/android/models/QueryReactionsResult;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)Lio/getstream/chat/android/models/QueryReactionsResult; + public fun equals (Ljava/lang/Object;)Z + public final fun getNext ()Ljava/lang/String; + public final fun getReactions ()Ljava/util/List; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + public final class io/getstream/chat/android/models/QueryRemindersResult { public fun (Ljava/util/List;Ljava/lang/String;)V public final fun component1 ()Ljava/util/List; @@ -1952,7 +1965,7 @@ public final class io/getstream/chat/android/models/QueryThreadsResult { public fun toString ()Ljava/lang/String; } -public final class io/getstream/chat/android/models/Reaction : io/getstream/chat/android/models/CustomObject { +public final class io/getstream/chat/android/models/Reaction : io/getstream/chat/android/models/CustomObject, io/getstream/chat/android/models/querysort/ComparableFieldProvider { public fun ()V public fun (Ljava/lang/String;Ljava/lang/String;ILio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/util/Date;Ljava/util/Date;Ljava/util/Date;Ljava/util/Date;Lio/getstream/chat/android/models/SyncStatus;Ljava/util/Map;ZZLjava/lang/String;)V public synthetic fun (Ljava/lang/String;Ljava/lang/String;ILio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/util/Date;Ljava/util/Date;Ljava/util/Date;Ljava/util/Date;Lio/getstream/chat/android/models/SyncStatus;Ljava/util/Map;ZZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -1974,6 +1987,7 @@ public final class io/getstream/chat/android/models/Reaction : io/getstream/chat public static synthetic fun copy$default (Lio/getstream/chat/android/models/Reaction;Ljava/lang/String;Ljava/lang/String;ILio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/util/Date;Ljava/util/Date;Ljava/util/Date;Ljava/util/Date;Lio/getstream/chat/android/models/SyncStatus;Ljava/util/Map;ZZLjava/lang/String;ILjava/lang/Object;)Lio/getstream/chat/android/models/Reaction; public fun equals (Ljava/lang/Object;)Z public final fun fetchUserId ()Ljava/lang/String; + public fun getComparableField (Ljava/lang/String;)Ljava/lang/Comparable; public final fun getCreatedAt ()Ljava/util/Date; public final fun getCreatedLocallyAt ()Ljava/util/Date; public final fun getDeletedAt ()Ljava/util/Date; diff --git a/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/QueryReactionsResult.kt b/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/QueryReactionsResult.kt new file mode 100644 index 00000000000..199315b718b --- /dev/null +++ b/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/QueryReactionsResult.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014-2025 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.models + +/** + * Result of querying reactions on a message. + * + * @property reactions The list of reactions. + * @property next TThe pagination token for fetching the next set of results. + */ +public data class QueryReactionsResult( + val reactions: List, + val next: String?, +) diff --git a/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/Reaction.kt b/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/Reaction.kt index 592efc3a0ba..0efe62b4faa 100644 --- a/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/Reaction.kt +++ b/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/Reaction.kt @@ -17,6 +17,7 @@ package io.getstream.chat.android.models import androidx.compose.runtime.Immutable +import io.getstream.chat.android.models.querysort.ComparableFieldProvider import java.util.Date /** @@ -56,7 +57,7 @@ public data class Reaction( val enforceUnique: Boolean = false, val skipPush: Boolean = false, val emojiCode: String? = null, -) : CustomObject { +) : CustomObject, ComparableFieldProvider { /** * The unique identifier of the reaction. @@ -71,6 +72,13 @@ public data class Reaction( return user?.id ?: userId } + override fun getComparableField(fieldName: String): Comparable<*>? { + return when (fieldName) { + "created_at", "createdAt" -> createdAt + else -> extraData[fieldName] as? Comparable<*> + } + } + @SinceKotlin("99999.9") @Suppress("NEWER_VERSION_IN_SINCE_KOTLIN") public fun newBuilder(): Builder = Builder(this) From 7bf1f7aa3af7def2935f9d2355f7831ece33f290 Mon Sep 17 00:00:00 2001 From: VelikovPetar Date: Wed, 10 Dec 2025 15:48:55 +0100 Subject: [PATCH 2/2] Update CHANGELOG.md. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65ba7d52ed6..6a61f68befe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ ### ⬆️ Improved ### ✅ Added +- Add `ChatClient.queryReactions(String, FilterObject?, Int?, String?, QuerySorter?)` operation for querying reactions with filtering, sorting, and pagination support. [#6040](https://github.com/GetStream/stream-chat-android/pull/6040) - Add `ChatClient.markUnread(String, String, Date)` for marking a channel as unread from a given timestamp. [#6027](https://github.com/GetStream/stream-chat-android/pull/6027) - Add `ChatClient.markThreadUnread(String, String, String)` for marking a thread as unread. [#6027](https://github.com/GetStream/stream-chat-android/pull/6027) - Add `ChannelClient.markUnread(Date)` for marking a channel as unread from a given timestamp. [#6027](https://github.com/GetStream/stream-chat-android/pull/6027)