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..a51bfe96716 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 @@ -39,7 +40,16 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch /** - * Represent the bottom sheet dialog that allows users to pick attachments. + * A dialog fragment that allows users to create polls with configurable character limits. + * + * This dialog provides a UI for creating polls with customizable settings including: + * - Poll question with optional character limit + * - Multiple answer options with optional character limit + * - Multiple vote configuration + * - Anonymous poll option + * - Option suggestion capability + * + * Use [newInstance] to create an instance with optional character limits. */ public class CreatePollDialogFragment : AppCompatDialogFragment() { @@ -48,7 +58,10 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { private var createPollDialogListener: CreatePollDialogListener? = null private val createPollViewModel: CreatePollViewModel by viewModels() private val optionsAdapter: OptionsAdapter by lazy { - OptionsAdapter { id, text -> createPollViewModel.onOptionTextChanged(id, text) } + OptionsAdapter( + optionTextLimit = arguments?.getInt(ARG_OPTION_TEXT_LIMIT)?.takeIf { it > 0 }, + onOptionChange = { id, text -> createPollViewModel.onOptionTextChanged(id, text) }, + ) } private lateinit var sendMenuItem: MenuItem @@ -81,6 +94,9 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { */ private fun setupDialog() { setupToolbar(binding.toolbar) + arguments?.getInt(ARG_QUESTION_TEXT_LIMIT)?.takeIf { it > 0 }?.let { limit -> + binding.question.filters = arrayOf(InputFilter.LengthFilter(limit)) + } binding.multipleAnswersSwitch.setOnCheckedChangeListener { _, isChecked -> binding.multipleAnswersCount.isVisible = isChecked createPollViewModel.setAllowMultipleVotes(isChecked) @@ -158,15 +174,29 @@ public class CreatePollDialogFragment : AppCompatDialogFragment() { public companion object { public const val TAG: String = "create_poll_dialog_fragment" + private const val ARG_QUESTION_TEXT_LIMIT: String = "arg_question_text_limit" + private const val ARG_OPTION_TEXT_LIMIT: String = "arg_option_text_limit" /** * Creates a new instance of [CreatePollDialogFragment]. * + * @param createPollDialogListener The listener for poll creation events. + * @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. * @return A new instance of [CreatePollDialogFragment]. */ - public fun newInstance(createPollDialogListener: CreatePollDialogListener): CreatePollDialogFragment { - return CreatePollDialogFragment() - .setCreatePollDialogListener(createPollDialogListener) + @JvmOverloads + public fun newInstance( + createPollDialogListener: CreatePollDialogListener, + questionTextLimit: Int? = null, + optionTextLimit: Int? = null, + ): CreatePollDialogFragment { + return CreatePollDialogFragment().apply { + arguments = Bundle().apply { + questionTextLimit?.let { putInt(ARG_QUESTION_TEXT_LIMIT, it) } + optionTextLimit?.let { putInt(ARG_OPTION_TEXT_LIMIT, it) } + } + }.setCreatePollDialogListener(createPollDialogListener) } } 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 */ }