From 6116f9cd990ffc886887338526528bdb35c6b1b4 Mon Sep 17 00:00:00 2001 From: Ryan Hurst Date: Mon, 11 May 2026 17:09:59 -0400 Subject: [PATCH 1/3] Add configurable character limits and feature toggles for polls Introduces PollsConfig to control poll feature availability and enforce character limits on questions and options. Poll features (multiple votes, anonymous voting, suggest options, add comments) can now be hidden or preset with default values through ChatUI.pollsConfig or passed directly to CreatePollDialogFragment. --- .../io/getstream/chat/android/ui/ChatUI.kt | 10 +++ .../picker/poll/CreatePollDialogFragment.kt | 81 ++++++++++++++++++- .../picker/poll/CreatePollViewModel.kt | 11 +++ .../attachment/picker/poll/OptionsAdapter.kt | 17 ++++ .../attachment/picker/poll/PollsConfig.kt | 77 ++++++++++++++++++ 5 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt diff --git a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/ChatUI.kt b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/ChatUI.kt index f5815d7f59b..c7ff0c5b689 100644 --- a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/ChatUI.kt +++ b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/ChatUI.kt @@ -30,6 +30,7 @@ import io.getstream.chat.android.ui.common.helper.VideoHeadersProvider import io.getstream.chat.android.ui.common.images.internal.StreamImageLoader import io.getstream.chat.android.ui.common.images.resizing.StreamCdnImageResizing import io.getstream.chat.android.ui.common.utils.ChannelNameFormatter +import io.getstream.chat.android.ui.feature.messages.composer.attachment.picker.poll.PollsConfig import io.getstream.chat.android.ui.feature.messages.composer.attachment.preview.AttachmentPreviewFactoryManager import io.getstream.chat.android.ui.feature.messages.list.adapter.viewholder.attachment.AttachmentFactoryManager import io.getstream.chat.android.ui.feature.messages.list.adapter.viewholder.attachment.DefaultQuotedAttachmentMessageFactory @@ -273,6 +274,15 @@ public object ChatUI { @JvmStatic public var showOriginalTranslationEnabled: Boolean = false + /** + * Configuration for poll creation features. Controls which poll features are configurable by the user + * and their default values. + * + * @see PollsConfig + */ + @JvmStatic + public var pollsConfig: PollsConfig = PollsConfig.Default + /** * Provides a custom renderer for user avatars. */ diff --git a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment.kt b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment.kt index a1a9ebaf5d9..4ac76970bb5 100644 --- a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment.kt +++ b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment.kt @@ -17,6 +17,7 @@ package io.getstream.chat.android.ui.feature.messages.composer.attachment.picker.poll import android.os.Bundle +import android.text.InputFilter import android.view.LayoutInflater import android.view.MenuItem import android.view.View @@ -30,6 +31,7 @@ import androidx.core.widget.addTextChangedListener import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import io.getstream.chat.android.models.PollConfig +import io.getstream.chat.android.ui.ChatUI import io.getstream.chat.android.ui.R import io.getstream.chat.android.ui.common.utils.PollsConstants import io.getstream.chat.android.ui.databinding.StreamUiFragmentCreatePollBinding @@ -40,6 +42,8 @@ import kotlinx.coroutines.launch /** * Represent the bottom sheet dialog that allows users to pick attachments. + * + * Use [newInstance] to create an instance with optional [PollsConfig]. */ public class CreatePollDialogFragment : AppCompatDialogFragment() { @@ -47,8 +51,19 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { private val binding get() = _binding!! private var createPollDialogListener: CreatePollDialogListener? = null private val createPollViewModel: CreatePollViewModel by viewModels() + private val pollsConfig: PollsConfig by lazy { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { + arguments?.getParcelable(ARG_POLLS_CONFIG, PollsConfig::class.java) + } else { + @Suppress("DEPRECATION") + arguments?.getParcelable(ARG_POLLS_CONFIG) + } ?: ChatUI.pollsConfig + } private val optionsAdapter: OptionsAdapter by lazy { - OptionsAdapter { id, text -> createPollViewModel.onOptionTextChanged(id, text) } + OptionsAdapter( + optionTextLimit = pollsConfig.optionTextLimit, + onOptionChange = { id, text -> createPollViewModel.onOptionTextChanged(id, text) }, + ) } private lateinit var sendMenuItem: MenuItem @@ -76,11 +91,56 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { setupDialog() } + /** + * Configures the visibility and default values of poll features based on [pollsConfig]. + */ + private fun configurePollFeatures() { + // Configure multiple votes feature + createPollViewModel.setAllowMultipleVotes(pollsConfig.multipleVotes.defaultValue) + binding.multipleAnswersLabel.isVisible = pollsConfig.multipleVotes.configurable + binding.multipleAnswersSwitch.isVisible = pollsConfig.multipleVotes.configurable + if (pollsConfig.multipleVotes.configurable) { + binding.multipleAnswersSwitch.isChecked = pollsConfig.multipleVotes.defaultValue + binding.multipleAnswersCount.isVisible = pollsConfig.multipleVotes.defaultValue + } + + // Configure anonymous poll feature + createPollViewModel.setAnnonymousPoll(pollsConfig.anonymousPoll.defaultValue) + binding.anonymousPollLabel.isVisible = pollsConfig.anonymousPoll.configurable + binding.anonymousPollSwitch.isVisible = pollsConfig.anonymousPoll.configurable + if (pollsConfig.anonymousPoll.configurable) { + binding.anonymousPollSwitch.isChecked = pollsConfig.anonymousPoll.defaultValue + } + + // Configure suggest an option feature + createPollViewModel.setSuggestAnOption(pollsConfig.suggestAnOption.defaultValue) + binding.suggestAnOptionLabel.isVisible = pollsConfig.suggestAnOption.configurable + binding.suggestAnOptionSwitch.isVisible = pollsConfig.suggestAnOption.configurable + if (pollsConfig.suggestAnOption.configurable) { + binding.suggestAnOptionSwitch.isChecked = pollsConfig.suggestAnOption.defaultValue + } + + // Configure add a comment feature + createPollViewModel.setAllowAnswers(pollsConfig.addComments.defaultValue) + binding.addACommentLabel.isVisible = pollsConfig.addComments.configurable + binding.addACommentLabelSwitch.isVisible = pollsConfig.addComments.configurable + if (pollsConfig.addComments.configurable) { + binding.addACommentLabelSwitch.isChecked = pollsConfig.addComments.defaultValue + } + } + /** * Initializes the dialog. */ private fun setupDialog() { setupToolbar(binding.toolbar) + pollsConfig.questionTextLimit?.takeIf { it > 0 }?.let { limit -> + binding.question.filters = arrayOf(InputFilter.LengthFilter(limit)) + } + + // Configure poll feature visibility and default values based on pollsConfig + configurePollFeatures() + binding.multipleAnswersSwitch.setOnCheckedChangeListener { _, isChecked -> binding.multipleAnswersCount.isVisible = isChecked createPollViewModel.setAllowMultipleVotes(isChecked) @@ -97,6 +157,9 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { binding.suggestAnOptionSwitch.setOnCheckedChangeListener { _, isChecked -> createPollViewModel.setSuggestAnOption(isChecked) } + binding.addACommentLabelSwitch.setOnCheckedChangeListener { _, isChecked -> + createPollViewModel.setAllowAnswers(isChecked) + } binding.addOption.setOnClickListener { createPollViewModel.createOption() } @@ -158,15 +221,25 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { public companion object { public const val TAG: String = "create_poll_dialog_fragment" + private const val ARG_POLLS_CONFIG: String = "arg_polls_config" /** * Creates a new instance of [CreatePollDialogFragment]. * + * @param createPollDialogListener The listener for poll creation events. + * @param pollsConfig Optional configuration for poll features. Defaults to [ChatUI.pollsConfig]. * @return A new instance of [CreatePollDialogFragment]. */ - public fun newInstance(createPollDialogListener: CreatePollDialogListener): CreatePollDialogFragment { - return CreatePollDialogFragment() - .setCreatePollDialogListener(createPollDialogListener) + @JvmOverloads + public fun newInstance( + createPollDialogListener: CreatePollDialogListener, + pollsConfig: PollsConfig? = null, + ): CreatePollDialogFragment { + return CreatePollDialogFragment().apply { + arguments = Bundle().apply { + pollsConfig?.let { config -> putParcelable(ARG_POLLS_CONFIG, config as android.os.Parcelable) } + } + }.setCreatePollDialogListener(createPollDialogListener) } } diff --git a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollViewModel.kt b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollViewModel.kt index 26328e8a0a6..3240b306c68 100644 --- a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollViewModel.kt +++ b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollViewModel.kt @@ -46,6 +46,7 @@ public class CreatePollViewModel : ViewModel() { private val createPoll = MutableSharedFlow(extraBufferCapacity = 1) private var suggestAnOption = false private var annonymousPoll = false + private var allowAnswers = false private var allowMultipleVotes = MutableStateFlow(false) private var maxAnswers: MutableStateFlow = MutableStateFlow(null) @@ -102,6 +103,7 @@ public class CreatePollViewModel : ViewModel() { options = options.map { PollOption(text = it.text) }, votingVisibility = if (annonymousPoll) VotingVisibility.ANONYMOUS else VotingVisibility.PUBLIC, allowUserSuggestedOptions = suggestAnOption, + allowAnswers = allowAnswers, maxVotesAllowed = maxAnswers.takeIf { allowMultipleVotes } ?: 1, enforceUniqueVote = !allowMultipleVotes, ) @@ -213,4 +215,13 @@ public class CreatePollViewModel : ViewModel() { public fun setAnnonymousPoll(annonymousPoll: Boolean) { this.annonymousPoll = annonymousPoll } + + /** + * Set if the poll allows users to add answers/comments. + * + * @param allowAnswers True if the poll allows users to add answers/comments, false otherwise. + */ + public fun setAllowAnswers(allowAnswers: Boolean) { + this.allowAnswers = allowAnswers + } } diff --git a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/OptionsAdapter.kt b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/OptionsAdapter.kt index f6430e3b2a1..64b0325d3dc 100644 --- a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/OptionsAdapter.kt +++ b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/OptionsAdapter.kt @@ -17,6 +17,7 @@ package io.getstream.chat.android.ui.feature.messages.composer.attachment.picker.poll import android.text.Editable +import android.text.InputFilter import android.text.TextWatcher import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil @@ -27,9 +28,17 @@ import io.getstream.chat.android.ui.databinding.StreamUiPollOptionBinding import io.getstream.chat.android.ui.utils.extensions.streamThemeInflater public class OptionsAdapter( + private val optionTextLimit: Int?, private val onOptionChange: (id: Int, text: String) -> Unit, ) : ListAdapter(OptionDiffCallback) { + /** + * Builds an [OptionsAdapter] instance without providing option text limit. + * + * @param onOptionChange Callback invoked when the option text changes. + */ + public constructor(onOptionChange: (id: Int, text: String) -> Unit) : this(null, onOptionChange) + init { setHasStableIds(true) } @@ -39,6 +48,7 @@ public class OptionsAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionViewHolder = OptionViewHolder( parent = parent, + optionTextLimit = optionTextLimit, onOptionChange = onOptionChange, ) @@ -53,11 +63,18 @@ public class OptionsAdapter( parent, false, ), + private val optionTextLimit: Int?, private val onOptionChange: (id: Int, text: String) -> Unit, ) : RecyclerView.ViewHolder(binding.root) { private lateinit var pollAnswer: PollAnswer + init { + optionTextLimit?.let { limit -> + binding.option.filters = arrayOf(InputFilter.LengthFilter(limit)) + } + } + private val textWatcher = object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { /* no-op */ } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { /* no-op */ } diff --git a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt new file mode 100644 index 00000000000..91cef8ebaa8 --- /dev/null +++ b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt @@ -0,0 +1,77 @@ +/* + * 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.ui.feature.messages.composer.attachment.picker.poll + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +/** + * Configuration for individual poll entry feature. + * + * @param configurable Indicates whether the poll entry is configurable. When false, the UI element is hidden. + * @param defaultValue Indicates the default value of the poll entry. + */ +@Parcelize +public data class PollsEntryConfig( + val configurable: Boolean, + val defaultValue: Boolean, +) : Parcelable { + public companion object { + /** + * The default configuration for a poll entry. It will make it configurable and disabled by default. + */ + public val Default: PollsEntryConfig = PollsEntryConfig( + configurable = true, + defaultValue = false, + ) + + /** + * The feature should not be supported, so it is not configurable by the user and hidden from the UI. + */ + public val NotConfigurable: PollsEntryConfig = PollsEntryConfig( + configurable = false, + defaultValue = false, + ) + } +} + +/** + * The configuration for the various poll features. It determines if the user can or cannot enable certain poll features. + * + * @param multipleVotes Configuration for allowing multiple votes in a poll. + * @param anonymousPoll Configuration for enabling anonymous polls. + * @param suggestAnOption Configuration for allowing users to suggest options in a poll. + * @param addComments Configuration for adding comments to a poll. + * @param questionTextLimit Optional character limit for the poll question. Null means no limit. + * @param optionTextLimit Optional character limit for poll answer options. Null means no limit. + */ +@Parcelize +public data class PollsConfig( + val multipleVotes: PollsEntryConfig = PollsEntryConfig.Default, + val anonymousPoll: PollsEntryConfig = PollsEntryConfig.Default, + val suggestAnOption: PollsEntryConfig = PollsEntryConfig.Default, + val addComments: PollsEntryConfig = PollsEntryConfig.Default, + val questionTextLimit: Int? = null, + val optionTextLimit: Int? = null, +) : Parcelable { + public companion object { + /** + * The default configuration for polls. All features are configurable and disabled by default. + */ + public val Default: PollsConfig = PollsConfig() + } +} From a20a5d81a8d02adaac47fe181ca4d34d3a8ab475 Mon Sep 17 00:00:00 2001 From: Ryan Hurst Date: Wed, 13 May 2026 15:18:14 -0400 Subject: [PATCH 2/3] addressing pr comments --- .../picker/poll/CreatePollDialogFragment.kt | 29 +++++++------- .../picker/poll/PollFeatureConfig.kt | 34 ++++++++++++++++ .../attachment/picker/poll/PollsConfig.kt | 40 +++---------------- 3 files changed, 54 insertions(+), 49 deletions(-) create mode 100644 stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig.kt diff --git a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment.kt b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment.kt index 4ac76970bb5..c70bc72773b 100644 --- a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment.kt +++ b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment.kt @@ -25,6 +25,7 @@ import android.view.ViewGroup import androidx.appcompat.app.AppCompatDialogFragment import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat +import androidx.core.os.BundleCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.isVisible import androidx.core.widget.addTextChangedListener @@ -39,6 +40,7 @@ import io.getstream.chat.android.ui.utils.extensions.applyEdgeToEdgePadding import io.getstream.chat.android.ui.utils.extensions.streamThemeInflater import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import kotlin.jvm.java /** * Represent the bottom sheet dialog that allows users to pick attachments. @@ -52,11 +54,8 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { private var createPollDialogListener: CreatePollDialogListener? = null private val createPollViewModel: CreatePollViewModel by viewModels() private val pollsConfig: PollsConfig by lazy { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { - arguments?.getParcelable(ARG_POLLS_CONFIG, PollsConfig::class.java) - } else { - @Suppress("DEPRECATION") - arguments?.getParcelable(ARG_POLLS_CONFIG) + arguments?.let { + BundleCompat.getParcelable(it, ARG_POLLS_CONFIG, PollsConfig::class.java) } ?: ChatUI.pollsConfig } private val optionsAdapter: OptionsAdapter by lazy { @@ -89,6 +88,11 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { super.onViewCreated(view, savedInstanceState) binding.root.applyEdgeToEdgePadding(typeMask = WindowInsetsCompat.Type.systemBars()) setupDialog() + + if (savedInstanceState == null) { + // Configure poll feature visibility and default values based on pollsConfig + configurePollFeatures() + } } /** @@ -121,11 +125,11 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { } // Configure add a comment feature - createPollViewModel.setAllowAnswers(pollsConfig.addComments.defaultValue) - binding.addACommentLabel.isVisible = pollsConfig.addComments.configurable - binding.addACommentLabelSwitch.isVisible = pollsConfig.addComments.configurable - if (pollsConfig.addComments.configurable) { - binding.addACommentLabelSwitch.isChecked = pollsConfig.addComments.defaultValue + createPollViewModel.setAllowAnswers(pollsConfig.allowComments.defaultValue) + binding.addACommentLabel.isVisible = pollsConfig.allowComments.configurable + binding.addACommentLabelSwitch.isVisible = pollsConfig.allowComments.configurable + if (pollsConfig.allowComments.configurable) { + binding.addACommentLabelSwitch.isChecked = pollsConfig.allowComments.defaultValue } } @@ -138,9 +142,6 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { binding.question.filters = arrayOf(InputFilter.LengthFilter(limit)) } - // Configure poll feature visibility and default values based on pollsConfig - configurePollFeatures() - binding.multipleAnswersSwitch.setOnCheckedChangeListener { _, isChecked -> binding.multipleAnswersCount.isVisible = isChecked createPollViewModel.setAllowMultipleVotes(isChecked) @@ -237,7 +238,7 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { ): CreatePollDialogFragment { return CreatePollDialogFragment().apply { arguments = Bundle().apply { - pollsConfig?.let { config -> putParcelable(ARG_POLLS_CONFIG, config as android.os.Parcelable) } + pollsConfig?.let { config -> putParcelable(ARG_POLLS_CONFIG, config) } } }.setCreatePollDialogListener(createPollDialogListener) } diff --git a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig.kt b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig.kt new file mode 100644 index 00000000000..3a6b2364d11 --- /dev/null +++ b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig.kt @@ -0,0 +1,34 @@ +package io.getstream.chat.android.ui.feature.messages.composer.attachment.picker.poll + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +/** + * Configuration for individual poll entry feature. + * + * @param configurable Indicates whether the poll entry is configurable. When false, the UI element is hidden. + * @param defaultValue Indicates the default value of the poll entry. + */ +@Parcelize +public data class PollFeatureConfig( + val configurable: Boolean, + val defaultValue: Boolean, +) : Parcelable { + public companion object { + /** + * The default configuration for a poll entry. It will make it configurable and disabled by default. + */ + public val Default: PollFeatureConfig = PollFeatureConfig( + configurable = true, + defaultValue = false, + ) + + /** + * The feature should not be supported, so it is not configurable by the user and hidden from the UI. + */ + public val NotConfigurable: PollFeatureConfig = PollFeatureConfig( + configurable = false, + defaultValue = false, + ) + } +} \ No newline at end of file diff --git a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt index 91cef8ebaa8..152a745569a 100644 --- a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt +++ b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt @@ -19,52 +19,22 @@ package io.getstream.chat.android.ui.feature.messages.composer.attachment.picker import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Configuration for individual poll entry feature. - * - * @param configurable Indicates whether the poll entry is configurable. When false, the UI element is hidden. - * @param defaultValue Indicates the default value of the poll entry. - */ -@Parcelize -public data class PollsEntryConfig( - val configurable: Boolean, - val defaultValue: Boolean, -) : Parcelable { - public companion object { - /** - * The default configuration for a poll entry. It will make it configurable and disabled by default. - */ - public val Default: PollsEntryConfig = PollsEntryConfig( - configurable = true, - defaultValue = false, - ) - - /** - * The feature should not be supported, so it is not configurable by the user and hidden from the UI. - */ - public val NotConfigurable: PollsEntryConfig = PollsEntryConfig( - configurable = false, - defaultValue = false, - ) - } -} - /** * The configuration for the various poll features. It determines if the user can or cannot enable certain poll features. * * @param multipleVotes Configuration for allowing multiple votes in a poll. * @param anonymousPoll Configuration for enabling anonymous polls. * @param suggestAnOption Configuration for allowing users to suggest options in a poll. - * @param addComments Configuration for adding comments to a poll. + * @param allowComments Configuration for adding comments to a poll. * @param questionTextLimit Optional character limit for the poll question. Null means no limit. * @param optionTextLimit Optional character limit for poll answer options. Null means no limit. */ @Parcelize public data class PollsConfig( - val multipleVotes: PollsEntryConfig = PollsEntryConfig.Default, - val anonymousPoll: PollsEntryConfig = PollsEntryConfig.Default, - val suggestAnOption: PollsEntryConfig = PollsEntryConfig.Default, - val addComments: PollsEntryConfig = PollsEntryConfig.Default, + val multipleVotes: PollFeatureConfig = PollFeatureConfig.Default, + val anonymousPoll: PollFeatureConfig = PollFeatureConfig.Default, + val suggestAnOption: PollFeatureConfig = PollFeatureConfig.Default, + val allowComments: PollFeatureConfig = PollFeatureConfig.Default, val questionTextLimit: Int? = null, val optionTextLimit: Int? = null, ) : Parcelable { From 997b5ed743afb4178941dde3688d4ade58b6ea21 Mon Sep 17 00:00:00 2001 From: Ryan Hurst Date: Thu, 14 May 2026 13:49:25 -0400 Subject: [PATCH 3/3] 1. Detekt - Fixed the MaxLineLength violation in PollsConfig.kt:23 by breaking the long comment line 2. Spotless - Applied formatting fixes (added license header to PollFeatureConfig.kt) 3. API Check - Regenerated the API dump file --- .../api/stream-chat-android-ui-components.api | 79 ++++++++++++++++++- .../picker/poll/PollFeatureConfig.kt | 18 ++++- .../attachment/picker/poll/PollsConfig.kt | 3 +- 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/stream-chat-android-ui-components/api/stream-chat-android-ui-components.api b/stream-chat-android-ui-components/api/stream-chat-android-ui-components.api index ca0708e9f2c..39709ebaf34 100644 --- a/stream-chat-android-ui-components/api/stream-chat-android-ui-components.api +++ b/stream-chat-android-ui-components/api/stream-chat-android-ui-components.api @@ -19,6 +19,7 @@ public final class io/getstream/chat/android/ui/ChatUI { public static final fun getMessageTextTransformer ()Lio/getstream/chat/android/ui/helper/transformer/ChatMessageTextTransformer; public static final fun getMimeTypeIconProvider ()Lio/getstream/chat/android/ui/helper/MimeTypeIconProvider; public static final fun getNavigator ()Lio/getstream/chat/android/ui/navigation/ChatNavigator; + public static final fun getPollsConfig ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig; public static final fun getQuotedAttachmentFactoryManager ()Lio/getstream/chat/android/ui/feature/messages/list/adapter/viewholder/attachment/QuotedAttachmentFactoryManager; public static final fun getReactionPushEmojiFactory ()Lio/getstream/chat/android/ui/common/helper/ReactionPushEmojiFactory; public static final fun getShowOriginalTranslationEnabled ()Z @@ -48,6 +49,7 @@ public final class io/getstream/chat/android/ui/ChatUI { public static final fun setMessageTextTransformer (Lio/getstream/chat/android/ui/helper/transformer/ChatMessageTextTransformer;)V public static final fun setMimeTypeIconProvider (Lio/getstream/chat/android/ui/helper/MimeTypeIconProvider;)V public static final fun setNavigator (Lio/getstream/chat/android/ui/navigation/ChatNavigator;)V + public static final fun setPollsConfig (Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig;)V public static final fun setQuotedAttachmentFactoryManager (Lio/getstream/chat/android/ui/feature/messages/list/adapter/viewholder/attachment/QuotedAttachmentFactoryManager;)V public static final fun setReactionPushEmojiFactory (Lio/getstream/chat/android/ui/common/helper/ReactionPushEmojiFactory;)V public static final fun setShowOriginalTranslationEnabled (Z)V @@ -1506,6 +1508,8 @@ public final class io/getstream/chat/android/ui/feature/messages/composer/attach public final class io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment$Companion { public final fun newInstance (Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment$CreatePollDialogListener;)Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment; + public final fun newInstance (Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment$CreatePollDialogListener;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig;)Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment; + public static synthetic fun newInstance$default (Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment$Companion;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment$CreatePollDialogListener;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig;ILjava/lang/Object;)Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment; } public abstract interface class io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/CreatePollDialogFragment$CreatePollDialogListener { @@ -1524,6 +1528,7 @@ public final class io/getstream/chat/android/ui/feature/messages/composer/attach public final fun getPollIsReady ()Lkotlinx/coroutines/flow/StateFlow; public final fun onOptionTextChanged (ILjava/lang/String;)V public final fun onTitleChanged (Ljava/lang/String;)V + public final fun setAllowAnswers (Z)V public final fun setAllowMultipleVotes (Z)V public final fun setAnnonymousPoll (Z)V public final fun setMaxAnswer (Ljava/lang/Integer;)V @@ -1531,6 +1536,7 @@ public final class io/getstream/chat/android/ui/feature/messages/composer/attach } public final class io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/OptionsAdapter : androidx/recyclerview/widget/ListAdapter { + public fun (Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;)V public fun (Lkotlin/jvm/functions/Function2;)V public fun getItemId (I)J public synthetic fun onBindViewHolder (Landroidx/recyclerview/widget/RecyclerView$ViewHolder;I)V @@ -1540,8 +1546,8 @@ public final class io/getstream/chat/android/ui/feature/messages/composer/attach } public final class io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/OptionsAdapter$OptionViewHolder : androidx/recyclerview/widget/RecyclerView$ViewHolder { - public fun (Landroid/view/ViewGroup;Lio/getstream/chat/android/ui/databinding/StreamUiPollOptionBinding;Lkotlin/jvm/functions/Function2;)V - public synthetic fun (Landroid/view/ViewGroup;Lio/getstream/chat/android/ui/databinding/StreamUiPollOptionBinding;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Landroid/view/ViewGroup;Lio/getstream/chat/android/ui/databinding/StreamUiPollOptionBinding;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;)V + public synthetic fun (Landroid/view/ViewGroup;Lio/getstream/chat/android/ui/databinding/StreamUiPollOptionBinding;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun bind (Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollAnswer;)V } @@ -1560,6 +1566,75 @@ public final class io/getstream/chat/android/ui/feature/messages/composer/attach public fun toString ()Ljava/lang/String; } +public final class io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig : android/os/Parcelable { + public static final field CREATOR Landroid/os/Parcelable$Creator; + public static final field Companion Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig$Companion; + public fun (ZZ)V + public final fun component1 ()Z + public final fun component2 ()Z + public final fun copy (ZZ)Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public static synthetic fun copy$default (Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;ZZILjava/lang/Object;)Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public final fun describeContents ()I + public fun equals (Ljava/lang/Object;)Z + public final fun getConfigurable ()Z + public final fun getDefaultValue ()Z + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public final fun writeToParcel (Landroid/os/Parcel;I)V +} + +public final class io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig$Companion { + public final fun getDefault ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public final fun getNotConfigurable ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; +} + +public final class io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig$Creator : android/os/Parcelable$Creator { + public fun ()V + public final fun createFromParcel (Landroid/os/Parcel;)Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object; + public final fun newArray (I)[Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public synthetic fun newArray (I)[Ljava/lang/Object; +} + +public final class io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig : android/os/Parcelable { + public static final field CREATOR Landroid/os/Parcelable$Creator; + public static final field Companion Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig$Companion; + public fun ()V + public fun (Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Ljava/lang/Integer;Ljava/lang/Integer;)V + public synthetic fun (Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public final fun component2 ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public final fun component3 ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public final fun component4 ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public final fun component5 ()Ljava/lang/Integer; + public final fun component6 ()Ljava/lang/Integer; + public final fun copy (Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Ljava/lang/Integer;Ljava/lang/Integer;)Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig; + public static synthetic fun copy$default (Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig;Ljava/lang/Integer;Ljava/lang/Integer;ILjava/lang/Object;)Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig; + public final fun describeContents ()I + public fun equals (Ljava/lang/Object;)Z + public final fun getAllowComments ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public final fun getAnonymousPoll ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public final fun getMultipleVotes ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public final fun getOptionTextLimit ()Ljava/lang/Integer; + public final fun getQuestionTextLimit ()Ljava/lang/Integer; + public final fun getSuggestAnOption ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public final fun writeToParcel (Landroid/os/Parcel;I)V +} + +public final class io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig$Companion { + public final fun getDefault ()Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig; +} + +public final class io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig$Creator : android/os/Parcelable$Creator { + public fun ()V + public final fun createFromParcel (Landroid/os/Parcel;)Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig; + public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object; + public final fun newArray (I)[Lio/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig; + public synthetic fun newArray (I)[Ljava/lang/Object; +} + public final class io/getstream/chat/android/ui/feature/messages/composer/attachment/preview/AttachmentPreviewFactoryManager { public fun ()V public fun (Ljava/util/List;)V diff --git a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig.kt b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig.kt index 3a6b2364d11..40ebfb47d2a 100644 --- a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig.kt +++ b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollFeatureConfig.kt @@ -1,3 +1,19 @@ +/* + * 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.ui.feature.messages.composer.attachment.picker.poll import android.os.Parcelable @@ -31,4 +47,4 @@ public data class PollFeatureConfig( defaultValue = false, ) } -} \ No newline at end of file +} diff --git a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt index 152a745569a..727ed2ec384 100644 --- a/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt +++ b/stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/composer/attachment/picker/poll/PollsConfig.kt @@ -20,7 +20,8 @@ import android.os.Parcelable import kotlinx.parcelize.Parcelize /** - * The configuration for the various poll features. It determines if the user can or cannot enable certain poll features. + * The configuration for the various poll features. It determines if the user can or cannot enable + * certain poll features. * * @param multipleVotes Configuration for allowing multiple votes in a poll. * @param anonymousPoll Configuration for enabling anonymous polls.