Migrate the query channel request to the generated ChannelGetOrCreate… · GetStream/stream-chat-android@a28b1c1 · GitHub
Skip to content

Commit a28b1c1

Browse files
authored
Migrate the query channel request to the generated ChannelGetOrCreateRequest (#6743)
* Send the query channel request with the generated ChannelGetOrCreateRequest * Keep sending message pagination dates given as strings
1 parent 3faf806 commit a28b1c1

20 files changed

Lines changed: 871 additions & 98 deletions

‎stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/MoshiChatApi.kt‎

Lines changed: 1 addition & 9 deletions

‎stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/ChannelApi.kt‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ import io.getstream.chat.android.client.api.AuthenticatedApi
2020
import io.getstream.chat.android.client.api.QueryParams
2121
import io.getstream.chat.android.client.api2.UrlQueryPayload
2222
import io.getstream.chat.android.client.api2.model.requests.PinnedMessagesRequest
23-
import io.getstream.chat.android.client.api2.model.requests.QueryChannelRequest
2423
import io.getstream.chat.android.client.api2.model.response.ChannelResponse
2524
import io.getstream.chat.android.client.api2.model.response.EventResponse
2625
import io.getstream.chat.android.client.api2.model.response.MessagesResponse
2726
import io.getstream.chat.android.client.api2.model.response.QueryChannelsResponse
2827
import io.getstream.chat.android.client.api2.model.response.QueryGroupedChannelsResponse
2928
import io.getstream.chat.android.client.call.RetrofitCall
29+
import io.getstream.chat.android.network.models.ChannelGetOrCreateRequest
3030
import io.getstream.chat.android.network.models.GroupedQueryChannelsRequest
3131
import io.getstream.chat.android.network.models.HideChannelRequest
3232
import io.getstream.chat.android.network.models.MarkDeliveredRequest
@@ -77,7 +77,7 @@ internal interface ChannelApi {
7777
fun queryChannel(
7878
@Path("type") channelType: String,
7979
@Query(QueryParams.CONNECTION_ID) connectionId: String,
80-
@Body request: QueryChannelRequest,
80+
@Body request: ChannelGetOrCreateRequest,
8181
): RetrofitCall<ChannelResponse>
8282

8383
@POST("/channels/read")
@@ -140,7 +140,7 @@ internal interface ChannelApi {
140140
@Path("type") channelType: String,
141141
@Path("id") channelId: String,
142142
@Query(QueryParams.CONNECTION_ID) connectionId: String,
143-
@Body request: QueryChannelRequest,
143+
@Body request: ChannelGetOrCreateRequest,
144144
): RetrofitCall<ChannelResponse>
145145

146146
@POST("/channels/{type}/{id}/read")

‎stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt‎

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@
1717
package io.getstream.chat.android.client.api2.mapping
1818

1919
import io.getstream.chat.android.PrivacySettings
20+
import io.getstream.chat.android.client.api.models.Pagination
21+
import io.getstream.chat.android.client.api.models.QueryChannelRequest
2022
import io.getstream.chat.android.client.api2.model.dto.DeviceDto
2123
import io.getstream.chat.android.client.api2.model.dto.UpstreamConnectedEventDto
2224
import io.getstream.chat.android.client.api2.model.dto.UpstreamUserDto
2325
import io.getstream.chat.android.client.events.ConnectedEvent
26+
import io.getstream.chat.android.client.parser2.adapters.internal.StreamDateFormatter
2427
import io.getstream.chat.android.models.Attachment
2528
import io.getstream.chat.android.models.ChatPreferences
2629
import io.getstream.chat.android.models.Device
@@ -35,16 +38,21 @@ import io.getstream.chat.android.models.Reaction
3538
import io.getstream.chat.android.models.User
3639
import io.getstream.chat.android.models.UserGroup
3740
import io.getstream.chat.android.models.UserTransformer
41+
import io.getstream.chat.android.network.models.ChannelGetOrCreateRequest
42+
import io.getstream.chat.android.network.models.ChannelInput
3843
import io.getstream.chat.android.network.models.ChannelMemberRequest
3944
import io.getstream.chat.android.network.models.ChatPreferencesInput
4045
import io.getstream.chat.android.network.models.DeliveryReceiptsResponse
46+
import io.getstream.chat.android.network.models.MessagePaginationParams
4147
import io.getstream.chat.android.network.models.MessageRequest
48+
import io.getstream.chat.android.network.models.PaginationParams
4249
import io.getstream.chat.android.network.models.PrivacySettingsResponse
4350
import io.getstream.chat.android.network.models.ReactionRequest
4451
import io.getstream.chat.android.network.models.ReadReceiptsResponse
4552
import io.getstream.chat.android.network.models.SharedLocation
4653
import io.getstream.chat.android.network.models.TypingIndicatorsResponse
4754
import io.getstream.chat.android.network.models.UserRequest
55+
import java.util.Date
4856
import io.getstream.chat.android.network.models.Attachment as AttachmentRequest
4957

5058
@Suppress("TooManyFunctions")
@@ -55,6 +63,8 @@ internal class DtoMapping(
5563

5664
private val supportedUpstreamMessageTypes = setOf(MessageType.REGULAR, MessageType.SYSTEM)
5765

66+
private val dateFormatter = StreamDateFormatter()
67+
5868
/**
5969
* Converts [Device] to [DeviceDto].
6070
*/
@@ -113,8 +123,8 @@ internal class DtoMapping(
113123
* Maps the domain [Member] to the generated network [ChannelMemberRequest] model.
114124
*
115125
* The query endpoint hashes the user ids to resolve a distinct channel and reads nothing else, but the role
116-
* and custom data are carried anyway since the domain member has them. `user` stays absent: the outgoing
117-
* model embeds a read-only [io.getstream.chat.android.network.models.UserResponse].
126+
* and custom data are carried anyway since the domain member has them. `user` stays absent: the member is
127+
* identified by its user id.
118128
*/
119129
internal fun Member.toChannelMemberRequest(): ChannelMemberRequest = ChannelMemberRequest(
120130
userId = getUserId(),
@@ -123,6 +133,57 @@ internal class DtoMapping(
123133
custom = extraData,
124134
)
125135

136+
/**
137+
* Maps the public [QueryChannelRequest] to the generated network [ChannelGetOrCreateRequest] model.
138+
*
139+
* The whole `data` map goes into [ChannelInput.custom], which the adapter flattens back into `data`: the
140+
* backend reads undeclared `data` keys as channel custom data, and matches declared ones first. Pagination
141+
* keys the generated models do not declare are not sent.
142+
*/
143+
internal fun QueryChannelRequest.toChannelGetOrCreateRequest(): ChannelGetOrCreateRequest =
144+
ChannelGetOrCreateRequest(
145+
state = state,
146+
watch = watch,
147+
presence = presence,
148+
// Always present, even when empty: the backend decodes them into pointers.
149+
messages = messages.toMessagePaginationParams(),
150+
members = members.toPaginationParams(),
151+
watchers = watchers.toPaginationParams(),
152+
data = ChannelInput(custom = data),
153+
)
154+
155+
private fun Map<String, Any>.toMessagePaginationParams() = MessagePaginationParams(
156+
limit = int("limit"),
157+
idGt = this[Pagination.GREATER_THAN.toString()] as? String,
158+
idGte = this[Pagination.GREATER_THAN_OR_EQUAL.toString()] as? String,
159+
idLt = this[Pagination.LESS_THAN.toString()] as? String,
160+
idLte = this[Pagination.LESS_THAN_OR_EQUAL.toString()] as? String,
161+
idAround = this[Pagination.AROUND_ID.toString()] as? String,
162+
createdAtAfter = date("created_at_after"),
163+
createdAtAfterOrEqual = date("created_at_after_or_equal"),
164+
createdAtBefore = date("created_at_before"),
165+
createdAtBeforeOrEqual = date("created_at_before_or_equal"),
166+
createdAtAround = date("created_at_around"),
167+
)
168+
169+
private fun Map<String, Any>.toPaginationParams() = PaginationParams(
170+
limit = int("limit"),
171+
offset = int("offset"),
172+
idGt = int("id_gt"),
173+
idGte = int("id_gte"),
174+
idLt = int("id_lt"),
175+
idLte = int("id_lte"),
176+
)
177+
178+
private fun Map<String, Any>.int(key: String): Int? = (this[key] as? Number)?.toInt()
179+
180+
// The maps are public, so a date can arrive as the ISO string the backend also accepts.
181+
private fun Map<String, Any>.date(key: String): Date? = when (val value = this[key]) {
182+
is Date -> value
183+
is String -> dateFormatter.parse(value)
184+
else -> null
185+
}
186+
126187
/**
127188
* Maps the domain [Location] to the generated network [SharedLocation] model.
128189
*/

‎stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/QueryChannelRequest.kt‎

Lines changed: 0 additions & 30 deletions
This file was deleted.

‎stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/optimisation/hash/ChannelQueryKey.kt‎

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,36 +16,38 @@
1616

1717
package io.getstream.chat.android.client.api2.optimisation.hash
1818

19-
import io.getstream.chat.android.client.api2.model.requests.QueryChannelRequest
19+
import io.getstream.chat.android.client.api.models.QueryChannelRequest
2020

2121
/**
2222
* A unique identifier of [QueryChannelRequest] per channel.
2323
*/
2424
internal data class ChannelQueryKey(
2525
val channelType: String,
2626
val channelId: String,
27-
val queryKey: QueryChannelRequest,
27+
val state: Boolean,
28+
val watch: Boolean,
29+
val presence: Boolean,
30+
val messages: Map<String, Any>,
31+
val watchers: Map<String, Any>,
32+
val members: Map<String, Any>,
33+
val data: Map<String, Any>,
2834
) {
2935

3036
companion object {
3137
fun from(
3238
channelType: String,
3339
channelId: String,
34-
query: io.getstream.chat.android.client.api.models.QueryChannelRequest,
35-
): ChannelQueryKey {
36-
return ChannelQueryKey(
37-
channelType = channelType,
38-
channelId = channelId,
39-
queryKey = QueryChannelRequest(
40-
state = query.state,
41-
watch = query.watch,
42-
presence = query.presence,
43-
messages = query.messages,
44-
watchers = query.watchers,
45-
members = query.members,
46-
data = query.data,
47-
),
48-
)
49-
}
40+
query: QueryChannelRequest,
41+
): ChannelQueryKey = ChannelQueryKey(
42+
channelType = channelType,
43+
channelId = channelId,
44+
state = query.state,
45+
watch = query.watch,
46+
presence = query.presence,
47+
messages = query.messages,
48+
watchers = query.watchers,
49+
members = query.members,
50+
data = query.data,
51+
)
5052
}
5153
}

‎stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/MoshiChatParser.kt‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import io.getstream.chat.android.client.events.ChatEvent
3030
import io.getstream.chat.android.client.events.ConnectedEvent
3131
import io.getstream.chat.android.client.extensions.internal.enrichIfNeeded
3232
import io.getstream.chat.android.client.parser.ChatParser
33+
import io.getstream.chat.android.client.parser2.adapters.ChannelInputAdapter
3334
import io.getstream.chat.android.client.parser2.adapters.ChannelInputRequestAdapter
3435
import io.getstream.chat.android.client.parser2.adapters.ChannelMemberPartialResponseAdapter
3536
import io.getstream.chat.android.client.parser2.adapters.ChannelMemberRequestAdapter
@@ -49,6 +50,7 @@ import io.getstream.chat.android.client.parser2.adapters.EventRequestAdapter
4950
import io.getstream.chat.android.client.parser2.adapters.ExactDateAdapter
5051
import io.getstream.chat.android.client.parser2.adapters.FullUserResponseAdapter
5152
import io.getstream.chat.android.client.parser2.adapters.GetOGResponseAdapter
53+
import io.getstream.chat.android.client.parser2.adapters.MemberUserRequestAdapter
5254
import io.getstream.chat.android.client.parser2.adapters.MessageRequestAdapter
5355
import io.getstream.chat.android.client.parser2.adapters.MessageResponseAdapter
5456
import io.getstream.chat.android.client.parser2.adapters.NetworkAttachmentAdapter
@@ -71,6 +73,7 @@ import io.getstream.chat.android.client.socket.ErrorResponse
7173
import io.getstream.chat.android.client.socket.SocketErrorMessage
7274
import io.getstream.chat.android.network.infrastructure.Serializer
7375
import io.getstream.chat.android.network.models.BlockListOptions
76+
import io.getstream.chat.android.network.models.ChannelConfigOverrides
7477
import io.getstream.chat.android.network.models.ChannelConfigWithInfo
7578
import io.getstream.chat.android.network.models.ChannelOwnCapability
7679
import io.getstream.chat.android.network.models.ChatPreferencesInput
@@ -105,11 +108,13 @@ internal class MoshiChatParser(
105108
.add(UserResponseCommonFieldsAdapter)
106109
.add(UserResponsePrivacyFieldsAdapter)
107110
.add(UserRequestAdapter)
111+
.add(MemberUserRequestAdapter)
108112
.add(NetworkAttachmentAdapter)
109113
.add(OwnUserResponseAdapter)
110114
.add(MessageRequestAdapter)
111115
.add(MessageResponseAdapter)
112116
.add(ChannelMemberRequestAdapter)
117+
.add(ChannelInputAdapter)
113118
.add(ChannelInputRequestAdapter)
114119
.add(ChannelResponseAdapter)
115120
.add(ChannelMemberResponseAdapter)
@@ -141,6 +146,14 @@ internal class MoshiChatParser(
141146
MessageRequest.Type::class.java,
142147
MessageRequest.Type.TypeAdapter(),
143148
)
149+
.add(
150+
ChannelConfigOverrides.BlocklistBehavior::class.java,
151+
ChannelConfigOverrides.BlocklistBehavior.BlocklistBehaviorAdapter(),
152+
)
153+
.add(
154+
ChannelConfigOverrides.PushLevel::class.java,
155+
ChannelConfigOverrides.PushLevel.PushLevelAdapter(),
156+
)
144157
.add(
145158
ConfigOverridesRequest.BlocklistBehavior::class.java,
146159
ConfigOverridesRequest.BlocklistBehavior.BlocklistBehaviorAdapter(),
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2014-2026 Stream.io Inc. All rights reserved.
3+
*
4+
* Licensed under the Stream License;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://github.com/GetStream/stream-chat-android/blob/main/LICENSE
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.getstream.chat.android.client.parser2.adapters
18+
19+
import com.squareup.moshi.FromJson
20+
import com.squareup.moshi.JsonAdapter
21+
import com.squareup.moshi.JsonReader
22+
import com.squareup.moshi.JsonWriter
23+
import com.squareup.moshi.ToJson
24+
import io.getstream.chat.android.network.models.ChannelInput
25+
26+
// The generated ChannelInput carries channel custom data in a `custom` field that must be
27+
// flattened to the JSON root on the wire; extraDataPropertyName matches its @Json(name = "custom").
28+
internal object ChannelInputAdapter :
29+
CustomObjectDtoAdapter<ChannelInput>(ChannelInput::class, extraDataPropertyName = "custom") {
30+
31+
@FromJson
32+
@Suppress("UNUSED_PARAMETER")
33+
fun fromJson(jsonReader: JsonReader): ChannelInput = error("Can't parse this from Json")
34+
35+
@ToJson
36+
fun toJson(
37+
jsonWriter: JsonWriter,
38+
request: ChannelInput?,
39+
mapAdapter: JsonAdapter<MutableMap<String, Any?>>,
40+
requestAdapter: JsonAdapter<ChannelInput>,
41+
) = serializeWithExtraData(jsonWriter, request, mapAdapter, requestAdapter)
42+
}
Lines changed: 42 additions & 0 deletions

0 commit comments

Comments
 (0)