diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d9b5017138..fddc9e5ef68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ ## stream-chat-android-ui-components ### 🐞 Fixed +- Filter out Poll Options differing only on whitespaces. [#5913](https://github.com/GetStream/stream-chat-android/pull/5913) ### ⬆️ Improved @@ -71,6 +72,7 @@ ## stream-chat-android-compose ### 🐞 Fixed +- Filter out Poll Options differing only on whitespaces. [#5913](https://github.com/GetStream/stream-chat-android/pull/5913) ### ⬆️ Improved diff --git a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollOptionList.kt b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollOptionList.kt index 0c2d1264436..5bbba2376ae 100644 --- a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollOptionList.kt +++ b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollOptionList.kt @@ -142,23 +142,27 @@ public fun PollOptionList( PaddingValues(horizontal = 16.dp, vertical = 8.dp) }, onValueChange = { newTitle -> - optionItemList.toMutableList().apply { - val duplicated = this.any { it.title == newTitle } - if (duplicated) { - this[index] = item.copy( + val duplicated = optionItemList + .withIndex() + .any { + it.index != index && + it.value.title.trim() == newTitle.trim() + } + optionItemList = optionItemList.mapIndexed { i, item -> + when (i) { + index -> item.copy( title = newTitle, - pollOptionError = PollOptionDuplicated( - context.getString(R.string.stream_compose_poll_option_error_duplicated), - ), + pollOptionError = when (duplicated) { + false -> null + true -> PollOptionDuplicated( + context.getString(R.string.stream_compose_poll_option_error_duplicated), + ) + }, ) - } else { - this[index] = - item.copy(title = newTitle, pollOptionError = null) + else -> item } - - optionItemList = this - onQuestionsChanged.invoke(this) } + onQuestionsChanged.invoke(optionItemList) }, decorationBox = { innerTextField -> if (item.pollOptionError == null) { 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 41c7d2b6765..cb1573740a3 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 @@ -154,11 +154,17 @@ public class CreatePollViewModel : ViewModel() { _options.value.let { options -> val previousOptions = options.values .filterNot { it.id == id } - .map { it.text } + .map { it.text.trim() } .filter { it.isNotEmpty() } options[id]?.let { option -> _options.value = LinkedHashMap(options).apply { - put(id, option.copy(text = text, duplicateError = previousOptions.contains(text))) + put( + id, + option.copy( + text = text, + duplicateError = previousOptions.any { it == text.trim() }, + ), + ) } } } 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 ca6a37138b8..6f24da5f874 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 @@ -62,6 +62,7 @@ public class OptionsAdapter( 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 */ } override fun afterTextChanged(s: Editable?) { + pollAnswer.updateErrorState() onOptionChange(pollAnswer.id, s.toString()) } } @@ -71,9 +72,13 @@ public class OptionsAdapter( binding.option.removeTextChangedListener(textWatcher) binding.option.setText(pollAnswer.text) binding.option.setSelection(pollAnswer.text.length) + pollAnswer.updateErrorState() binding.option.addTextChangedListener(textWatcher) + } + + private fun PollAnswer.updateErrorState() { binding.option.error = when { - pollAnswer.duplicateError -> + duplicateError -> binding.root.context.getString(R.string.stream_ui_poll_this_is_already_an_option) else -> null }