Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AND-16] Implement ChatClient.partialUpdateMember() #5497

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
### ⬆️ Improved

### ✅ Added
- Add `ChatClient::partialUpdateMember` for updating a `Member` in the scope of a `Channel`. [#5497](https://github.com/GetStream/stream-chat-android/pull/5497)
- Add `ChannelClient::partialUpdateMember` for updating a `Member` in the scope of a `Channel`. [#5497](https://github.com/GetStream/stream-chat-android/pull/5497)

### ⚠️ Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ public final class io/getstream/chat/android/client/ChatClient {
public final fun muteUser (Ljava/lang/String;)Lio/getstream/result/call/Call;
public final fun muteUser (Ljava/lang/String;Ljava/lang/Integer;)Lio/getstream/result/call/Call;
public static synthetic fun muteUser$default (Lio/getstream/chat/android/client/ChatClient;Ljava/lang/String;Ljava/lang/Integer;ILjava/lang/Object;)Lio/getstream/result/call/Call;
public final fun partialUpdateMember (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/List;)Lio/getstream/result/call/Call;
public static synthetic fun partialUpdateMember$default (Lio/getstream/chat/android/client/ChatClient;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/List;ILjava/lang/Object;)Lio/getstream/result/call/Call;
public final fun partialUpdateMessage (Ljava/lang/String;Ljava/util/Map;Ljava/util/List;)Lio/getstream/result/call/Call;
public static synthetic fun partialUpdateMessage$default (Lio/getstream/chat/android/client/ChatClient;Ljava/lang/String;Ljava/util/Map;Ljava/util/List;ILjava/lang/Object;)Lio/getstream/result/call/Call;
public final fun partialUpdateThread (Ljava/lang/String;Ljava/util/Map;Ljava/util/List;)Lio/getstream/result/call/Call;
Expand Down Expand Up @@ -670,6 +672,8 @@ public final class io/getstream/chat/android/client/channel/ChannelClient {
public final fun muteUser (Ljava/lang/String;)Lio/getstream/result/call/Call;
public final fun muteUser (Ljava/lang/String;Ljava/lang/Integer;)Lio/getstream/result/call/Call;
public static synthetic fun muteUser$default (Lio/getstream/chat/android/client/channel/ChannelClient;Ljava/lang/String;Ljava/lang/Integer;ILjava/lang/Object;)Lio/getstream/result/call/Call;
public final fun partialUpdateMember (Ljava/lang/String;Ljava/util/Map;Ljava/util/List;)Lio/getstream/result/call/Call;
public static synthetic fun partialUpdateMember$default (Lio/getstream/chat/android/client/channel/ChannelClient;Ljava/lang/String;Ljava/util/Map;Ljava/util/List;ILjava/lang/Object;)Lio/getstream/result/call/Call;
public final fun pinMessage (Lio/getstream/chat/android/models/Message;I)Lio/getstream/result/call/Call;
public final fun pinMessage (Lio/getstream/chat/android/models/Message;Ljava/util/Date;)Lio/getstream/result/call/Call;
public final fun query (Lio/getstream/chat/android/client/api/models/QueryChannelRequest;)Lio/getstream/result/call/Call;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2350,6 +2350,34 @@ internal constructor(
)
}

/**
* Updates specific fields of member data, retaining the custom data fields which were set previously.
*
* @param channelType The channel type. ie messaging.
* @param channelId The channel id. ie 123.
* @param userId The ID of the member to be updated.
* @param set The key-value data to be updated in the member data.
* @param unset The list of keys to be removed from the member data.
*
* @return Executable async [Call] responsible for updating member data.
*/
@CheckResult
public fun partialUpdateMember(
channelType: String,
channelId: String,
userId: String,
set: Map<String, Any> = emptyMap(),
unset: List<String> = emptyList(),
): Call<Member> {
return api.partialUpdateMember(
channelType = channelType,
channelId = channelId,
userId = userId,
set = set,
unset = unset,
)
}

/**
* Enables slow mode for the channel. When slow mode is enabled, users can only send a message every
* [cooldownTimeInSeconds] time interval. The [cooldownTimeInSeconds] is specified in seconds, and should be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,15 @@ internal interface ChatApi {
skipPush: Boolean?,
): Call<Channel>

@CheckResult
fun partialUpdateMember(
channelType: String,
channelId: String,
userId: String,
set: Map<String, Any>,
unset: List<String>,
): Call<Member>

@CheckResult
fun queryMembers(
channelType: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import io.getstream.chat.android.client.api.ChatApi
import io.getstream.chat.android.client.api.ErrorCall
import io.getstream.chat.android.models.Channel
import io.getstream.chat.android.models.CustomObject
import io.getstream.chat.android.models.Member
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.models.User
import io.getstream.result.Error
Expand Down Expand Up @@ -86,6 +87,18 @@ internal class ExtraDataValidator(
.withExtraDataValidation(set)
}

override fun partialUpdateMember(
channelType: String,
channelId: String,
userId: String,
set: Map<String, Any>,
unset: List<String>,
): Call<Member> {
return delegate
.partialUpdateMember(channelType, channelId, userId, set, unset)
.withExtraDataValidation(set)
}

private fun <T : CustomObject> Call<List<T>>.withExtraDataValidation(
objects: List<T>,
): Call<List<T>> {
Expand Down Expand Up @@ -144,6 +157,7 @@ internal class ExtraDataValidator(
is Channel -> extraData.keys.filter(reservedInChannelPredicate)
is Message -> extraData.keys.filter(reservedInChannelPredicate)
is User -> extraData.keys.filter(reservedInChannelPredicate)
is Member -> extraData.keys.filter(reservedInMemberPredicate)
else -> emptyList()
}
}
Expand All @@ -153,6 +167,7 @@ internal class ExtraDataValidator(
Channel::class -> keys.filter(reservedInChannelPredicate)
Message::class -> keys.filter(reservedInMessagePredicate)
User::class -> keys.filter(reservedInUserPredicate)
Member::class -> keys.filter(reservedInMemberPredicate)
else -> emptyList()
}
}
Expand All @@ -166,6 +181,7 @@ internal class ExtraDataValidator(
is Channel -> "channel"
is Message -> "message"
is User -> "user"
is Member -> "member"
else -> ""
}
}
Expand Down Expand Up @@ -210,8 +226,24 @@ internal class ExtraDataValidator(
"updated_at",
)

private val reservedInMember = setOf(
"user",
"created_at",
"updated_at",
"invited",
"invite_accepted_at",
"invite_rejected_at",
"shadow_banned",
"banned",
"channel_role",
"notifications_muted",
"status",
"ban_expires",
)

private val reservedInChannelPredicate: (String) -> Boolean = reservedInChannel::contains
private val reservedInMessagePredicate: (String) -> Boolean = reservedInMessage::contains
private val reservedInUserPredicate: (String) -> Boolean = reservedInUser::contains
private val reservedInMemberPredicate: (String) -> Boolean = reservedInMember::contains
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ import io.getstream.chat.android.client.api2.model.requests.UnblockUserRequest
import io.getstream.chat.android.client.api2.model.requests.UpdateChannelPartialRequest
import io.getstream.chat.android.client.api2.model.requests.UpdateChannelRequest
import io.getstream.chat.android.client.api2.model.requests.UpdateCooldownRequest
import io.getstream.chat.android.client.api2.model.requests.UpdateMemberPartialRequest
import io.getstream.chat.android.client.api2.model.requests.UpdateMessageRequest
import io.getstream.chat.android.client.api2.model.requests.UpdateUsersRequest
import io.getstream.chat.android.client.api2.model.requests.UpstreamOptionDto
Expand Down Expand Up @@ -785,6 +786,23 @@ constructor(
).map(this::flattenChannel)
}

override fun partialUpdateMember(
channelType: String,
channelId: String,
userId: String,
set: Map<String, Any>,
unset: List<String>,
): Call<Member> {
return channelApi.partialUpdateMember(
channelType = channelType,
channelId = channelId,
userId = userId,
body = UpdateMemberPartialRequest(set, unset),
).map { response ->
response.channel_member.toDomain(currentUserIdProvider())
}
}

private fun flattenChannel(response: ChannelResponse): Channel {
return response.channel.toDomain(currentUserIdProvider(), null).let { channel ->
channel.copy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import io.getstream.chat.android.client.api2.model.requests.TruncateChannelReque
import io.getstream.chat.android.client.api2.model.requests.UpdateChannelPartialRequest
import io.getstream.chat.android.client.api2.model.requests.UpdateChannelRequest
import io.getstream.chat.android.client.api2.model.requests.UpdateCooldownRequest
import io.getstream.chat.android.client.api2.model.requests.UpdateMemberPartialRequest
import io.getstream.chat.android.client.api2.model.requests.UpdateMemberPartialResponse
import io.getstream.chat.android.client.api2.model.response.ChannelResponse
import io.getstream.chat.android.client.api2.model.response.CompletableResponse
import io.getstream.chat.android.client.api2.model.response.EventResponse
Expand Down Expand Up @@ -135,6 +137,14 @@ internal interface ChannelApi {
@Body body: InviteMembersRequest,
): RetrofitCall<ChannelResponse>

@PATCH("/channels/{type}/{id}/member/{user_id}")
fun partialUpdateMember(
@Path("type") channelType: String,
@Path("id") channelId: String,
@Path("user_id") userId: String,
@Body body: UpdateMemberPartialRequest,
): RetrofitCall<UpdateMemberPartialResponse>

@POST("/channels/{type}/{id}/event")
fun sendEvent(
@Path("type") channelType: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ internal fun DownstreamMemberDto.toDomain(currentUserId: UserId?): Member =
notificationsMuted = notifications_muted,
status = status,
banExpires = ban_expires,
extraData = extraData,
)

internal fun Member.toDto(): UpstreamMemberDto =
Expand All @@ -51,4 +52,5 @@ internal fun Member.toDto(): UpstreamMemberDto =
notifications_muted = notificationsMuted,
status = status,
ban_expires = banExpires,
extraData = extraData,
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,17 @@
package io.getstream.chat.android.client.api2.model.dto

import com.squareup.moshi.JsonClass
import io.getstream.chat.android.core.internal.StreamHandsOff
import java.util.Date

/**
* See [io.getstream.chat.android.client.parser2.adapters.UpstreamMemberDtoAdapter] for
* special [extraData] handling.
*/
@StreamHandsOff(
reason = "Field names can't be changed because [CustomObjectDtoAdapter] class uses reflections to add/remove " +
"content of [extraData] map",
)
@JsonClass(generateAdapter = true)
internal data class UpstreamMemberDto(
val user: UpstreamUserDto,
Expand All @@ -33,8 +42,18 @@ internal data class UpstreamMemberDto(
val notifications_muted: Boolean?,
val status: String?,
val ban_expires: Date?,
)

val extraData: Map<String, Any>,
) : ExtraDataDto

/**
* See [io.getstream.chat.android.client.parser2.adapters.DownstreamMemberDtoAdapter] for
* special [extraData] handling.
*/
@StreamHandsOff(
reason = "Field names can't be changed because [CustomObjectDtoAdapter] class uses reflections to add/remove " +
"content of [extraData] map",
)
@JsonClass(generateAdapter = true)
internal data class DownstreamMemberDto(
val user: DownstreamUserDto,
Expand All @@ -49,4 +68,6 @@ internal data class DownstreamMemberDto(
val notifications_muted: Boolean?,
val status: String?,
val ban_expires: Date?,
)

val extraData: Map<String, Any>,
) : ExtraDataDto
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2014-2024 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

/**
* Used to form a partial member update request.
*
* @param set Map of key-value pairs to set.
* @param unset List of keys to unset.
*/
@JsonClass(generateAdapter = true)
internal data class UpdateMemberPartialRequest(
val set: Map<String, Any>,
val unset: List<String>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2014-2024 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.DownstreamMemberDto

/**
* Response model of the partial member update.
*
* @param channel_member The updated member object.
*/
@JsonClass(generateAdapter = true)
internal data class UpdateMemberPartialResponse(
val channel_member: DownstreamMemberDto,
)
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,22 @@ public class ChannelClient internal constructor(
return client.updateChannelPartial(channelType, channelId, set, unset)
}

/**
* Updates specific fields of custom data for a given member.
*
* @param userId The user id of the member to update.
* @param set The key-value data to be updated in the member data.
* @param unset The list of keys to be removed from the member data.
*/
@CheckResult
public fun partialUpdateMember(
userId: String,
set: Map<String, Any> = emptyMap(),
unset: List<String> = emptyList(),
): Call<Member> {
return client.partialUpdateMember(channelType, channelId, userId, set, unset)
}

/**
* Enables slow mode for the channel. When slow mode is enabled, users can only send a message every
* [cooldownTimeInSeconds] time interval. The [cooldownTimeInSeconds] is specified in seconds, and should be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ import io.getstream.chat.android.client.parser.ChatParser
import io.getstream.chat.android.client.parser2.adapters.AttachmentDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.DateAdapter
import io.getstream.chat.android.client.parser2.adapters.DownstreamChannelDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.DownstreamMemberDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.DownstreamMessageDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.DownstreamModerationDetailsDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.DownstreamReactionDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.DownstreamUserDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.EventAdapterFactory
import io.getstream.chat.android.client.parser2.adapters.ExactDateAdapter
import io.getstream.chat.android.client.parser2.adapters.UpstreamChannelDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.UpstreamMemberDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.UpstreamMessageDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.UpstreamReactionDtoAdapter
import io.getstream.chat.android.client.parser2.adapters.UpstreamUserDtoAdapter
Expand Down Expand Up @@ -67,6 +69,8 @@ internal class MoshiChatParser(
.add(UpstreamReactionDtoAdapter)
.add(DownstreamUserDtoAdapter)
.add(UpstreamUserDtoAdapter)
.add(DownstreamMemberDtoAdapter)
.add(UpstreamMemberDtoAdapter)
.add(FlagRequestAdapterFactory)
.build()
}
Expand Down
Loading
Loading