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 fe7ade61f74..3b2a127a395 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 @@ -47,7 +47,6 @@ import io.getstream.chat.android.client.api2.mapping.DomainMapping import io.getstream.chat.android.client.api2.mapping.DtoMapping import io.getstream.chat.android.client.api2.mapping.EventMapping import io.getstream.chat.android.client.api2.mapping.toFilterDomainWithFields -import io.getstream.chat.android.client.api2.model.dto.UpstreamPushPreferenceInputDto import io.getstream.chat.android.client.api2.model.requests.BanUserRequest import io.getstream.chat.android.client.api2.model.requests.FlagMessageRequest import io.getstream.chat.android.client.api2.model.requests.FlagRequest @@ -60,7 +59,6 @@ import io.getstream.chat.android.client.api2.model.requests.SendMessageRequest import io.getstream.chat.android.client.api2.model.requests.SyncHistoryRequest import io.getstream.chat.android.client.api2.model.requests.TruncateChannelRequest import io.getstream.chat.android.client.api2.model.requests.UpdateMessageRequest -import io.getstream.chat.android.client.api2.model.requests.UpsertPushPreferencesRequest import io.getstream.chat.android.client.api2.model.response.ChannelResponse import io.getstream.chat.android.client.call.RetrofitCall import io.getstream.chat.android.client.events.ChatEvent @@ -145,7 +143,9 @@ import io.getstream.chat.android.network.models.MessageRequest import io.getstream.chat.android.network.models.MuteChannelRequest import io.getstream.chat.android.network.models.PollOptionInput import io.getstream.chat.android.network.models.PollOptionRequest +import io.getstream.chat.android.network.models.PushPreferenceInput import io.getstream.chat.android.network.models.QueryDraftsRequest +import io.getstream.chat.android.network.models.QueryMembersPayload import io.getstream.chat.android.network.models.QueryPollVotesRequest import io.getstream.chat.android.network.models.QueryPollsRequest import io.getstream.chat.android.network.models.QueryReactionsRequest @@ -172,6 +172,7 @@ import io.getstream.chat.android.network.models.UpdateUserGroupResponse import io.getstream.chat.android.network.models.UpdateUserPartialRequest import io.getstream.chat.android.network.models.UpdateUsersPartialRequest import io.getstream.chat.android.network.models.UpdateUsersRequest +import io.getstream.chat.android.network.models.UpsertPushPreferencesRequest import io.getstream.chat.android.network.models.UpsertPushPreferencesResponse import io.getstream.chat.android.network.models.UserGroupResponse import io.getstream.chat.android.network.models.UserRequest @@ -495,11 +496,11 @@ constructor( } override fun setUserPushPreference(level: PushPreferenceLevel): Call { - val input = UpstreamPushPreferenceInputDto( - channel_cid = null, - chat_level = level.value, - disabled_until = null, - remove_disable = true, + val input = PushPreferenceInput( + channelCid = null, + chatLevel = PushPreferenceInput.ChatLevel.fromString(level.value), + disabledUntil = null, + removeDisable = true, ) val request = UpsertPushPreferencesRequest(listOf(input)) return pushPreferencesApi @@ -508,11 +509,11 @@ constructor( } override fun snoozeUserPushNotifications(until: Date): Call { - val input = UpstreamPushPreferenceInputDto( - channel_cid = null, - chat_level = null, - disabled_until = until, - remove_disable = null, + val input = PushPreferenceInput( + channelCid = null, + chatLevel = null, + disabledUntil = until, + removeDisable = null, ) val request = UpsertPushPreferencesRequest(listOf(input)) return pushPreferencesApi @@ -521,11 +522,11 @@ constructor( } override fun setChannelPushPreference(cid: String, level: PushPreferenceLevel): Call { - val input = UpstreamPushPreferenceInputDto( - channel_cid = cid, - chat_level = level.value, - disabled_until = null, - remove_disable = true, + val input = PushPreferenceInput( + channelCid = cid, + chatLevel = PushPreferenceInput.ChatLevel.fromString(level.value), + disabledUntil = null, + removeDisable = true, ) val request = UpsertPushPreferencesRequest(listOf(input)) return pushPreferencesApi @@ -534,11 +535,11 @@ constructor( } override fun snoozeChannelPushNotifications(cid: String, until: Date): Call { - val input = UpstreamPushPreferenceInputDto( - channel_cid = cid, - chat_level = null, - disabled_until = until, - remove_disable = null, + val input = PushPreferenceInput( + channelCid = cid, + chatLevel = null, + disabledUntil = until, + removeDisable = null, ) val request = UpsertPushPreferencesRequest(listOf(input)) return pushPreferencesApi @@ -547,12 +548,12 @@ constructor( } override fun setUserChatPreferences(preferences: ChatPreferences): Call { - val input = UpstreamPushPreferenceInputDto( - channel_cid = null, - chat_level = null, - disabled_until = null, - remove_disable = null, - chat_preferences = with(dtoMapping) { preferences.toDto() }, + val input = PushPreferenceInput( + channelCid = null, + chatLevel = null, + disabledUntil = null, + removeDisable = null, + chatPreferences = with(dtoMapping) { preferences.toChatPreferencesInput() }, ) return pushPreferencesApi .upsertPushPreferences(UpsertPushPreferencesRequest(listOf(input))) @@ -560,12 +561,12 @@ constructor( } override fun setChannelChatPreferences(cid: String, preferences: ChatPreferences): Call { - val input = UpstreamPushPreferenceInputDto( - channel_cid = cid, - chat_level = null, - disabled_until = null, - remove_disable = null, - chat_preferences = with(dtoMapping) { preferences.toDto() }, + val input = PushPreferenceInput( + channelCid = cid, + chatLevel = null, + disabledUntil = null, + removeDisable = null, + chatPreferences = with(dtoMapping) { preferences.toChatPreferencesInput() }, ) return pushPreferencesApi .upsertPushPreferences(UpsertPushPreferencesRequest(listOf(input))) @@ -1645,14 +1646,14 @@ constructor( members: List, ): Call> { val request = with(dtoMapping) { - io.getstream.chat.android.client.api2.model.requests.QueryMembersRequest( + QueryMembersPayload( type = channelType, id = channelId, - filter_conditions = filter.toMap(), + filterConditions = filter.toMap(), offset = offset, limit = limit, - sort = sort.toDto(), - members = members.map { it.toDto() }, + sort = sort.toSortParams(), + members = members.map { it.toChannelMemberRequest() }, ) } 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 63c3852dea3..925034af286 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,12 +19,12 @@ 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.requests.QueryMembersRequest import io.getstream.chat.android.client.api2.model.requests.SyncHistoryRequest import io.getstream.chat.android.client.api2.model.response.SearchMessagesResponse 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.MembersResponse +import io.getstream.chat.android.network.models.QueryMembersPayload import io.getstream.chat.android.network.models.SearchPayload import io.getstream.chat.android.network.models.WrappedUnreadCountsResponse import okhttp3.ResponseBody @@ -52,7 +52,7 @@ internal interface GeneralApi { @GET("/members") fun queryMembers( - @UrlQueryPayload @Query("payload") payload: QueryMembersRequest, + @UrlQueryPayload @Query("payload") payload: QueryMembersPayload, ): RetrofitCall @GET("/unread") diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/PushPreferencesApi.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/PushPreferencesApi.kt index c9ad96f39b0..ae52a6c462e 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/PushPreferencesApi.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/PushPreferencesApi.kt @@ -17,8 +17,8 @@ package io.getstream.chat.android.client.api2.endpoint import io.getstream.chat.android.client.api.AuthenticatedApi -import io.getstream.chat.android.client.api2.model.requests.UpsertPushPreferencesRequest import io.getstream.chat.android.client.call.RetrofitCall +import io.getstream.chat.android.network.models.UpsertPushPreferencesRequest import io.getstream.chat.android.network.models.UpsertPushPreferencesResponse import retrofit2.http.Body import retrofit2.http.POST diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt index 177657064bf..47e28440634 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt @@ -26,7 +26,6 @@ import io.getstream.chat.android.client.api2.model.dto.DeviceDto 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.TypingIndicatorsDto -import io.getstream.chat.android.client.api2.model.dto.UpstreamChatPreferencesDto import io.getstream.chat.android.client.api2.model.dto.UpstreamConnectedEventDto import io.getstream.chat.android.client.api2.model.dto.UpstreamLocationDto import io.getstream.chat.android.client.api2.model.dto.UpstreamMemberDataDto @@ -51,6 +50,7 @@ import io.getstream.chat.android.models.User import io.getstream.chat.android.models.UserGroup import io.getstream.chat.android.models.UserTransformer import io.getstream.chat.android.network.models.ChannelMemberRequest +import io.getstream.chat.android.network.models.ChatPreferencesInput import io.getstream.chat.android.network.models.DeliveryReceiptsResponse import io.getstream.chat.android.network.models.MessageRequest import io.getstream.chat.android.network.models.PrivacySettingsResponse @@ -216,6 +216,20 @@ internal class DtoMapping( custom = extraData, ) + /** + * Maps the domain [Member] to the generated network [ChannelMemberRequest] model. + * + * The query endpoint hashes the user ids to resolve a distinct channel and reads nothing else, but the role + * and custom data are carried anyway since the domain member has them. `user` stays absent: the outgoing + * model embeds a read-only [io.getstream.chat.android.network.models.UserResponse]. + */ + internal fun Member.toChannelMemberRequest(): ChannelMemberRequest = ChannelMemberRequest( + userId = getUserId(), + channelRole = channelRole, + user = null, + custom = extraData, + ) + /** * Maps the domain [Location] to the generated network [SharedLocation] model. */ @@ -394,13 +408,13 @@ internal class DtoMapping( connection_id = connectionId, ) - internal fun ChatPreferences.toDto(): UpstreamChatPreferencesDto = UpstreamChatPreferencesDto( - direct_mentions = directMentions?.value, - role_mentions = roleMentions?.value, - group_mentions = groupMentions?.value, - here_mentions = hereMentions?.value, - channel_mentions = channelMentions?.value, - thread_replies = threadReplies?.value, - default_preference = defaultPreference?.value, + internal fun ChatPreferences.toChatPreferencesInput(): ChatPreferencesInput = ChatPreferencesInput( + directMentions = directMentions?.value?.let(ChatPreferencesInput.DirectMentions::fromString), + roleMentions = roleMentions?.value?.let(ChatPreferencesInput.RoleMentions::fromString), + groupMentions = groupMentions?.value?.let(ChatPreferencesInput.GroupMentions::fromString), + hereMentions = hereMentions?.value?.let(ChatPreferencesInput.HereMentions::fromString), + channelMentions = channelMentions?.value?.let(ChatPreferencesInput.ChannelMentions::fromString), + threadReplies = threadReplies?.value?.let(ChatPreferencesInput.ThreadReplies::fromString), + defaultPreference = defaultPreference?.value?.let(ChatPreferencesInput.DefaultPreference::fromString), ) } diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PushPreferenceDtos.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PushPreferenceDtos.kt index 94d855855a9..3714ecc4843 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PushPreferenceDtos.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PushPreferenceDtos.kt @@ -19,24 +19,6 @@ package io.getstream.chat.android.client.api2.model.dto import com.squareup.moshi.JsonClass import java.util.Date -/** - * Upstream DTO for setting push notification preferences. - * - * @param channel_cid The channel ID (e.g., "messaging:123"). - * @param chat_level The chat level preference ("all", "default", "mentions" or "none"). - * @param disabled_until Timestamp until which notifications are disabled. - * @param remove_disable Whether to remove any existing disable setting. - * @param chat_preferences Per-category toggles. Setting this clears [chat_level] server-side. - */ -@JsonClass(generateAdapter = true) -internal data class UpstreamPushPreferenceInputDto( - val channel_cid: String?, - val chat_level: String?, - val disabled_until: Date?, - val remove_disable: Boolean?, - val chat_preferences: UpstreamChatPreferencesDto? = null, -) - /** * Downstream DTO for receiving push notification preferences. * @@ -51,17 +33,6 @@ internal data class DownstreamPushPreferenceDto( val chat_preferences: DownstreamChatPreferencesDto? = null, ) -@JsonClass(generateAdapter = true) -internal data class UpstreamChatPreferencesDto( - val direct_mentions: String? = null, - val role_mentions: String? = null, - val group_mentions: String? = null, - val here_mentions: String? = null, - val channel_mentions: String? = null, - val thread_replies: String? = null, - val default_preference: String? = null, -) - @JsonClass(generateAdapter = true) internal data class DownstreamChatPreferencesDto( val direct_mentions: String? = null, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/QueryMembersRequest.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/QueryMembersRequest.kt deleted file mode 100644 index f6a533ebbce..00000000000 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/QueryMembersRequest.kt +++ /dev/null @@ -1,31 +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.requests - -import com.squareup.moshi.JsonClass -import io.getstream.chat.android.client.api2.model.dto.UpstreamMemberDto - -@JsonClass(generateAdapter = true) -internal data class QueryMembersRequest( - val type: String, - val id: String, - val filter_conditions: Map<*, *>, - val offset: Int, - val limit: Int, - val sort: List>, - val members: List, -) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/MoshiChatParser.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/MoshiChatParser.kt index 6bb80a02de2..03823020f40 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/MoshiChatParser.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/MoshiChatParser.kt @@ -72,9 +72,12 @@ import io.getstream.chat.android.network.infrastructure.Serializer import io.getstream.chat.android.network.models.BlockListOptions import io.getstream.chat.android.network.models.ChannelConfigWithInfo import io.getstream.chat.android.network.models.ChannelOwnCapability +import io.getstream.chat.android.network.models.ChatPreferencesInput import io.getstream.chat.android.network.models.ConfigOverridesRequest import io.getstream.chat.android.network.models.CreatePollRequest +import io.getstream.chat.android.network.models.FeedsPreferences import io.getstream.chat.android.network.models.MessageRequest +import io.getstream.chat.android.network.models.PushPreferenceInput import io.getstream.chat.android.network.models.TranslateMessageRequest import io.getstream.chat.android.network.models.UpdatePollRequest import retrofit2.Retrofit @@ -172,6 +175,74 @@ internal class MoshiChatParser( BlockListOptions.Behavior::class.java, BlockListOptions.Behavior.BehaviorAdapter(), ) + .add( + PushPreferenceInput.CallLevel::class.java, + PushPreferenceInput.CallLevel.CallLevelAdapter(), + ) + .add( + PushPreferenceInput.ChatLevel::class.java, + PushPreferenceInput.ChatLevel.ChatLevelAdapter(), + ) + .add( + PushPreferenceInput.FeedsLevel::class.java, + PushPreferenceInput.FeedsLevel.FeedsLevelAdapter(), + ) + .add( + ChatPreferencesInput.ChannelMentions::class.java, + ChatPreferencesInput.ChannelMentions.ChannelMentionsAdapter(), + ) + .add( + ChatPreferencesInput.DefaultPreference::class.java, + ChatPreferencesInput.DefaultPreference.DefaultPreferenceAdapter(), + ) + .add( + ChatPreferencesInput.DirectMentions::class.java, + ChatPreferencesInput.DirectMentions.DirectMentionsAdapter(), + ) + .add( + ChatPreferencesInput.GroupMentions::class.java, + ChatPreferencesInput.GroupMentions.GroupMentionsAdapter(), + ) + .add( + ChatPreferencesInput.HereMentions::class.java, + ChatPreferencesInput.HereMentions.HereMentionsAdapter(), + ) + .add( + ChatPreferencesInput.RoleMentions::class.java, + ChatPreferencesInput.RoleMentions.RoleMentionsAdapter(), + ) + .add( + ChatPreferencesInput.ThreadReplies::class.java, + ChatPreferencesInput.ThreadReplies.ThreadRepliesAdapter(), + ) + .add( + FeedsPreferences.Comment::class.java, + FeedsPreferences.Comment.CommentAdapter(), + ) + .add( + FeedsPreferences.CommentMention::class.java, + FeedsPreferences.CommentMention.CommentMentionAdapter(), + ) + .add( + FeedsPreferences.CommentReaction::class.java, + FeedsPreferences.CommentReaction.CommentReactionAdapter(), + ) + .add( + FeedsPreferences.CommentReply::class.java, + FeedsPreferences.CommentReply.CommentReplyAdapter(), + ) + .add( + FeedsPreferences.Follow::class.java, + FeedsPreferences.Follow.FollowAdapter(), + ) + .add( + FeedsPreferences.Mention::class.java, + FeedsPreferences.Mention.MentionAdapter(), + ) + .add( + FeedsPreferences.Reaction::class.java, + FeedsPreferences.Reaction.ReactionAdapter(), + ) // Registered last so the model-specific adapters above keep precedence and delegate into it. .add(NullCollectionsAsEmptyFactory) .build() diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/ChatPreferencesInput.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/ChatPreferencesInput.kt new file mode 100644 index 00000000000..adbcc9829c7 --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/ChatPreferencesInput.kt @@ -0,0 +1,276 @@ +/* + * 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.FromJson +import com.squareup.moshi.Json +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.JsonReader +import com.squareup.moshi.JsonWriter +import com.squareup.moshi.ToJson + +/** + * + */ +@com.squareup.moshi.JsonClass(generateAdapter = true) +internal data class ChatPreferencesInput( + @Json(name = "channel_mentions") + internal val channelMentions: ChannelMentions? = null, + + @Json(name = "default_preference") + internal val defaultPreference: DefaultPreference? = null, + + @Json(name = "direct_mentions") + internal val directMentions: DirectMentions? = null, + + @Json(name = "group_mentions") + internal val groupMentions: GroupMentions? = null, + + @Json(name = "here_mentions") + internal val hereMentions: HereMentions? = null, + + @Json(name = "role_mentions") + internal val roleMentions: RoleMentions? = null, + + @Json(name = "thread_replies") + internal val threadReplies: ThreadReplies? = null, +) { + + /** + * ChannelMentions Enum + */ + internal sealed class ChannelMentions(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): ChannelMentions = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : ChannelMentions("all") + internal object None : ChannelMentions("none") + internal data class Unknown(val unknownValue: String) : ChannelMentions(unknownValue) + + internal class ChannelMentionsAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): ChannelMentions? { + val s = reader.nextString() ?: return null + return ChannelMentions.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: ChannelMentions?) { + writer.value(value?.value) + } + } + } + + /** + * DefaultPreference Enum + */ + internal sealed class DefaultPreference(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): DefaultPreference = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : DefaultPreference("all") + internal object None : DefaultPreference("none") + internal data class Unknown(val unknownValue: String) : DefaultPreference(unknownValue) + + internal class DefaultPreferenceAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): DefaultPreference? { + val s = reader.nextString() ?: return null + return DefaultPreference.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: DefaultPreference?) { + writer.value(value?.value) + } + } + } + + /** + * DirectMentions Enum + */ + internal sealed class DirectMentions(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): DirectMentions = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : DirectMentions("all") + internal object None : DirectMentions("none") + internal data class Unknown(val unknownValue: String) : DirectMentions(unknownValue) + + internal class DirectMentionsAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): DirectMentions? { + val s = reader.nextString() ?: return null + return DirectMentions.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: DirectMentions?) { + writer.value(value?.value) + } + } + } + + /** + * GroupMentions Enum + */ + internal sealed class GroupMentions(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): GroupMentions = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : GroupMentions("all") + internal object None : GroupMentions("none") + internal data class Unknown(val unknownValue: String) : GroupMentions(unknownValue) + + internal class GroupMentionsAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): GroupMentions? { + val s = reader.nextString() ?: return null + return GroupMentions.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: GroupMentions?) { + writer.value(value?.value) + } + } + } + + /** + * HereMentions Enum + */ + internal sealed class HereMentions(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): HereMentions = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : HereMentions("all") + internal object None : HereMentions("none") + internal data class Unknown(val unknownValue: String) : HereMentions(unknownValue) + + internal class HereMentionsAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): HereMentions? { + val s = reader.nextString() ?: return null + return HereMentions.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: HereMentions?) { + writer.value(value?.value) + } + } + } + + /** + * RoleMentions Enum + */ + internal sealed class RoleMentions(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): RoleMentions = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : RoleMentions("all") + internal object None : RoleMentions("none") + internal data class Unknown(val unknownValue: String) : RoleMentions(unknownValue) + + internal class RoleMentionsAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): RoleMentions? { + val s = reader.nextString() ?: return null + return RoleMentions.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: RoleMentions?) { + writer.value(value?.value) + } + } + } + + /** + * ThreadReplies Enum + */ + internal sealed class ThreadReplies(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): ThreadReplies = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : ThreadReplies("all") + internal object None : ThreadReplies("none") + internal data class Unknown(val unknownValue: String) : ThreadReplies(unknownValue) + + internal class ThreadRepliesAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): ThreadReplies? { + val s = reader.nextString() ?: return null + return ThreadReplies.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: ThreadReplies?) { + writer.value(value?.value) + } + } + } +} diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/FeedsPreferences.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/FeedsPreferences.kt new file mode 100644 index 00000000000..d1ee824c366 --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/FeedsPreferences.kt @@ -0,0 +1,279 @@ +/* + * 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.FromJson +import com.squareup.moshi.Json +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.JsonReader +import com.squareup.moshi.JsonWriter +import com.squareup.moshi.ToJson + +/** + * + */ +@com.squareup.moshi.JsonClass(generateAdapter = true) +internal data class FeedsPreferences( + @Json(name = "comment") + internal val comment: Comment? = null, + + @Json(name = "comment_mention") + internal val commentMention: CommentMention? = null, + + @Json(name = "comment_reaction") + internal val commentReaction: CommentReaction? = null, + + @Json(name = "comment_reply") + internal val commentReply: CommentReply? = null, + + @Json(name = "follow") + internal val follow: Follow? = null, + + @Json(name = "mention") + internal val mention: Mention? = null, + + @Json(name = "reaction") + internal val reaction: Reaction? = null, + + @Json(name = "custom_activity_types") + internal val customActivityTypes: Map? = emptyMap(), +) { + + /** + * Comment Enum + */ + internal sealed class Comment(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): Comment = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : Comment("all") + internal object None : Comment("none") + internal data class Unknown(val unknownValue: String) : Comment(unknownValue) + + internal class CommentAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): Comment? { + val s = reader.nextString() ?: return null + return Comment.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: Comment?) { + writer.value(value?.value) + } + } + } + + /** + * CommentMention Enum + */ + internal sealed class CommentMention(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): CommentMention = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : CommentMention("all") + internal object None : CommentMention("none") + internal data class Unknown(val unknownValue: String) : CommentMention(unknownValue) + + internal class CommentMentionAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): CommentMention? { + val s = reader.nextString() ?: return null + return CommentMention.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: CommentMention?) { + writer.value(value?.value) + } + } + } + + /** + * CommentReaction Enum + */ + internal sealed class CommentReaction(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): CommentReaction = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : CommentReaction("all") + internal object None : CommentReaction("none") + internal data class Unknown(val unknownValue: String) : CommentReaction(unknownValue) + + internal class CommentReactionAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): CommentReaction? { + val s = reader.nextString() ?: return null + return CommentReaction.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: CommentReaction?) { + writer.value(value?.value) + } + } + } + + /** + * CommentReply Enum + */ + internal sealed class CommentReply(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): CommentReply = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : CommentReply("all") + internal object None : CommentReply("none") + internal data class Unknown(val unknownValue: String) : CommentReply(unknownValue) + + internal class CommentReplyAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): CommentReply? { + val s = reader.nextString() ?: return null + return CommentReply.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: CommentReply?) { + writer.value(value?.value) + } + } + } + + /** + * Follow Enum + */ + internal sealed class Follow(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): Follow = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : Follow("all") + internal object None : Follow("none") + internal data class Unknown(val unknownValue: String) : Follow(unknownValue) + + internal class FollowAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): Follow? { + val s = reader.nextString() ?: return null + return Follow.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: Follow?) { + writer.value(value?.value) + } + } + } + + /** + * Mention Enum + */ + internal sealed class Mention(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): Mention = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : Mention("all") + internal object None : Mention("none") + internal data class Unknown(val unknownValue: String) : Mention(unknownValue) + + internal class MentionAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): Mention? { + val s = reader.nextString() ?: return null + return Mention.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: Mention?) { + writer.value(value?.value) + } + } + } + + /** + * Reaction Enum + */ + internal sealed class Reaction(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): Reaction = when (s) { + "all" -> All + "none" -> None + else -> Unknown(s) + } + } + internal object All : Reaction("all") + internal object None : Reaction("none") + internal data class Unknown(val unknownValue: String) : Reaction(unknownValue) + + internal class ReactionAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): Reaction? { + val s = reader.nextString() ?: return null + return Reaction.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: Reaction?) { + writer.value(value?.value) + } + } + } +} diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/PushPreferenceInput.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/PushPreferenceInput.kt new file mode 100644 index 00000000000..7640b01cd09 --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/PushPreferenceInput.kt @@ -0,0 +1,170 @@ +/* + * 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.FromJson +import com.squareup.moshi.Json +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.JsonReader +import com.squareup.moshi.JsonWriter +import com.squareup.moshi.ToJson + +/** + * + */ +@com.squareup.moshi.JsonClass(generateAdapter = true) +internal data class PushPreferenceInput( + @Json(name = "call_level") + internal val callLevel: CallLevel? = null, + + @Json(name = "channel_cid") + internal val channelCid: String? = null, + + @Json(name = "chat_level") + internal val chatLevel: ChatLevel? = null, + + @Json(name = "disabled_until") + internal val disabledUntil: java.util.Date? = null, + + @Json(name = "feeds_level") + internal val feedsLevel: FeedsLevel? = null, + + @Json(name = "remove_disable") + internal val removeDisable: Boolean? = null, + + @Json(name = "user_id") + internal val userId: String? = null, + + @Json(name = "chat_preferences") + internal val chatPreferences: io.getstream.chat.android.network.models.ChatPreferencesInput? = null, + + @Json(name = "feeds_preferences") + internal val feedsPreferences: io.getstream.chat.android.network.models.FeedsPreferences? = null, +) { + + /** + * CallLevel Enum + */ + internal sealed class CallLevel(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): CallLevel = when (s) { + "all" -> All + "default" -> Default + "none" -> None + else -> Unknown(s) + } + } + internal object All : CallLevel("all") + internal object Default : CallLevel("default") + internal object None : CallLevel("none") + internal data class Unknown(val unknownValue: String) : CallLevel(unknownValue) + + internal class CallLevelAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): CallLevel? { + val s = reader.nextString() ?: return null + return CallLevel.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: CallLevel?) { + writer.value(value?.value) + } + } + } + + /** + * ChatLevel Enum + */ + internal sealed class ChatLevel(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): ChatLevel = when (s) { + "all" -> All + "all_mentions" -> AllMentions + "default" -> Default + "direct_mentions" -> DirectMentions + "mentions" -> Mentions + "none" -> None + else -> Unknown(s) + } + } + internal object All : ChatLevel("all") + internal object AllMentions : ChatLevel("all_mentions") + internal object Default : ChatLevel("default") + internal object DirectMentions : ChatLevel("direct_mentions") + internal object Mentions : ChatLevel("mentions") + internal object None : ChatLevel("none") + internal data class Unknown(val unknownValue: String) : ChatLevel(unknownValue) + + internal class ChatLevelAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): ChatLevel? { + val s = reader.nextString() ?: return null + return ChatLevel.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: ChatLevel?) { + writer.value(value?.value) + } + } + } + + /** + * FeedsLevel Enum + */ + internal sealed class FeedsLevel(internal val value: String) { + override fun toString(): String = value + + internal companion object { + internal fun fromString(s: String): FeedsLevel = when (s) { + "all" -> All + "default" -> Default + "none" -> None + else -> Unknown(s) + } + } + internal object All : FeedsLevel("all") + internal object Default : FeedsLevel("default") + internal object None : FeedsLevel("none") + internal data class Unknown(val unknownValue: String) : FeedsLevel(unknownValue) + + internal class FeedsLevelAdapter : JsonAdapter() { + @FromJson + override fun fromJson(reader: JsonReader): FeedsLevel? { + val s = reader.nextString() ?: return null + return FeedsLevel.fromString(s) + } + + @ToJson + override fun toJson(writer: JsonWriter, value: FeedsLevel?) { + writer.value(value?.value) + } + } + } +} diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/QueryMembersPayload.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/QueryMembersPayload.kt new file mode 100644 index 00000000000..9a6b7c6ce88 --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/QueryMembersPayload.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 + +/** + * + */ +@com.squareup.moshi.JsonClass(generateAdapter = true) +internal data class QueryMembersPayload( + @Json(name = "type") + internal val type: String, + + @Json(name = "filter_conditions") + internal val filterConditions: Map = emptyMap(), + + @Json(name = "id") + internal val id: String? = null, + + @Json(name = "limit") + internal val limit: Int? = null, + + @Json(name = "offset") + internal val offset: Int? = null, + + @Json(name = "members") + internal val members: List? = emptyList(), + + @Json(name = "sort") + internal val sort: List? = emptyList(), +) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/UpsertPushPreferencesRequest.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UpsertPushPreferencesRequest.kt similarity index 63% rename from stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/UpsertPushPreferencesRequest.kt rename to stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UpsertPushPreferencesRequest.kt index 42a4c70ef8b..1b6be2fec23 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/UpsertPushPreferencesRequest.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/UpsertPushPreferencesRequest.kt @@ -14,17 +14,22 @@ * limitations under the License. */ -package io.getstream.chat.android.client.api2.model.requests +@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.UpstreamPushPreferenceInputDto +import com.squareup.moshi.Json /** - * Request DTO for upserting push notification preferences. * - * @param preferences List of push preferences to be upserted. */ -@JsonClass(generateAdapter = true) +@com.squareup.moshi.JsonClass(generateAdapter = true) internal data class UpsertPushPreferencesRequest( - val preferences: List, + @Json(name = "preferences") + internal val preferences: List = emptyList(), ) 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 225a652b474..42afc15c5e3 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 @@ -40,8 +40,6 @@ import io.getstream.chat.android.client.api2.mapping.DtoMapping import io.getstream.chat.android.client.api2.mapping.EventMapping import io.getstream.chat.android.client.api2.model.dto.AttachmentDto import io.getstream.chat.android.client.api2.model.dto.DownstreamLocationDto -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.BanUserRequest import io.getstream.chat.android.client.api2.model.requests.FlagMessageRequest import io.getstream.chat.android.client.api2.model.requests.FlagUserRequest @@ -49,7 +47,6 @@ import io.getstream.chat.android.client.api2.model.requests.MuteUserRequest import io.getstream.chat.android.client.api2.model.requests.PinnedMessagesRequest import io.getstream.chat.android.client.api2.model.requests.QueryBannedUsersRequest import io.getstream.chat.android.client.api2.model.requests.UpdateMemberPartialResponse -import io.getstream.chat.android.client.api2.model.requests.UpsertPushPreferencesRequest import io.getstream.chat.android.client.api2.model.response.ChannelResponse import io.getstream.chat.android.client.api2.model.response.DraftMessageResponse import io.getstream.chat.android.client.api2.model.response.EventResponse @@ -124,6 +121,7 @@ import io.getstream.chat.android.network.models.BlockUsersResponse import io.getstream.chat.android.network.models.CastPollVoteRequest import io.getstream.chat.android.network.models.ChannelMemberRequest import io.getstream.chat.android.network.models.ChannelPushPreferencesResponse +import io.getstream.chat.android.network.models.ChatPreferencesInput import io.getstream.chat.android.network.models.ChatPreferencesResponse import io.getstream.chat.android.network.models.CreateDeviceRequest import io.getstream.chat.android.network.models.CreateGuestRequest @@ -153,6 +151,7 @@ import io.getstream.chat.android.network.models.MuteChannelRequest import io.getstream.chat.android.network.models.PollOptionInput import io.getstream.chat.android.network.models.PollOptionRequest import io.getstream.chat.android.network.models.PollOptionResponse +import io.getstream.chat.android.network.models.PushPreferenceInput import io.getstream.chat.android.network.models.PushPreferencesResponse import io.getstream.chat.android.network.models.QueryDraftsRequest import io.getstream.chat.android.network.models.QueryPollVotesRequest @@ -182,6 +181,7 @@ import io.getstream.chat.android.network.models.UpdateUserGroupRequest import io.getstream.chat.android.network.models.UpdateUserGroupResponse import io.getstream.chat.android.network.models.UpdateUserPartialRequest import io.getstream.chat.android.network.models.UpdateUsersPartialRequest +import io.getstream.chat.android.network.models.UpsertPushPreferencesRequest import io.getstream.chat.android.network.models.UpsertPushPreferencesResponse import io.getstream.chat.android.network.models.UserRequest import io.getstream.chat.android.network.models.VoteData @@ -3010,11 +3010,11 @@ internal class MoshiChatApiTest { // then val expectedRequest = UpsertPushPreferencesRequest( preferences = listOf( - UpstreamPushPreferenceInputDto( - channel_cid = null, - chat_level = level.value, - disabled_until = null, - remove_disable = true, + PushPreferenceInput( + channelCid = null, + chatLevel = PushPreferenceInput.ChatLevel.fromString(level.value), + disabledUntil = null, + removeDisable = true, ), ), ) @@ -3044,11 +3044,11 @@ internal class MoshiChatApiTest { // then val expectedRequest = UpsertPushPreferencesRequest( preferences = listOf( - UpstreamPushPreferenceInputDto( - channel_cid = null, - chat_level = null, - disabled_until = until, - remove_disable = null, + PushPreferenceInput( + channelCid = null, + chatLevel = null, + disabledUntil = until, + removeDisable = null, ), ), ) @@ -3081,11 +3081,11 @@ internal class MoshiChatApiTest { // then val expectedRequest = UpsertPushPreferencesRequest( preferences = listOf( - UpstreamPushPreferenceInputDto( - channel_cid = cid, - chat_level = level.value, - disabled_until = null, - remove_disable = true, + PushPreferenceInput( + channelCid = cid, + chatLevel = PushPreferenceInput.ChatLevel.fromString(level.value), + disabledUntil = null, + removeDisable = true, ), ), ) @@ -3118,11 +3118,11 @@ internal class MoshiChatApiTest { // then val expectedRequest = UpsertPushPreferencesRequest( preferences = listOf( - UpstreamPushPreferenceInputDto( - channel_cid = cid, - chat_level = null, - disabled_until = until, - remove_disable = null, + PushPreferenceInput( + channelCid = cid, + chatLevel = null, + disabledUntil = until, + removeDisable = null, ), ), ) @@ -3161,15 +3161,15 @@ internal class MoshiChatApiTest { val expectedRequest = UpsertPushPreferencesRequest( preferences = listOf( - UpstreamPushPreferenceInputDto( - channel_cid = null, - chat_level = null, - disabled_until = null, - remove_disable = null, - chat_preferences = UpstreamChatPreferencesDto( - direct_mentions = "all", - channel_mentions = "none", - default_preference = "none", + PushPreferenceInput( + channelCid = null, + chatLevel = null, + disabledUntil = null, + removeDisable = null, + chatPreferences = ChatPreferencesInput( + directMentions = ChatPreferencesInput.DirectMentions.All, + channelMentions = ChatPreferencesInput.ChannelMentions.None, + defaultPreference = ChatPreferencesInput.DefaultPreference.None, ), ), ), @@ -3203,12 +3203,14 @@ internal class MoshiChatApiTest { val expectedRequest = UpsertPushPreferencesRequest( preferences = listOf( - UpstreamPushPreferenceInputDto( - channel_cid = cid, - chat_level = null, - disabled_until = null, - remove_disable = null, - chat_preferences = UpstreamChatPreferencesDto(direct_mentions = "all"), + PushPreferenceInput( + channelCid = cid, + chatLevel = null, + disabledUntil = null, + removeDisable = null, + chatPreferences = ChatPreferencesInput( + directMentions = ChatPreferencesInput.DirectMentions.All, + ), ), ), ) diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/RequestBodiesAdapterTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/RequestBodiesAdapterTest.kt new file mode 100644 index 00000000000..62052532ece --- /dev/null +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/RequestBodiesAdapterTest.kt @@ -0,0 +1,49 @@ +/* + * 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.parser2.testdata.RequestBodiesTestData +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test + +internal class RequestBodiesAdapterTest { + private val parser = ParserFactory.createMoshiChatParser() + + @Test + fun `Serialize the queryMembers payload`() { + val json = parser.toJson(RequestBodiesTestData.queryMembers) + Assertions.assertEquals(RequestBodiesTestData.queryMembersJson, json) + } + + @Test + fun `Serialize a push preference that snoozes notifications`() { + val json = parser.toJson(RequestBodiesTestData.snoozeUserPushPreferences) + Assertions.assertEquals(RequestBodiesTestData.snoozeUserPushPreferencesJson, json) + } + + @Test + fun `Serialize a push preference that sets a channel level`() { + val json = parser.toJson(RequestBodiesTestData.setChannelPushPreference) + Assertions.assertEquals(RequestBodiesTestData.setChannelPushPreferenceJson, json) + } + + @Test + fun `Serialize a push preference carrying chat preference toggles`() { + val json = parser.toJson(RequestBodiesTestData.setChatPreferences) + Assertions.assertEquals(RequestBodiesTestData.setChatPreferencesJson, json) + } +} diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/RequestBodiesTestData.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/RequestBodiesTestData.kt new file mode 100644 index 00000000000..effff987e5a --- /dev/null +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/RequestBodiesTestData.kt @@ -0,0 +1,83 @@ +/* + * 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.network.models.ChannelMemberRequest +import io.getstream.chat.android.network.models.ChatPreferencesInput +import io.getstream.chat.android.network.models.PushPreferenceInput +import io.getstream.chat.android.network.models.QueryMembersPayload +import io.getstream.chat.android.network.models.SortParamRequest +import io.getstream.chat.android.network.models.UpsertPushPreferencesRequest +import java.util.Date + +internal object RequestBodiesTestData { + + val queryMembers = QueryMembersPayload( + type = "messaging", + id = "channelId", + filterConditions = mapOf("name" to mapOf("\$autocomplete" to "amit")), + offset = 10, + limit = 30, + // Pinned as a literal rather than built from a sorter, so the expected wire shape is asserted + // rather than restated by the same conversion the payload uses. + sort = listOf(SortParamRequest(field = "created_at", direction = -1)), + members = listOf(ChannelMemberRequest(userId = "amit", channelRole = "channel_moderator")), + ) + + // The member carries no custom data, and the collecting adapter flattens custom to the root, so no + // `custom` key is emitted at all. + val queryMembersJson = + """{"type":"messaging","filter_conditions":{"name":{"${'$'}autocomplete":"amit"}},"id":"channelId",""" + + """"limit":30,"offset":10,"members":[{"user_id":"amit","channel_role":"channel_moderator"}],""" + + """"sort":[{"direction":-1,"field":"created_at"}]}""" + + val snoozeUserPushPreferences = UpsertPushPreferencesRequest( + preferences = listOf(PushPreferenceInput(disabledUntil = Date(1614218400000))), + ) + + const val snoozeUserPushPreferencesJson = + """{"preferences":[{"disabled_until":"2021-02-25T02:00:00.000Z"}]}""" + + val setChannelPushPreference = UpsertPushPreferencesRequest( + preferences = listOf( + PushPreferenceInput( + channelCid = "messaging:channelId", + chatLevel = PushPreferenceInput.ChatLevel.fromString("all"), + removeDisable = true, + ), + ), + ) + + const val setChannelPushPreferenceJson = + """{"preferences":[{"channel_cid":"messaging:channelId","chat_level":"all","remove_disable":true}]}""" + + val setChatPreferences = UpsertPushPreferencesRequest( + preferences = listOf( + PushPreferenceInput( + chatPreferences = ChatPreferencesInput( + directMentions = ChatPreferencesInput.DirectMentions.fromString("all"), + threadReplies = ChatPreferencesInput.ThreadReplies.fromString("none"), + defaultPreference = ChatPreferencesInput.DefaultPreference.fromString("all"), + ), + ), + ), + ) + + const val setChatPreferencesJson = + """{"preferences":[{"chat_preferences":{"default_preference":"all","direct_mentions":"all",""" + + """"thread_replies":"none"}}]}""" +}