From 0108c5a667f2db16f6db1d1f743fae7e8aa0ec6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jc=20Mi=C3=B1arro?= Date: Wed, 8 May 2024 13:22:41 +0200 Subject: [PATCH 1/4] Create new endpoints to get older replies --- .../chat/android/client/api/ChatApi.kt | 7 ++++++ .../client/api/internal/DistinctChatApi.kt | 11 +++++++++ .../api/internal/DistinctChatApiEnabler.kt | 4 ++++ .../chat/android/client/api2/MoshiChatApi.kt | 10 ++++++++ .../client/api2/endpoint/MessageApi.kt | 7 ++++++ .../optimisation/hash/GetNewerRepliesHash.kt | 23 +++++++++++++++++++ 6 files changed, 62 insertions(+) create mode 100644 stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/optimisation/hash/GetNewerRepliesHash.kt 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 c41a99d1b8c..ef6cce80ac0 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 @@ -110,6 +110,13 @@ internal interface ChatApi { @CheckResult fun getReplies(messageId: String, limit: Int): Call> + @CheckResult + fun getNewerReplies( + parentId: String, + limit: Int, + lastId: String?, + ): Call> + @CheckResult fun getReactions( messageId: String, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/internal/DistinctChatApi.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/internal/DistinctChatApi.kt index 198ec11cf17..89542315346 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/internal/DistinctChatApi.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/internal/DistinctChatApi.kt @@ -21,6 +21,7 @@ import io.getstream.chat.android.client.api.models.PinnedMessagesPagination import io.getstream.chat.android.client.api.models.QueryChannelRequest import io.getstream.chat.android.client.api.models.QueryChannelsRequest import io.getstream.chat.android.client.api2.optimisation.hash.ChannelQueryKey +import io.getstream.chat.android.client.api2.optimisation.hash.GetNewerRepliesHash import io.getstream.chat.android.client.api2.optimisation.hash.GetPinnedMessagesHash import io.getstream.chat.android.client.api2.optimisation.hash.GetReactionsHash import io.getstream.chat.android.client.api2.optimisation.hash.GetRepliesHash @@ -78,6 +79,16 @@ internal class DistinctChatApi( } } + override fun getNewerReplies(parentId: String, limit: Int, lastId: String?): Call> { + val uniqueKey = GetNewerRepliesHash(parentId, limit, lastId).hashCode() + StreamLog.d(TAG) { + "[getNewerReplies] parentId: $parentId, limit: $limit, lastId: $lastId, uniqueKey: $uniqueKey" + } + return getOrCreate(uniqueKey) { + delegate.getNewerReplies(parentId, limit, lastId) + } + } + override fun getReactions(messageId: String, offset: Int, limit: Int): Call> { val uniqueKey = GetReactionsHash(messageId, offset, limit).hashCode() StreamLog.d(TAG) { diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/internal/DistinctChatApiEnabler.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/internal/DistinctChatApiEnabler.kt index 6a540a5014a..46bba6a01eb 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/internal/DistinctChatApiEnabler.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/internal/DistinctChatApiEnabler.kt @@ -50,6 +50,10 @@ internal class DistinctChatApiEnabler( return getApi().getReplies(messageId, limit) } + override fun getNewerReplies(parentId: String, limit: Int, lastId: String?): Call> { + return getApi().getNewerReplies(parentId, limit, lastId) + } + override fun getReactions(messageId: String, offset: Int, limit: Int): Call> { return getApi().getReactions(messageId, offset, limit) } 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 0cd090c28e4..75711e77bd7 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 @@ -751,6 +751,16 @@ constructor( } } + override fun getNewerReplies( + parentId: String, + limit: Int, + lastId: String?, + ): Call> = messageApi.getNewerReplies( + parentId = parentId, + limit = limit, + lastId = lastId, + ).map { response -> response.messages.map(DownstreamMessageDto::toDomain) } + override fun getReplies(messageId: String, limit: Int): Call> { return messageApi.getReplies( messageId = 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 978585b5d0c..2c0448733b8 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 @@ -115,6 +115,13 @@ internal interface MessageApi { @Query("limit") limit: Int, ): RetrofitCall + @GET("/messages/{parent_id}/replies?sort=[{\"field\":\"created_at\",\"direction\":1}]") + fun getNewerReplies( + @Path("parent_id") parentId: String, + @Query("limit") limit: Int, + @Query("id_gt") lastId: String?, + ): RetrofitCall + @GET("/messages/{parent_id}/replies") fun getRepliesMore( @Path("parent_id") messageId: String, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/optimisation/hash/GetNewerRepliesHash.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/optimisation/hash/GetNewerRepliesHash.kt new file mode 100644 index 00000000000..23e1099b4fd --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/optimisation/hash/GetNewerRepliesHash.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014-2022 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.optimisation.hash + +internal data class GetNewerRepliesHash( + val parentId: String, + val limit: Int, + val lastId: String?, +) From d364d6bf71f2056eaa0383dbb5aee130d79640b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jc=20Mi=C3=B1arro?= Date: Wed, 8 May 2024 13:28:14 +0200 Subject: [PATCH 2/4] Expose method to get older replies --- .../api/stream-chat-android-client.api | 2 ++ .../chat/android/client/ChatClient.kt | 23 +++++++++++++++++++ .../api/models/identifier/Identifiers.kt | 16 +++++++++++++ 3 files changed, 41 insertions(+) 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 61f7c6f2490..d694a6de34c 100644 --- a/stream-chat-android-client/api/stream-chat-android-client.api +++ b/stream-chat-android-client/api/stream-chat-android-client.api @@ -69,6 +69,8 @@ public final class io/getstream/chat/android/client/ChatClient { public final fun getLogicRegistry ()Lio/getstream/chat/android/client/channel/state/ChannelStateLogicProvider; public final fun getMessage (Ljava/lang/String;)Lio/getstream/result/call/Call; public final fun getMessagesWithAttachments (Ljava/lang/String;Ljava/lang/String;IILjava/util/List;)Lio/getstream/result/call/Call; + public final fun getNewerReplies (Ljava/lang/String;ILjava/lang/String;)Lio/getstream/result/call/Call; + public static synthetic fun getNewerReplies$default (Lio/getstream/chat/android/client/ChatClient;Ljava/lang/String;ILjava/lang/String;ILjava/lang/Object;)Lio/getstream/result/call/Call; public static final fun getOFFLINE_SUPPORT_ENABLED ()Z public final fun getPinnedMessages (Ljava/lang/String;Ljava/lang/String;ILio/getstream/chat/android/models/querysort/QuerySorter;Lio/getstream/chat/android/client/api/models/PinnedMessagesPagination;)Lio/getstream/result/call/Call; public final fun getReactions (Ljava/lang/String;II)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 69d5fef96e2..bdc6383a19c 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 @@ -54,6 +54,7 @@ import io.getstream.chat.android.client.api.models.identifier.SendMessageIdentif import io.getstream.chat.android.client.api.models.identifier.SendReactionIdentifier import io.getstream.chat.android.client.api.models.identifier.ShuffleGiphyIdentifier import io.getstream.chat.android.client.api.models.identifier.UpdateMessageIdentifier +import io.getstream.chat.android.client.api.models.identifier.getNewerRepliesIdentifier import io.getstream.chat.android.client.api2.model.dto.AttachmentDto import io.getstream.chat.android.client.api2.model.dto.DownstreamChannelDto import io.getstream.chat.android.client.api2.model.dto.DownstreamMessageDto @@ -1549,6 +1550,28 @@ internal constructor( .share(userScope) { GetRepliesIdentifier(messageId, limit) } } + /** + * Fetch replies to the specified message with id [parentId] that are newer than the message with [lastId]. + * If [lastId] is null, the oldest replies are returned. + * + * @param parentId The id of the parent message. + * @param limit The number of replies to fetch. + * @param lastId The id of the last message to fetch. + * + * @return Executable async [Call] responsible for fetching newer replies. + */ + @CheckResult + public fun getNewerReplies( + parentId: String, + limit: Int, + lastId: String? = null, + ): Call> { + logger.d { "[getNewerReplies] parentId: $parentId, limit: $limit, lastId: $lastId" } + + return api.getNewerReplies(parentId, limit, lastId) + .share(userScope) { getNewerRepliesIdentifier(parentId, limit, lastId) } + } + @CheckResult public fun getRepliesMore( messageId: String, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/models/identifier/Identifiers.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/models/identifier/Identifiers.kt index 4980c30a661..319ec5009e7 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/models/identifier/Identifiers.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/models/identifier/Identifiers.kt @@ -125,6 +125,22 @@ internal fun GetRepliesIdentifier( return result } +/** + * Identifier for a [ChatClient.getNewerReplies] call. + */ +@Suppress("FunctionName", "MagicNumber") +internal fun getNewerRepliesIdentifier( + parentId: String, + limit: Int, + lastId: String? = null, +): Int { + var result = "GetOlderReplies".hashCode() + result = 31 * result + parentId.hashCode() + result = 31 * result + limit.hashCode() + result = 31 * result + (lastId?.hashCode() ?: 0) + return result +} + /** * Identifier for a [ChatClient.getRepliesMore] call. */ From 9b8c06523f154dbe817b7fce62c912c8bb7aa1ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jc=20Mi=C3=B1arro?= Date: Wed, 8 May 2024 16:12:34 +0200 Subject: [PATCH 3/4] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f83eb008dc2..31b70b22b2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ ### ⬆️ Improved ### ✅ Added +- Added `ChatClient.getNewerReplies` to fetch newer replies for a message in a thread. [#5256](https://github.com/GetStream/stream-chat-android/pull/5256) ### ⚠️ Changed From a6ef58c0a70b0b29ab75de906e26f635f5e64e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jc=20Mi=C3=B1arro?= Date: Tue, 14 May 2024 09:56:08 +0200 Subject: [PATCH 4/4] Update stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt Co-authored-by: Kanat Kiialbaev --- .../main/java/io/getstream/chat/android/client/ChatClient.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 bdc6383a19c..a1947986f99 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 @@ -1556,7 +1556,7 @@ internal constructor( * * @param parentId The id of the parent message. * @param limit The number of replies to fetch. - * @param lastId The id of the last message to fetch. + * @param lastId The id of the last message to fetch from exclusively. * * @return Executable async [Call] responsible for fetching newer replies. */