From 0badf781d914240e74928dae10af6dc092cc5981 Mon Sep 17 00:00:00 2001 From: VelikovPetar Date: Mon, 6 Oct 2025 15:32:29 +0200 Subject: [PATCH 01/19] Add missing arguments to `CreatePoll`. --- .../client/api/models/QueryThreadsRequest.kt | 1 + .../chat/android/client/api2/MoshiChatApi.kt | 26 +- .../android/client/api2/endpoint/PollsApi.kt | 6 +- .../client/api2/mapping/DomainMapping.kt | 15 +- .../client/api2/model/dto/PollsDtos.kt | 59 ++-- .../{PollsRequest.kt => PollRequests.kt} | 62 ++-- .../response/SuggestPollOptionResponse.kt | 4 +- .../android/client/parser2/MoshiChatParser.kt | 8 + .../parser2/adapters/PollDtoAdapters.kt | 101 +++++++ .../getstream/chat/android/client/Mother.kt | 12 +- .../android/client/api2/MoshiChatApiTest.kt | 16 +- .../client/api2/mapping/DomainMappingTest.kt | 10 +- .../internal/PollExtensionsTests.kt | 3 + .../parser2/CreatePollRequestAdapterTest.kt | 37 +++ .../parser2/DownstreamPollDtoAdapterTest.kt | 44 +++ .../DownstreamPollOptionDtoAdapterTest.kt | 44 +++ .../parser2/UpstreamOptionDtoAdapterTest.kt | 37 +++ .../parser2/testdata/PollDtoTestData.kt | 281 ++++++++++++++++++ .../api/stream-chat-android-core.api | 57 +++- .../io/getstream/chat/android/models/Poll.kt | 59 +++- .../io/getstream/chat/android/Mother.kt | 8 + .../database/internal/ChatDatabase.kt | 2 +- .../domain/message/internal/MessageMapper.kt | 10 + .../domain/message/internal/Poll.kt | 5 + .../android/previewdata/PreviewPollData.kt | 3 + 25 files changed, 809 insertions(+), 101 deletions(-) rename stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/{PollsRequest.kt => PollRequests.kt} (70%) create mode 100644 stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/PollDtoAdapters.kt create mode 100644 stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/CreatePollRequestAdapterTest.kt create mode 100644 stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollDtoAdapterTest.kt create mode 100644 stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollOptionDtoAdapterTest.kt create mode 100644 stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/UpstreamOptionDtoAdapterTest.kt create mode 100644 stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/PollDtoTestData.kt diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/models/QueryThreadsRequest.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/models/QueryThreadsRequest.kt index bfc59ef5fab..3e509fe8e92 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/models/QueryThreadsRequest.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/models/QueryThreadsRequest.kt @@ -30,6 +30,7 @@ import io.getstream.chat.android.models.querysort.QuerySorter * @property filter The filter object for the query. Supported fields: * - `channel_cid` Filter by channel CID. Supported operators: `$eq`, `$in` * - `channel.disabled` Filter by channel disabled status. Supported operators: `$eq` + * - `channel.team` Filter by channel team. Supported operators: `$eq`, `$in` * - `parent_message_id` Filter by parent message ID. Supported operators: `$eq`, `$in` * - `created_by_user_id` Filter by thread creator’s user ID. Supported operators: `$eq`, `$in` * - `created_at` Filter by thread creation timestamp. Supported operators: `$eq`, `$gt`, `$lt`, `$gte`, `$lte` 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 0007c4bc18e..0825fd78f6c 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 @@ -48,6 +48,7 @@ import io.getstream.chat.android.client.api2.model.requests.AddDeviceRequest import io.getstream.chat.android.client.api2.model.requests.AddMembersRequest import io.getstream.chat.android.client.api2.model.requests.BanUserRequest import io.getstream.chat.android.client.api2.model.requests.BlockUserRequest +import io.getstream.chat.android.client.api2.model.requests.CreatePollRequest import io.getstream.chat.android.client.api2.model.requests.FlagMessageRequest import io.getstream.chat.android.client.api2.model.requests.FlagRequest import io.getstream.chat.android.client.api2.model.requests.FlagUserRequest @@ -62,7 +63,6 @@ import io.getstream.chat.android.client.api2.model.requests.PartialUpdateMessage import io.getstream.chat.android.client.api2.model.requests.PartialUpdateThreadRequest import io.getstream.chat.android.client.api2.model.requests.PartialUpdateUsersRequest import io.getstream.chat.android.client.api2.model.requests.PinnedMessagesRequest -import io.getstream.chat.android.client.api2.model.requests.PollRequest import io.getstream.chat.android.client.api2.model.requests.PollUpdateRequest import io.getstream.chat.android.client.api2.model.requests.PollVoteRequest import io.getstream.chat.android.client.api2.model.requests.QueryBannedUsersRequest @@ -1508,18 +1508,24 @@ constructor( override fun createPoll(pollConfig: PollConfig): Call { return pollsApi.createPoll( - PollRequest( - name = pollConfig.name, + CreatePollRequest( + allow_answers = pollConfig.allowAnswers, + allow_user_suggested_options = pollConfig.allowUserSuggestedOptions, description = pollConfig.description, - options = pollConfig.options.map(::UpstreamOptionDto), - voting_visibility = when (pollConfig.votingVisibility) { - VotingVisibility.PUBLIC -> PollRequest.VOTING_VISIBILITY_PUBLIC - VotingVisibility.ANONYMOUS -> PollRequest.VOTING_VISIBILITY_ANONYMOUS - }, enforce_unique_vote = pollConfig.enforceUniqueVote, max_votes_allowed = pollConfig.maxVotesAllowed, - allow_user_suggested_options = pollConfig.allowUserSuggestedOptions, - allow_answers = pollConfig.allowAnswers, + name = pollConfig.name, + options = pollConfig.options.map { + UpstreamOptionDto( + text = it.text, + extraData = it.extraData, + ) + }, + voting_visibility = when (pollConfig.votingVisibility) { + VotingVisibility.PUBLIC -> CreatePollRequest.VOTING_VISIBILITY_PUBLIC + VotingVisibility.ANONYMOUS -> CreatePollRequest.VOTING_VISIBILITY_ANONYMOUS + }, + extraData = pollConfig.extraData, ), ).mapDomain { it.poll.toDomain() } } diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/PollsApi.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/PollsApi.kt index 8212835103e..1342a32d111 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/PollsApi.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/endpoint/PollsApi.kt @@ -17,7 +17,7 @@ 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.PollRequest +import io.getstream.chat.android.client.api2.model.requests.CreatePollRequest import io.getstream.chat.android.client.api2.model.requests.PollUpdateRequest import io.getstream.chat.android.client.api2.model.requests.PollVoteRequest import io.getstream.chat.android.client.api2.model.requests.SuggestPollOptionRequest @@ -38,12 +38,12 @@ internal interface PollsApi { /** * Creates a new poll. * - * @param pollRequest The poll request. + * @param body Body holding the poll properties to be created. * * @return The poll response. */ @POST("/polls") - fun createPoll(@Body pollRequest: PollRequest): RetrofitCall + fun createPoll(@Body body: CreatePollRequest): RetrofitCall /** * Suggest a new option for a poll. diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt index 798d5c4c5c0..be4027d42d2 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt @@ -35,9 +35,9 @@ import io.getstream.chat.android.client.api2.model.dto.DownstreamMessageDto import io.getstream.chat.android.client.api2.model.dto.DownstreamModerationDetailsDto import io.getstream.chat.android.client.api2.model.dto.DownstreamModerationDto import io.getstream.chat.android.client.api2.model.dto.DownstreamMuteDto -import io.getstream.chat.android.client.api2.model.dto.DownstreamOptionDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPendingMessageDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPollDto +import io.getstream.chat.android.client.api2.model.dto.DownstreamPollOptionDto import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionDto import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionGroupDto import io.getstream.chat.android.client.api2.model.dto.DownstreamReminderDto @@ -432,7 +432,7 @@ internal class DomainMapping( .values .toList() - val answer = latest_answers?.map { it.toAnswerDomain() } ?: emptyList() + val answers = latest_answers?.map { it.toAnswerDomain() } ?: emptyList() return Poll( id = id, @@ -444,13 +444,17 @@ internal class DomainMapping( maxVotesAllowed = max_votes_allowed ?: 1, allowUserSuggestedOptions = allow_user_suggested_options, allowAnswers = allow_answers, + voteCount = vote_count, voteCountsByOption = vote_counts_by_option ?: emptyMap(), votes = votes, ownVotes = ownVotes, createdAt = created_at, updatedAt = updated_at, - closed = is_closed, - answers = answer, + closed = is_closed ?: false, + answersCount = answers_count, + answers = answers, + createdBy = created_by?.toDomain(), + extraData = extraData ?: emptyMap(), ) } @@ -459,9 +463,10 @@ internal class DomainMapping( * * @return Option */ - internal fun DownstreamOptionDto.toDomain(): Option = Option( + internal fun DownstreamPollOptionDto.toDomain(): Option = Option( id = id, text = text, + extraData = extraData ?: emptyMap(), ) /** diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PollsDtos.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PollsDtos.kt index c17605cb293..a90e8dcd7a2 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PollsDtos.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PollsDtos.kt @@ -24,12 +24,14 @@ import java.util.Date * * @property id The id of the option. * @property text The text of the option. + * @property extraData Any extra data associated with the option. */ @JsonClass(generateAdapter = true) -internal data class DownstreamOptionDto( +internal data class DownstreamPollOptionDto( val id: String, val text: String, -) + val extraData: Map?, +) : ExtraDataDto /** * Represents the DTO for a vote in a poll. @@ -58,44 +60,49 @@ internal data class DownstreamVoteDto( /** * Represents the DTO for a poll. * - * @property id The id of the poll. - * @property name The name of the poll. - * @property description The description of the poll. - * @property voting_visibility The visibility of the votes in the poll. Can be "public" or "anonymous". - * @property enforce_unique_vote Whether the poll enforces unique votes. - * @property max_votes_allowed The maximum number of votes allowed in the poll. - * @property allow_user_suggested_options Whether the poll allows user suggested options. * @property allow_answers Whether the poll allows answers. - * @property options The options in the poll. - * @property vote_counts_by_option The vote counts for each option in the poll. - * @property latest_votes_by_option The latest votes for each option in the poll. + * @property allow_user_suggested_options Whether the poll allows user suggested options. + * @property answers_count The total number of answers in the poll. * @property created_at The date when the poll was created. * @property created_by The user who created the poll. * @property created_by_id The id of the user who created the poll. + * @property description The description of the poll. + * @property enforce_unique_vote Whether the poll enforces unique votes. + * @property id The id of the poll. + * @property is_closed Whether the poll is closed. + * @property latest_answers The latest answers in the poll. + * @property latest_votes_by_option The latest votes for each option in the poll. + * @property max_votes_allowed The maximum number of votes allowed in the poll. + * @property name The name of the poll. + * @property options The options in the poll. * @property own_votes The votes of the user who requested the poll. * @property updated_at The date when the poll was last updated. * @property vote_count The total number of votes in the poll. - * @property is_closed Whether the poll is closed. + * @property vote_counts_by_option The vote counts for each option in the poll. + * @property voting_visibility The visibility of the votes in the poll. Can be "public" or "anonymous". + * @property extraData Any extra data associated with the poll. */ @JsonClass(generateAdapter = true) internal data class DownstreamPollDto( - val id: String, - val name: String, - val description: String, - val voting_visibility: String?, - val enforce_unique_vote: Boolean, - val max_votes_allowed: Int?, - val allow_user_suggested_options: Boolean, val allow_answers: Boolean, - val options: List, - val vote_counts_by_option: Map?, - val latest_votes_by_option: Map>?, - val latest_answers: List?, + val allow_user_suggested_options: Boolean, + val answers_count: Int, val created_at: Date, val created_by: DownstreamUserDto?, val created_by_id: String, + val description: String, + val enforce_unique_vote: Boolean, + val id: String, + val is_closed: Boolean?, + val latest_answers: List?, + val latest_votes_by_option: Map>?, + val max_votes_allowed: Int?, + val name: String, + val options: List, val own_votes: List, val updated_at: Date, val vote_count: Int, - val is_closed: Boolean = false, -) + val vote_counts_by_option: Map?, + val voting_visibility: String?, + val extraData: Map?, +) : ExtraDataDto diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/PollsRequest.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/PollRequests.kt similarity index 70% rename from stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/PollsRequest.kt rename to stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/PollRequests.kt index 835570b6180..87d2bb156c9 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/PollsRequest.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/requests/PollRequests.kt @@ -17,50 +17,56 @@ package io.getstream.chat.android.client.api2.model.requests import com.squareup.moshi.JsonClass +import io.getstream.chat.android.client.api2.model.dto.ExtraDataDto /** - * Used for creating a new poll. - * - * @property text the text of the option. - */ -@JsonClass(generateAdapter = true) -internal data class UpstreamOptionDto( - val text: String, -) - -/** - * Used for creating a new poll. + * Request body for creating a new poll. * - * @property name the name of the poll. - * @property description the description of the poll. - * @property options the list of options for the poll. - * @property voting_visibility the visibility of the poll. Accepted values are "public" and "anonymous". - * @property enforce_unique_vote Indicates whether users can cast multiple votes. - * @property max_votes_allowed the maximum number of votes allowed per user. min: 1, max: 10 + * @property allow_answers Indicates whether users can suggest user defined answers. * @property allow_user_suggested_options Indicates whether users can suggest new options. + * @property description A description of the poll. + * @property enforce_unique_vote Indicates whether users can cast multiple votes. + * @property max_votes_allowed Indicates the maximum amount of votes a user can cast. + * @property name The name of the poll. + * @property options The list of options for the poll. + * @property voting_visibility The visibility of the poll. Accepted values are "public" and "anonymous". + * @property extraData Any additional custom fields. */ @JsonClass(generateAdapter = true) -internal data class PollRequest( - val name: String, +internal data class CreatePollRequest( + val allow_answers: Boolean, + val allow_user_suggested_options: Boolean, val description: String, - val options: List, - val voting_visibility: String, val enforce_unique_vote: Boolean, val max_votes_allowed: Int, - val allow_user_suggested_options: Boolean, - val allow_answers: Boolean, -) { + val name: String, + val options: List, + val voting_visibility: String, + val extraData: Map, +) : ExtraDataDto { - companion object { - const val VOTING_VISIBILITY_PUBLIC = "public" - const val VOTING_VISIBILITY_ANONYMOUS = "anonymous" + internal companion object { + internal const val VOTING_VISIBILITY_PUBLIC = "public" + internal const val VOTING_VISIBILITY_ANONYMOUS = "anonymous" } } +/** + * Used for creating a new poll. + * + * @property text the text of the option. + * @property extraData any additional custom fields. + */ +@JsonClass(generateAdapter = true) +internal data class UpstreamOptionDto( + val text: String, + val extraData: Map, +) : ExtraDataDto + /** * Used for suggesting a new option for a poll. * - * @property poll_option the option object. + * @property text the option text. */ @JsonClass(generateAdapter = true) internal data class SuggestPollOptionRequest( diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/SuggestPollOptionResponse.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/SuggestPollOptionResponse.kt index bc461d9617c..7719df846b7 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/SuggestPollOptionResponse.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/response/SuggestPollOptionResponse.kt @@ -17,7 +17,7 @@ package io.getstream.chat.android.client.api2.model.response import com.squareup.moshi.JsonClass -import io.getstream.chat.android.client.api2.model.dto.DownstreamOptionDto +import io.getstream.chat.android.client.api2.model.dto.DownstreamPollOptionDto /** * Response for suggesting a new option for a poll. @@ -28,5 +28,5 @@ import io.getstream.chat.android.client.api2.model.dto.DownstreamOptionDto @JsonClass(generateAdapter = true) internal data class SuggestPollOptionResponse( val duration: String, - val poll_option: DownstreamOptionDto, + val poll_option: DownstreamPollOptionDto, ) 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 d33b66060f2..bc5f596b0f2 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 @@ -31,11 +31,14 @@ import io.getstream.chat.android.client.events.ConnectedEvent import io.getstream.chat.android.client.extensions.internal.enrichIfNeeded 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.CreatePollRequestAdapter 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.DownstreamPollDtoAdapter +import io.getstream.chat.android.client.parser2.adapters.DownstreamPollOptionDtoAdapter import io.getstream.chat.android.client.parser2.adapters.DownstreamReactionDtoAdapter import io.getstream.chat.android.client.parser2.adapters.DownstreamThreadDtoAdapter import io.getstream.chat.android.client.parser2.adapters.DownstreamThreadInfoDtoAdapter @@ -46,6 +49,7 @@ import io.getstream.chat.android.client.parser2.adapters.UpstreamChannelDtoAdapt import io.getstream.chat.android.client.parser2.adapters.UpstreamMemberDataDtoAdapter 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.UpstreamOptionDtoAdapter import io.getstream.chat.android.client.parser2.adapters.UpstreamReactionDtoAdapter import io.getstream.chat.android.client.parser2.adapters.UpstreamUserDtoAdapter import io.getstream.chat.android.client.socket.ErrorResponse @@ -79,6 +83,10 @@ internal class MoshiChatParser( .add(FlagRequestAdapterFactory) .add(DownstreamThreadDtoAdapter) .add(DownstreamThreadInfoDtoAdapter) + .add(DownstreamPollDtoAdapter) + .add(DownstreamPollOptionDtoAdapter) + .add(CreatePollRequestAdapter) + .add(UpstreamOptionDtoAdapter) .build() } diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/PollDtoAdapters.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/PollDtoAdapters.kt new file mode 100644 index 00000000000..b5d99368ad4 --- /dev/null +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/PollDtoAdapters.kt @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014-2025 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.getstream.chat.android.client.parser2.adapters + +import com.squareup.moshi.FromJson +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.JsonReader +import com.squareup.moshi.JsonWriter +import com.squareup.moshi.ToJson +import io.getstream.chat.android.client.api2.model.dto.DownstreamPollDto +import io.getstream.chat.android.client.api2.model.dto.DownstreamPollOptionDto +import io.getstream.chat.android.client.api2.model.requests.CreatePollRequest +import io.getstream.chat.android.client.api2.model.requests.UpstreamOptionDto + +/** + * Deserializer for [DownstreamPollDto] that handles the [io.getstream.chat.android.client.api2.model.dto.ExtraDataDto] + * implementation. + */ +internal object DownstreamPollDtoAdapter : CustomObjectDtoAdapter(DownstreamPollDto::class) { + + @FromJson + fun fromJson( + jsonReader: JsonReader, + mapAdapter: JsonAdapter>, + pollAdapter: JsonAdapter, + ): DownstreamPollDto? = parseWithExtraData(jsonReader, mapAdapter, pollAdapter) + + @ToJson + fun toJson(jsonWriter: JsonWriter, value: DownstreamPollDto): Unit = error("Can't convert this to Json") +} + +/** + * Deserializer for [DownstreamPollOptionDto] that handles the + * [io.getstream.chat.android.client.api2.model.dto.ExtraDataDto] implementation. + */ +internal object DownstreamPollOptionDtoAdapter : + CustomObjectDtoAdapter(DownstreamPollOptionDto::class) { + + @FromJson + fun fromJson( + jsonReader: JsonReader, + mapAdapter: JsonAdapter>, + optionAdapter: JsonAdapter, + ): DownstreamPollOptionDto? = parseWithExtraData(jsonReader, mapAdapter, optionAdapter) + + @ToJson + fun toJson(jsonWriter: JsonWriter, value: DownstreamPollOptionDto): Unit = error("Can't convert this to Json") +} + +/** + * Serializer for [CreatePollRequest] that handles the [io.getstream.chat.android.client.api2.model.dto.ExtraDataDto] + * implementation. + */ +internal object CreatePollRequestAdapter : CustomObjectDtoAdapter(CreatePollRequest::class) { + + @FromJson + @Suppress("UNUSED_PARAMETER") + fun fromJson(jsonReader: JsonReader): CreatePollRequest = error("Can't parse this from Json") + + @ToJson + fun toJson( + jsonWriter: JsonWriter, + request: CreatePollRequest?, + mapAdapter: JsonAdapter>, + requestAdapter: JsonAdapter, + ) = serializeWithExtraData(jsonWriter, request, mapAdapter, requestAdapter) +} + +/** + * Serializer for [UpstreamOptionDto] that handles the [io.getstream.chat.android.client.api2.model.dto.ExtraDataDto] + * implementation. + */ +internal object UpstreamOptionDtoAdapter : + CustomObjectDtoAdapter(UpstreamOptionDto::class) { + + @FromJson + @Suppress("UNUSED_PARAMETER") + fun fromJson(jsonReader: JsonReader): UpstreamOptionDto = error("Can't parse this from Json") + + @ToJson + fun toJson( + jsonWriter: JsonWriter, + option: UpstreamOptionDto?, + mapAdapter: JsonAdapter>, + optionAdapter: JsonAdapter, + ) = serializeWithExtraData(jsonWriter, option, mapAdapter, optionAdapter) +} diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt index 6ab0261fad2..a3fd45cb532 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt @@ -40,9 +40,9 @@ import io.getstream.chat.android.client.api2.model.dto.DownstreamMessageDto import io.getstream.chat.android.client.api2.model.dto.DownstreamModerationDetailsDto import io.getstream.chat.android.client.api2.model.dto.DownstreamModerationDto import io.getstream.chat.android.client.api2.model.dto.DownstreamMuteDto -import io.getstream.chat.android.client.api2.model.dto.DownstreamOptionDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPendingMessageDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPollDto +import io.getstream.chat.android.client.api2.model.dto.DownstreamPollOptionDto import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionDto import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionGroupDto import io.getstream.chat.android.client.api2.model.dto.DownstreamReminderDto @@ -1032,7 +1032,7 @@ internal object Mother { maxVotesAllowed: Int = randomInt(), allowUserSuggestedOptions: Boolean = randomBoolean(), allowAnswers: Boolean = randomBoolean(), - options: List = listOf(randomDownstreamOptionDto()), + options: List = listOf(randomDownstreamOptionDto()), voteCountsByOption: Map = emptyMap(), latestVotesByOption: Map> = emptyMap(), latestAnswers: List = listOf(randomAnswerDownstreamVoteDto()), @@ -1042,7 +1042,9 @@ internal object Mother { ownVotes: List = listOf(randomDownstreamVoteDto()), updatedAt: Date = randomDate(), voteCount: Int = randomInt(), + answersCount: Int = randomInt(), isClosed: Boolean = randomBoolean(), + extraData: Map = randomExtraData(1), ): DownstreamPollDto = DownstreamPollDto( id = id, name = name, @@ -1062,15 +1064,19 @@ internal object Mother { own_votes = ownVotes, updated_at = updatedAt, vote_count = voteCount, + answers_count = answersCount, is_closed = isClosed, + extraData = extraData, ) fun randomDownstreamOptionDto( id: String = randomString(), text: String = randomString(), - ): DownstreamOptionDto = DownstreamOptionDto( + extraData: Map = randomExtraData(1), + ): DownstreamPollOptionDto = DownstreamPollOptionDto( id = id, text = text, + extraData = extraData, ) fun randomDownstreamVoteDto( 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 39b3d91f4b2..be31a0fe09e 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 @@ -43,6 +43,7 @@ import io.getstream.chat.android.client.api2.model.requests.AcceptInviteRequest import io.getstream.chat.android.client.api2.model.requests.AddDeviceRequest import io.getstream.chat.android.client.api2.model.requests.BanUserRequest import io.getstream.chat.android.client.api2.model.requests.BlockUserRequest +import io.getstream.chat.android.client.api2.model.requests.CreatePollRequest import io.getstream.chat.android.client.api2.model.requests.FlagMessageRequest import io.getstream.chat.android.client.api2.model.requests.FlagUserRequest import io.getstream.chat.android.client.api2.model.requests.GuestUserRequest @@ -55,7 +56,6 @@ import io.getstream.chat.android.client.api2.model.requests.PartialUpdateMessage import io.getstream.chat.android.client.api2.model.requests.PartialUpdateThreadRequest import io.getstream.chat.android.client.api2.model.requests.PartialUpdateUsersRequest import io.getstream.chat.android.client.api2.model.requests.PinnedMessagesRequest -import io.getstream.chat.android.client.api2.model.requests.PollRequest import io.getstream.chat.android.client.api2.model.requests.PollUpdateRequest import io.getstream.chat.android.client.api2.model.requests.PollVoteRequest import io.getstream.chat.android.client.api2.model.requests.QueryBannedUsersRequest @@ -2180,18 +2180,24 @@ internal class MoshiChatApiTest { val pollConfig = randomPollConfig() val result = sut.createPoll(pollConfig).await() // then - val expectedBody = PollRequest( + val expectedBody = CreatePollRequest( name = pollConfig.name, description = pollConfig.description, - options = pollConfig.options.map(::UpstreamOptionDto), + options = pollConfig.options.map { + UpstreamOptionDto( + text = it.text, + extraData = it.extraData, + ) + }, voting_visibility = when (pollConfig.votingVisibility) { - VotingVisibility.PUBLIC -> PollRequest.VOTING_VISIBILITY_PUBLIC - VotingVisibility.ANONYMOUS -> PollRequest.VOTING_VISIBILITY_ANONYMOUS + VotingVisibility.PUBLIC -> CreatePollRequest.VOTING_VISIBILITY_PUBLIC + VotingVisibility.ANONYMOUS -> CreatePollRequest.VOTING_VISIBILITY_ANONYMOUS }, enforce_unique_vote = pollConfig.enforceUniqueVote, max_votes_allowed = pollConfig.maxVotesAllowed, allow_user_suggested_options = pollConfig.allowUserSuggestedOptions, allow_answers = pollConfig.allowAnswers, + extraData = pollConfig.extraData, ) result `should be instance of` expected verify(api, times(1)).createPoll(expectedBody) diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt index 0719c1a97ca..a957da02471 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt @@ -382,13 +382,14 @@ internal class DomainMappingTest { name = pollDto.name, description = pollDto.description, options = options.map { - Option(it.id, it.text) + Option(it.id, it.text, it.extraData ?: emptyMap()) }, votingVisibility = VotingVisibility.PUBLIC, enforceUniqueVote = pollDto.enforce_unique_vote, maxVotesAllowed = pollDto.max_votes_allowed ?: 1, allowUserSuggestedOptions = pollDto.allow_user_suggested_options, allowAnswers = pollDto.allow_answers, + voteCount = pollDto.vote_count, voteCountsByOption = pollDto.vote_counts_by_option ?: emptyMap(), votes = listOf( Vote( @@ -420,7 +421,8 @@ internal class DomainMappingTest { ), createdAt = pollDto.created_at, updatedAt = pollDto.updated_at, - closed = pollDto.is_closed, + closed = pollDto.is_closed ?: false, + answersCount = pollDto.answers_count, answers = listOf( Answer( id = answer.id, @@ -431,8 +433,10 @@ internal class DomainMappingTest { user = with(sut) { answer.user?.toDomain() }, ), ), + createdBy = with(sut) { pollDto.created_by?.toDomain() }, + extraData = pollDto.extraData ?: emptyMap(), ) - poll shouldBeEqualTo expected + Assertions.assertEquals(expected, poll) } @Test diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/extensions/internal/PollExtensionsTests.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/extensions/internal/PollExtensionsTests.kt index ad4488cad5e..2f2c88ee24a 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/extensions/internal/PollExtensionsTests.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/extensions/internal/PollExtensionsTests.kt @@ -80,13 +80,16 @@ internal class PollExtensionsTests { maxVotesAllowed = 1, allowUserSuggestedOptions = false, allowAnswers = true, + voteCount = 2, voteCountsByOption = mapOf("option1" to 1, "option2" to 1), votes = listOf(vote1, vote2), ownVotes = listOf(vote1), createdAt = now, updatedAt = now, closed = false, + answersCount = 1, answers = listOf(answer1), + createdBy = user1, ) @Test diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/CreatePollRequestAdapterTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/CreatePollRequestAdapterTest.kt new file mode 100644 index 00000000000..9ce311d3971 --- /dev/null +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/CreatePollRequestAdapterTest.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014-2025 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.getstream.chat.android.client.parser2 + +import io.getstream.chat.android.client.parser2.testdata.PollDtoTestData +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test + +internal class CreatePollRequestAdapterTest { + private val parser = ParserFactory.createMoshiChatParser() + + @Test + fun `Serialize CreatePollRequest with custom fields`() { + val json = parser.toJson(PollDtoTestData.createPollRequest) + Assertions.assertEquals(PollDtoTestData.createPollRequestJson, json) + } + + @Test + fun `Serialize CreatePollRequest without custom fields`() { + val json = parser.toJson(PollDtoTestData.createPollRequestWithoutExtraData) + Assertions.assertEquals(PollDtoTestData.createPollRequestJsonWithoutExtraData, json) + } +} diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollDtoAdapterTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollDtoAdapterTest.kt new file mode 100644 index 00000000000..270ac364b75 --- /dev/null +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollDtoAdapterTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014-2025 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.getstream.chat.android.client.parser2 + +import io.getstream.chat.android.client.api2.model.dto.DownstreamPollDto +import io.getstream.chat.android.client.parser2.testdata.PollDtoTestData +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test + +internal class DownstreamPollDtoAdapterTest { + private val parser = ParserFactory.createMoshiChatParser() + + @Test + fun `Deserialize JSON poll with custom fields`() { + val poll = parser.fromJson( + PollDtoTestData.downstreamPollJson, + DownstreamPollDto::class.java, + ) + Assertions.assertEquals(PollDtoTestData.downstreamPoll, poll) + } + + @Test + fun `Deserialize JSON poll without custom fields`() { + val poll = parser.fromJson( + PollDtoTestData.downstreamPollJsonWithoutExtraData, + DownstreamPollDto::class.java, + ) + Assertions.assertEquals(PollDtoTestData.downstreamPollWithoutExtraData, poll) + } +} diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollOptionDtoAdapterTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollOptionDtoAdapterTest.kt new file mode 100644 index 00000000000..b563141479f --- /dev/null +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollOptionDtoAdapterTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014-2025 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.getstream.chat.android.client.parser2 + +import io.getstream.chat.android.client.api2.model.dto.DownstreamPollOptionDto +import io.getstream.chat.android.client.parser2.testdata.PollDtoTestData +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test + +internal class DownstreamPollOptionDtoAdapterTest { + private val parser = ParserFactory.createMoshiChatParser() + + @Test + fun `Deserialize JSON poll option with custom fields`() { + val option = parser.fromJson( + PollDtoTestData.downstreamPollOptionJson, + DownstreamPollOptionDto::class.java, + ) + Assertions.assertEquals(PollDtoTestData.downstreamPollOption, option) + } + + @Test + fun `Deserialize JSON poll option without custom fields`() { + val option = parser.fromJson( + PollDtoTestData.downstreamPollOptionJsonWithoutExtraData, + DownstreamPollOptionDto::class.java, + ) + Assertions.assertEquals(PollDtoTestData.downstreamPollOptionWithoutExtraData, option) + } +} diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/UpstreamOptionDtoAdapterTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/UpstreamOptionDtoAdapterTest.kt new file mode 100644 index 00000000000..6465646960e --- /dev/null +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/UpstreamOptionDtoAdapterTest.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014-2025 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.getstream.chat.android.client.parser2 + +import io.getstream.chat.android.client.parser2.testdata.PollDtoTestData +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test + +internal class UpstreamOptionDtoAdapterTest { + private val parser = ParserFactory.createMoshiChatParser() + + @Test + fun `Serialize UpstreamOptionDto with custom fields`() { + val json = parser.toJson(PollDtoTestData.upstreamOption) + Assertions.assertEquals(PollDtoTestData.upstreamOptionJson, json) + } + + @Test + fun `Serialize UpstreamOptionDto without custom fields`() { + val json = parser.toJson(PollDtoTestData.upstreamOptionWithoutExtraData) + Assertions.assertEquals(PollDtoTestData.upstreamOptionJsonWithoutExtraData, json) + } +} diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/PollDtoTestData.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/PollDtoTestData.kt new file mode 100644 index 00000000000..ddebf77c904 --- /dev/null +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/testdata/PollDtoTestData.kt @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2014-2025 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.getstream.chat.android.client.parser2.testdata + +import io.getstream.chat.android.client.api2.model.dto.DownstreamPollDto +import io.getstream.chat.android.client.api2.model.dto.DownstreamPollOptionDto +import io.getstream.chat.android.client.api2.model.requests.CreatePollRequest +import io.getstream.chat.android.client.api2.model.requests.UpstreamOptionDto +import org.intellij.lang.annotations.Language +import java.util.Date + +internal object PollDtoTestData { + + // DownstreamPollOptionDto Test Data + + @Language("JSON") + val downstreamPollOptionJson = + """{ + "id": "option1", + "text": "Option 1", + "extraData": { + "key1": "value1", + "key2": true + }, + "customKey": "customValue" + }""" + + val downstreamPollOption = DownstreamPollOptionDto( + id = "option1", + text = "Option 1", + extraData = mapOf( + "extraData" to mapOf( + "key1" to "value1", + "key2" to true, + ), + "customKey" to "customValue", + ), + ) + + @Language("JSON") + val downstreamPollOptionJsonWithoutExtraData = + """{ + "id": "option2", + "text": "Option 2" + }""" + + val downstreamPollOptionWithoutExtraData = DownstreamPollOptionDto( + id = "option2", + text = "Option 2", + extraData = emptyMap(), + ) + + // DownstreamPollDto Test Data + + @Language("JSON") + val downstreamPollJson = + """{ + "allow_answers": true, + "allow_user_suggested_options": false, + "answers_count": 5, + "created_at": "2020-06-10T11:04:31.000Z", + "created_by": ${UserDtoTestData.downstreamJson}, + "created_by_id": "userId", + "description": "Poll description", + "enforce_unique_vote": true, + "id": "poll1", + "is_closed": false, + "latest_answers": [], + "latest_votes_by_option": {}, + "max_votes_allowed": 1, + "name": "Poll Name", + "options": [ + { + "id": "option1", + "text": "Option 1" + } + ], + "own_votes": [], + "updated_at": "2020-06-10T11:04:31.588Z", + "vote_count": 10, + "vote_counts_by_option": { + "option1": 10 + }, + "voting_visibility": "public", + "extraData": { + "poll_key": "poll_value" + }, + "customPollKey": "customPollValue" + }""" + + val downstreamPoll = DownstreamPollDto( + allow_answers = true, + allow_user_suggested_options = false, + answers_count = 5, + created_at = Date(1591787071000), + created_by = UserDtoTestData.downstreamUser, + created_by_id = "userId", + description = "Poll description", + enforce_unique_vote = true, + id = "poll1", + is_closed = false, + latest_answers = emptyList(), + latest_votes_by_option = emptyMap(), + max_votes_allowed = 1, + name = "Poll Name", + options = listOf( + DownstreamPollOptionDto( + id = "option1", + text = "Option 1", + extraData = emptyMap(), + ), + ), + own_votes = emptyList(), + updated_at = Date(1591787071588), + vote_count = 10, + vote_counts_by_option = mapOf("option1" to 10), + voting_visibility = "public", + extraData = mapOf( + "extraData" to mapOf( + "poll_key" to "poll_value", + ), + "customPollKey" to "customPollValue", + ), + ) + + @Language("JSON") + val downstreamPollJsonWithoutExtraData = + """{ + "allow_answers": false, + "allow_user_suggested_options": true, + "answers_count": 0, + "created_at": "2020-06-10T11:04:31.000Z", + "created_by": ${UserDtoTestData.downstreamJson}, + "created_by_id": "userId", + "description": "Simple poll", + "enforce_unique_vote": false, + "id": "poll2", + "is_closed": null, + "latest_answers": null, + "latest_votes_by_option": null, + "max_votes_allowed": null, + "name": "Simple Poll", + "options": [], + "own_votes": [], + "updated_at": "2020-06-10T11:04:31.588Z", + "vote_count": 0, + "vote_counts_by_option": null, + "voting_visibility": null + }""" + + val downstreamPollWithoutExtraData = DownstreamPollDto( + allow_answers = false, + allow_user_suggested_options = true, + answers_count = 0, + created_at = Date(1591787071000), + created_by = UserDtoTestData.downstreamUser, + created_by_id = "userId", + description = "Simple poll", + enforce_unique_vote = false, + id = "poll2", + is_closed = null, + latest_answers = null, + latest_votes_by_option = null, + max_votes_allowed = null, + name = "Simple Poll", + options = emptyList(), + own_votes = emptyList(), + updated_at = Date(1591787071588), + vote_count = 0, + vote_counts_by_option = null, + voting_visibility = null, + extraData = emptyMap(), + ) + + // UpstreamOptionDto Test Data + + @Language("JSON") + val upstreamOptionJson = + """{ + "text": "option", + "customKey1": "customValue1", + "customKey2": 42.0 + }""".withoutWhitespace() + + val upstreamOption = UpstreamOptionDto( + text = "option", + extraData = mapOf( + "customKey1" to "customValue1", + "customKey2" to 42.0, // JSON numbers are parsed as Double + ), + ) + + @Language("JSON") + val upstreamOptionJsonWithoutExtraData = + """{ + "text": "option" + }""".withoutWhitespace() + + val upstreamOptionWithoutExtraData = UpstreamOptionDto( + text = "option", + extraData = emptyMap(), + ) + + // CreatePollRequest Test Data + + @Language("JSON") + val createPollRequestJson = + """{ + "allow_answers": true, + "allow_user_suggested_options": false, + "description": "description", + "enforce_unique_vote": true, + "max_votes_allowed": 1, + "name": "poll", + "options": [ + { + "text": "option" + } + ], + "voting_visibility": "public", + "customRequestKey": "customRequestValue" + }""".withoutWhitespace() + + val createPollRequest = CreatePollRequest( + allow_answers = true, + allow_user_suggested_options = false, + description = "description", + enforce_unique_vote = true, + max_votes_allowed = 1, + name = "poll", + options = listOf( + UpstreamOptionDto( + text = "option", + extraData = emptyMap(), + ), + ), + voting_visibility = "public", + extraData = mapOf( + "customRequestKey" to "customRequestValue", + ), + ) + + @Language("JSON") + val createPollRequestJsonWithoutExtraData = + """{ + "allow_answers": false, + "allow_user_suggested_options": false, + "description": "", + "enforce_unique_vote": false, + "max_votes_allowed": 1, + "name": "poll", + "options": [], + "voting_visibility": "public" + }""".withoutWhitespace() + + val createPollRequestWithoutExtraData = CreatePollRequest( + allow_answers = false, + allow_user_suggested_options = false, + description = "", + enforce_unique_vote = false, + max_votes_allowed = 1, + name = "poll", + options = emptyList(), + voting_visibility = "public", + extraData = emptyMap(), + ) +} diff --git a/stream-chat-android-core/api/stream-chat-android-core.api b/stream-chat-android-core/api/stream-chat-android-core.api index 34ff01fb2f9..82099b0b513 100644 --- a/stream-chat-android-core/api/stream-chat-android-core.api +++ b/stream-chat-android-core/api/stream-chat-android-core.api @@ -1635,12 +1635,15 @@ public final class io/getstream/chat/android/models/NotInFilterObject : io/getst } public final class io/getstream/chat/android/models/Option { - public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/lang/String; - public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lio/getstream/chat/android/models/Option; - public static synthetic fun copy$default (Lio/getstream/chat/android/models/Option;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lio/getstream/chat/android/models/Option; + public final fun component3 ()Ljava/util/Map; + public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)Lio/getstream/chat/android/models/Option; + public static synthetic fun copy$default (Lio/getstream/chat/android/models/Option;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)Lio/getstream/chat/android/models/Option; public fun equals (Ljava/lang/Object;)Z + public final fun getExtraData ()Ljava/util/Map; public final fun getId ()Ljava/lang/String; public final fun getText ()Ljava/lang/String; public fun hashCode ()I @@ -1678,17 +1681,21 @@ public final class io/getstream/chat/android/models/PendingMessage$Builder { } public final class io/getstream/chat/android/models/Poll { - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lio/getstream/chat/android/models/VotingVisibility;ZIZZLjava/util/Map;Ljava/util/List;Ljava/util/List;Ljava/util/Date;Ljava/util/Date;ZLjava/util/List;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lio/getstream/chat/android/models/VotingVisibility;ZIZZLjava/util/Map;Ljava/util/List;Ljava/util/List;Ljava/util/Date;Ljava/util/Date;ZLjava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lio/getstream/chat/android/models/VotingVisibility;ZIZZILjava/util/Map;Ljava/util/List;Ljava/util/List;Ljava/util/Date;Ljava/util/Date;ZILjava/util/List;Lio/getstream/chat/android/models/User;Ljava/util/Map;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lio/getstream/chat/android/models/VotingVisibility;ZIZZILjava/util/Map;Ljava/util/List;Ljava/util/List;Ljava/util/Date;Ljava/util/Date;ZILjava/util/List;Lio/getstream/chat/android/models/User;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; - public final fun component10 ()Ljava/util/Map; - public final fun component11 ()Ljava/util/List; + public final fun component10 ()I + public final fun component11 ()Ljava/util/Map; public final fun component12 ()Ljava/util/List; - public final fun component13 ()Ljava/util/Date; + public final fun component13 ()Ljava/util/List; public final fun component14 ()Ljava/util/Date; - public final fun component15 ()Z - public final fun component16 ()Ljava/util/List; + public final fun component15 ()Ljava/util/Date; + public final fun component16 ()Z + public final fun component17 ()I + public final fun component18 ()Ljava/util/List; + public final fun component19 ()Lio/getstream/chat/android/models/User; public final fun component2 ()Ljava/lang/String; + public final fun component20 ()Ljava/util/Map; public final fun component3 ()Ljava/lang/String; public final fun component4 ()Ljava/util/List; public final fun component5 ()Lio/getstream/chat/android/models/VotingVisibility; @@ -1696,22 +1703,26 @@ public final class io/getstream/chat/android/models/Poll { public final fun component7 ()I public final fun component8 ()Z public final fun component9 ()Z - public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lio/getstream/chat/android/models/VotingVisibility;ZIZZLjava/util/Map;Ljava/util/List;Ljava/util/List;Ljava/util/Date;Ljava/util/Date;ZLjava/util/List;)Lio/getstream/chat/android/models/Poll; - public static synthetic fun copy$default (Lio/getstream/chat/android/models/Poll;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lio/getstream/chat/android/models/VotingVisibility;ZIZZLjava/util/Map;Ljava/util/List;Ljava/util/List;Ljava/util/Date;Ljava/util/Date;ZLjava/util/List;ILjava/lang/Object;)Lio/getstream/chat/android/models/Poll; + public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lio/getstream/chat/android/models/VotingVisibility;ZIZZILjava/util/Map;Ljava/util/List;Ljava/util/List;Ljava/util/Date;Ljava/util/Date;ZILjava/util/List;Lio/getstream/chat/android/models/User;Ljava/util/Map;)Lio/getstream/chat/android/models/Poll; + public static synthetic fun copy$default (Lio/getstream/chat/android/models/Poll;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lio/getstream/chat/android/models/VotingVisibility;ZIZZILjava/util/Map;Ljava/util/List;Ljava/util/List;Ljava/util/Date;Ljava/util/Date;ZILjava/util/List;Lio/getstream/chat/android/models/User;Ljava/util/Map;ILjava/lang/Object;)Lio/getstream/chat/android/models/Poll; public fun equals (Ljava/lang/Object;)Z public final fun getAllowAnswers ()Z public final fun getAllowUserSuggestedOptions ()Z public final fun getAnswers ()Ljava/util/List; + public final fun getAnswersCount ()I public final fun getClosed ()Z public final fun getCreatedAt ()Ljava/util/Date; + public final fun getCreatedBy ()Lio/getstream/chat/android/models/User; public final fun getDescription ()Ljava/lang/String; public final fun getEnforceUniqueVote ()Z + public final fun getExtraData ()Ljava/util/Map; public final fun getId ()Ljava/lang/String; public final fun getMaxVotesAllowed ()I public final fun getName ()Ljava/lang/String; public final fun getOptions ()Ljava/util/List; public final fun getOwnVotes ()Ljava/util/List; public final fun getUpdatedAt ()Ljava/util/Date; + public final fun getVoteCount ()I public final fun getVoteCountsByOption ()Ljava/util/Map; public final fun getVotes ()Ljava/util/List; public final fun getVotes (Lio/getstream/chat/android/models/Option;)Ljava/util/List; @@ -1723,6 +1734,8 @@ public final class io/getstream/chat/android/models/Poll { public final class io/getstream/chat/android/models/PollConfig { public fun (Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lio/getstream/chat/android/models/VotingVisibility;ZIZZ)V public synthetic fun (Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lio/getstream/chat/android/models/VotingVisibility;ZIZZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lio/getstream/chat/android/models/VotingVisibility;ZIZZLjava/util/Map;)V + public synthetic fun (Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lio/getstream/chat/android/models/VotingVisibility;ZIZZLjava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/util/List; public final fun component3 ()Ljava/lang/String; @@ -1731,13 +1744,15 @@ public final class io/getstream/chat/android/models/PollConfig { public final fun component6 ()I public final fun component7 ()Z public final fun component8 ()Z - public final fun copy (Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lio/getstream/chat/android/models/VotingVisibility;ZIZZ)Lio/getstream/chat/android/models/PollConfig; - public static synthetic fun copy$default (Lio/getstream/chat/android/models/PollConfig;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lio/getstream/chat/android/models/VotingVisibility;ZIZZILjava/lang/Object;)Lio/getstream/chat/android/models/PollConfig; + public final fun component9 ()Ljava/util/Map; + public final fun copy (Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lio/getstream/chat/android/models/VotingVisibility;ZIZZLjava/util/Map;)Lio/getstream/chat/android/models/PollConfig; + public static synthetic fun copy$default (Lio/getstream/chat/android/models/PollConfig;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lio/getstream/chat/android/models/VotingVisibility;ZIZZLjava/util/Map;ILjava/lang/Object;)Lio/getstream/chat/android/models/PollConfig; public fun equals (Ljava/lang/Object;)Z public final fun getAllowAnswers ()Z public final fun getAllowUserSuggestedOptions ()Z public final fun getDescription ()Ljava/lang/String; public final fun getEnforceUniqueVote ()Z + public final fun getExtraData ()Ljava/util/Map; public final fun getMaxVotesAllowed ()I public final fun getName ()Ljava/lang/String; public final fun getOptions ()Ljava/util/List; @@ -1746,6 +1761,20 @@ public final class io/getstream/chat/android/models/PollConfig { public fun toString ()Ljava/lang/String; } +public final class io/getstream/chat/android/models/PollOption { + public fun (Ljava/lang/String;Ljava/util/Map;)V + public synthetic fun (Ljava/lang/String;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/util/Map; + public final fun copy (Ljava/lang/String;Ljava/util/Map;)Lio/getstream/chat/android/models/PollOption; + public static synthetic fun copy$default (Lio/getstream/chat/android/models/PollOption;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)Lio/getstream/chat/android/models/PollOption; + public fun equals (Ljava/lang/Object;)Z + public final fun getExtraData ()Ljava/util/Map; + public final fun getText ()Ljava/lang/String; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + public final class io/getstream/chat/android/models/PushMessage { public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V public final fun component1 ()Ljava/lang/String; diff --git a/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/Poll.kt b/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/Poll.kt index 6e120593574..be080128559 100644 --- a/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/Poll.kt +++ b/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/Poll.kt @@ -32,13 +32,17 @@ import java.util.Date * @property maxVotesAllowed The maximum number of votes a user can cast. * @property allowUserSuggestedOptions If set to true, users can suggest new options. * @property allowAnswers If set to true, users can vote. + * @property voteCount The total number of votes cast in the poll. * @property voteCountsByOption The number of votes for each option. * @property votes The list of votes. * @property ownVotes The list of votes cast by the current user. * @property createdAt The creation date of the poll. * @property updatedAt The last update date of the poll. * @property closed If set to true, the poll is closed and no more votes can be cast. + * @property answersCount The total number of answers in the poll. * @property answers The list of poll answers. + * @property createdBy The user who created the poll. This property is optional and might be null. + * @property extraData Any additional data associated with the poll. */ @Immutable public data class Poll( @@ -51,13 +55,17 @@ public data class Poll( val maxVotesAllowed: Int, val allowUserSuggestedOptions: Boolean, val allowAnswers: Boolean, + val voteCount: Int, val voteCountsByOption: Map, val votes: List, val ownVotes: List, val createdAt: Date, val updatedAt: Date, val closed: Boolean, + val answersCount: Int, val answers: List = emptyList(), + val createdBy: User?, + val extraData: Map = emptyMap(), ) { /** @@ -94,11 +102,13 @@ public data class Answer( * * @property id The unique identifier of the option. * @property text The text of the option. + * @property extraData Any additional data associated with the option. */ @Immutable public data class Option( val id: String, val text: String, + val extraData: Map = emptyMap(), ) /** @@ -113,16 +123,63 @@ public data class Option( * @property maxVotesAllowed The maximum number of votes a user can cast. Default is 1. * @property allowUserSuggestedOptions If set to true, users can suggest new options. Default is false. * @property allowAnswers If set to true, users can send answers. Default is false. + * @property extraData Any additional data associated with the poll. */ public data class PollConfig( val name: String, - val options: List, + val options: List, val description: String = "", val votingVisibility: VotingVisibility = VotingVisibility.PUBLIC, val enforceUniqueVote: Boolean = true, val maxVotesAllowed: Int = 1, val allowUserSuggestedOptions: Boolean = false, val allowAnswers: Boolean = false, + val extraData: Map = emptyMap(), +) { + + /** + * Alternative constructor to create a PollConfig with a list of option texts. + * + * @param name The name of the poll. + * @param options The list of option texts for the poll. + * @param description The description of the poll. + * @param votingVisibility The visibility of the votes. Default is [VotingVisibility.PUBLIC]. + * @param enforceUniqueVote If set to true, a user can only vote once. Default is true. + * @param maxVotesAllowed The maximum number of votes a user can cast. Default is 1. + * @param allowUserSuggestedOptions If set to true, users can suggest new options. Default is false. + * @param allowAnswers If set to true, users can send answers. Default is false. + */ + public constructor( + name: String, + options: List, + description: String = "", + votingVisibility: VotingVisibility = VotingVisibility.PUBLIC, + enforceUniqueVote: Boolean = true, + maxVotesAllowed: Int = 1, + allowUserSuggestedOptions: Boolean = false, + allowAnswers: Boolean = false, + ) : this( + name = name, + options = options.map { PollOption(it) }, + description = description, + votingVisibility = votingVisibility, + enforceUniqueVote = enforceUniqueVote, + maxVotesAllowed = maxVotesAllowed, + allowUserSuggestedOptions = allowUserSuggestedOptions, + allowAnswers = allowAnswers, + extraData = emptyMap(), + ) +} + +/** + * Model representing the input required to create a poll option. + * + * @property text The text of the option. + * @property extraData Any additional data associated with the option. + */ +public data class PollOption( + val text: String, + val extraData: Map = emptyMap(), ) /** diff --git a/stream-chat-android-core/src/testFixtures/kotlin/io/getstream/chat/android/Mother.kt b/stream-chat-android-core/src/testFixtures/kotlin/io/getstream/chat/android/Mother.kt index 9e8ba0838fd..d77df001077 100644 --- a/stream-chat-android-core/src/testFixtures/kotlin/io/getstream/chat/android/Mother.kt +++ b/stream-chat-android-core/src/testFixtures/kotlin/io/getstream/chat/android/Mother.kt @@ -847,6 +847,7 @@ public fun randomPoll( votingVisibility: VotingVisibility = VotingVisibility.PUBLIC, enforceUniqueVote: Boolean = randomBoolean(), maxVotesAllowed: Int = positiveRandomInt(), + voteCount: Int = positiveRandomInt(), voteCountsByOption: Map = emptyMap(), allowUserSuggestedOptions: Boolean = randomBoolean(), allowAnswers: Boolean = randomBoolean(), @@ -856,7 +857,10 @@ public fun randomPoll( createdAt: Date = randomDate(), updatedAt: Date = randomDate(), closed: Boolean = randomBoolean(), + answersCount: Int = positiveRandomInt(), answers: List = emptyList(), + createdBy: User = randomUser(), + extraData: Map = randomExtraData(1), ): Poll = Poll( id = id, name = name, @@ -864,6 +868,7 @@ public fun randomPoll( votingVisibility = votingVisibility, enforceUniqueVote = enforceUniqueVote, maxVotesAllowed = maxVotesAllowed, + voteCount = voteCount, voteCountsByOption = voteCountsByOption, allowUserSuggestedOptions = allowUserSuggestedOptions, allowAnswers = allowAnswers, @@ -873,7 +878,10 @@ public fun randomPoll( createdAt = createdAt, updatedAt = updatedAt, closed = closed, + answersCount = answersCount, answers = answers, + extraData = extraData, + createdBy = createdBy, ) public fun randomPollOption( diff --git a/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/database/internal/ChatDatabase.kt b/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/database/internal/ChatDatabase.kt index d1c8e2b8454..1eae2a81c57 100644 --- a/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/database/internal/ChatDatabase.kt +++ b/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/database/internal/ChatDatabase.kt @@ -86,7 +86,7 @@ import io.getstream.chat.android.offline.repository.domain.user.internal.UserEnt ThreadOrderEntity::class, DraftMessageEntity::class, ], - version = 93, + version = 94, exportSchema = false, ) @TypeConverters( diff --git a/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/domain/message/internal/MessageMapper.kt b/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/domain/message/internal/MessageMapper.kt index 5aaf27a671a..e360a5088b4 100644 --- a/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/domain/message/internal/MessageMapper.kt +++ b/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/domain/message/internal/MessageMapper.kt @@ -243,15 +243,20 @@ internal fun Poll.toEntity(): PollEntity = PollEntity( maxVotesAllowed = maxVotesAllowed, allowUserSuggestedOptions = allowUserSuggestedOptions, allowAnswers = allowAnswers, + voteCount = voteCount, voteCountsByOption = voteCountsByOption, ownVotes = ownVotes.map { it.toEntity() }, closed = closed, + answersCount = answersCount, answers = answers.map { it.toEntity() }, + createdById = createdBy?.id, + extraData = extraData, ) internal fun Option.toEntity(): OptionEntity = OptionEntity( id = id, text = text, + extraData = extraData, ) internal fun Vote.toEntity(): VoteEntity = VoteEntity( @@ -292,15 +297,20 @@ internal suspend fun PollEntity.toModel( maxVotesAllowed = maxVotesAllowed, allowUserSuggestedOptions = allowUserSuggestedOptions, allowAnswers = allowAnswers, + voteCount = voteCount, voteCountsByOption = voteCountsByOption, ownVotes = ownVotes.map { it.toModel(getUser) }, closed = closed, + answersCount = answersCount, answers = answers.map { it.toModel(getUser) }, + createdBy = createdById?.let { getUser(it) }, + extraData = extraData, ) private fun OptionEntity.toModel(): Option = Option( id = id, text = text, + extraData = extraData, ) private suspend fun VoteEntity.toModel( diff --git a/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/domain/message/internal/Poll.kt b/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/domain/message/internal/Poll.kt index 7209835a86d..6de4a6e5577 100644 --- a/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/domain/message/internal/Poll.kt +++ b/stream-chat-android-offline/src/main/java/io/getstream/chat/android/offline/repository/domain/message/internal/Poll.kt @@ -34,19 +34,24 @@ internal class PollEntity( val maxVotesAllowed: Int, val allowUserSuggestedOptions: Boolean, val allowAnswers: Boolean, + val voteCount: Int, val voteCountsByOption: Map, val votes: List, val ownVotes: List, val createdAt: Date, val updatedAt: Date, val closed: Boolean, + val answersCount: Int, val answers: List, + val createdById: String?, + val extraData: Map, ) @JsonClass(generateAdapter = true) internal class OptionEntity( val id: String, val text: String, + val extraData: Map, ) @JsonClass(generateAdapter = true) diff --git a/stream-chat-android-previewdata/src/main/kotlin/io/getstream/chat/android/previewdata/PreviewPollData.kt b/stream-chat-android-previewdata/src/main/kotlin/io/getstream/chat/android/previewdata/PreviewPollData.kt index d1b45e69ffa..9958494dfb9 100644 --- a/stream-chat-android-previewdata/src/main/kotlin/io/getstream/chat/android/previewdata/PreviewPollData.kt +++ b/stream-chat-android-previewdata/src/main/kotlin/io/getstream/chat/android/previewdata/PreviewPollData.kt @@ -53,6 +53,7 @@ public object PreviewPollData { maxVotesAllowed = 1, allowUserSuggestedOptions = false, allowAnswers = true, + voteCount = 5, voteCountsByOption = mapOf( option1.id to 3, option2.id to 1, @@ -104,6 +105,8 @@ public object PreviewPollData { createdAt = Now, updatedAt = Now, closed = false, + answersCount = 0, + createdBy = null, ) } From 1d5c0aeff06adab2c50abf618d35ecba9cb1f94a Mon Sep 17 00:00:00 2001 From: VelikovPetar Date: Mon, 6 Oct 2025 15:53:16 +0200 Subject: [PATCH 02/19] Add `getPoll` operation. --- .../chat/android/client/ChatClient.kt | 64 +++++++++++-------- .../chat/android/client/api/ChatApi.kt | 3 + .../chat/android/client/api2/MoshiChatApi.kt | 4 ++ .../android/client/api2/endpoint/PollsApi.kt | 11 ++++ .../android/client/ChatClientPollsApiTests.kt | 26 ++++++++ .../android/client/api2/MoshiChatApiTest.kt | 17 +++++ .../client/api2/MoshiChatApiTestArguments.kt | 3 + 7 files changed, 101 insertions(+), 27 deletions(-) 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 805d2e2c2b0..376fc1e787c 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 @@ -1625,33 +1625,6 @@ internal constructor( ) } - /** - * Send a message with a poll to the given channel. - * - * @param channelType The channel type. ie messaging. - * @param channelId The channel id. ie 123. - * @param pollConfig The poll configuration. - * - * @return Executable async [Call] responsible for sending a poll. - */ - @CheckResult - public fun sendPoll( - channelType: String, - channelId: String, - pollConfig: PollConfig, - ): Call { - return api.createPoll(pollConfig) - .flatMap { poll -> - sendMessage( - channelType = channelType, - channelId = channelId, - Message( - extraData = mapOf("poll_id" to poll.id), - ), - ) - } - } - /** * Sends a static location message to the given channel. * @@ -1793,6 +1766,43 @@ internal constructor( } } } + /** + * Send a message with a poll to the given channel. + * + * @param channelType The channel type. ie messaging. + * @param channelId The channel id. ie 123. + * @param pollConfig The poll configuration. + * + * @return Executable async [Call] responsible for sending a poll. + */ + @CheckResult + public fun sendPoll( + channelType: String, + channelId: String, + pollConfig: PollConfig, + ): Call { + return api.createPoll(pollConfig) + .flatMap { poll -> + sendMessage( + channelType = channelType, + channelId = channelId, + Message( + extraData = mapOf("poll_id" to poll.id), + ), + ) + } + } + + /** + * Get a poll by id. + * + * @param pollId The poll id. + * @return Executable async [Call] responsible for fetching a poll. + */ + @CheckResult + public fun getPoll(pollId: String): Call { + return api.getPoll(pollId) + } @CheckResult public fun suggestPollOption( 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 c5002597b1b..f10b129f815 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 @@ -557,6 +557,9 @@ internal interface ChatApi { @CheckResult fun createPoll(pollConfig: PollConfig): Call + @CheckResult + fun getPoll(pollId: String): Call + @CheckResult fun suggestPollOption(pollId: String, option: String): Call