diff --git a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionViewHolder.kt b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionViewHolder.kt index f0b81e973..e8ca339ef 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionViewHolder.kt @@ -31,11 +31,14 @@ class PollCreateOptionViewHolder( itemsListener.onRemoveOptionsItemClick(pollCreateOptionItem, position) } - textListener = getTextWatcher(pollCreateOptionItem) + textListener = getTextWatcher(pollCreateOptionItem, itemsListener) binding.pollOptionText.addTextChangedListener(textListener) } - private fun getTextWatcher(pollCreateOptionItem: PollCreateOptionItem) = + private fun getTextWatcher( + pollCreateOptionItem: PollCreateOptionItem, + itemsListener: PollCreateOptionsItemListener + ) = object : TextWatcher { override fun afterTextChanged(s: Editable) { // unused atm @@ -47,6 +50,8 @@ class PollCreateOptionViewHolder( override fun onTextChanged(option: CharSequence, start: Int, before: Int, count: Int) { pollCreateOptionItem.pollOption = option.toString() + + itemsListener.onOptionsItemTextChanged(pollCreateOptionItem) } } } diff --git a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionsItemListener.kt b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionsItemListener.kt index 751c95d4b..5cb0c53b4 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionsItemListener.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionsItemListener.kt @@ -3,4 +3,6 @@ package com.nextcloud.talk.polls.adapters interface PollCreateOptionsItemListener { fun onRemoveOptionsItemClick(pollCreateOptionItem: PollCreateOptionItem, position: Int) + + fun onOptionsItemTextChanged(pollCreateOptionItem: PollCreateOptionItem) } diff --git a/app/src/main/java/com/nextcloud/talk/polls/ui/PollCreateDialogFragment.kt b/app/src/main/java/com/nextcloud/talk/polls/ui/PollCreateDialogFragment.kt index 365506133..35bd6648f 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/ui/PollCreateDialogFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/ui/PollCreateDialogFragment.kt @@ -5,14 +5,17 @@ import android.app.Dialog import android.os.Bundle import android.text.Editable import android.text.TextWatcher +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.fragment.app.DialogFragment import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager import autodagger.AutoInjector +import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.databinding.DialogPollCreateBinding import com.nextcloud.talk.polls.adapters.PollCreateOptionItem @@ -78,6 +81,7 @@ class PollCreateDialogFragment( private fun setupListeners() { binding.pollAddOptionsItem.setOnClickListener { viewModel.addOption() + adapter?.itemCount?.minus(1)?.let { it -> binding.pollCreateOptionsList.scrollToPosition(it) } } binding.pollDismiss.setOnClickListener { @@ -117,41 +121,32 @@ class PollCreateDialogFragment( private fun setupStateObserver() { viewModel.viewState.observe(viewLifecycleOwner) { state -> when (state) { - // PollCreateViewModel.InitialState -> showInitial() is PollCreateViewModel.PollCreatedState -> dismiss() - is PollCreateViewModel.PollCreationFailedState -> dismiss() - is PollCreateViewModel.PollCreatingState -> updateDialog(state) + is PollCreateViewModel.PollCreationFailedState -> showError() + is PollCreateViewModel.PollCreationState -> updateButtons(state) } } - // viewModel.state.observe(this) { state -> - // when (state) { - // MessageSearchViewModel.InitialState -> showInitial() - // MessageSearchViewModel.EmptyState -> showEmpty() - // is MessageSearchViewModel.LoadedState -> showLoaded(state) - // MessageSearchViewModel.LoadingState -> showLoading() - // MessageSearchViewModel.ErrorState -> showError() - // is MessageSearchViewModel.FinishedState -> onFinish() - // } - // } } - private fun updateDialog(state: PollCreateViewModel.PollCreatingState) { - // binding.pollCreateQuestion.setText(state.question) - // - // adapter!!.updateOptionsList(state.options) - // - // binding.pollPrivatePollCheckbox.isChecked = state.privatePoll - // binding.pollMultipleAnswersCheckbox.isChecked = state.multipleAnswer + private fun updateButtons(state: PollCreateViewModel.PollCreationState) { + binding.pollAddOptionsItem.isEnabled = state.enableAddOptionButton + binding.pollCreateButton.isEnabled = state.enableCreatePollButton } - private fun showInitial() { - binding.pollCreateButton.isEnabled = false + private fun showError() { + dismiss() + Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show() + Log.e(TAG, "Failed to create poll") } override fun onRemoveOptionsItemClick(pollCreateOptionItem: PollCreateOptionItem, position: Int) { viewModel.removeOption(pollCreateOptionItem) } + override fun onOptionsItemTextChanged(pollCreateOptionItem: PollCreateOptionItem) { + viewModel.optionsItemTextChanged() + } + /** * Fragment creator */ diff --git a/app/src/main/java/com/nextcloud/talk/polls/viewmodels/PollCreateViewModel.kt b/app/src/main/java/com/nextcloud/talk/polls/viewmodels/PollCreateViewModel.kt index 05f3fabe4..341618d93 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/viewmodels/PollCreateViewModel.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/viewmodels/PollCreateViewModel.kt @@ -16,10 +16,14 @@ class PollCreateViewModel @Inject constructor(private val repository: PollReposi private lateinit var roomToken: String - // private var _options: MutableLiveData> = - // MutableLiveData>() - // val options: LiveData> - // get() = _options + sealed interface ViewState + open class PollCreationState(val enableAddOptionButton: Boolean, val enableCreatePollButton: Boolean) : ViewState + object PollCreatedState : ViewState + object PollCreationFailedState : ViewState + + private val _viewState: MutableLiveData = MutableLiveData(PollCreationState(true, false)) + val viewState: LiveData + get() = _viewState private var _options: MutableLiveData> = MutableLiveData>() @@ -31,27 +35,18 @@ class PollCreateViewModel @Inject constructor(private val repository: PollReposi get() = _question private var _privatePoll: MutableLiveData = MutableLiveData() - var privatePoll: LiveData = _privatePoll + val privatePoll: LiveData get() = _privatePoll private var _multipleAnswer: MutableLiveData = MutableLiveData() - var multipleAnswer: LiveData = _multipleAnswer + val multipleAnswer: LiveData get() = _multipleAnswer - sealed interface ViewState - object InitialState : ViewState - open class PollCreatingState() : ViewState - open class PollCreatedState() : ViewState - open class PollCreationFailedState() : ViewState - - private val _viewState: MutableLiveData = MutableLiveData(InitialState) - val viewState: LiveData - get() = _viewState - private var disposable: Disposable? = null fun initialize(roomToken: String) { this.roomToken = roomToken + updateCreationState() } override fun onCleared() { @@ -64,12 +59,14 @@ class PollCreateViewModel @Inject constructor(private val repository: PollReposi val currentOptions: ArrayList = _options.value ?: ArrayList() currentOptions.add(item) _options.value = currentOptions + updateCreationState() } fun removeOption(item: PollCreateOptionItem) { val currentOptions: ArrayList = _options.value ?: ArrayList() currentOptions.remove(item) _options.value = currentOptions + updateCreationState() } fun createPoll() { @@ -83,9 +80,9 @@ class PollCreateViewModel @Inject constructor(private val repository: PollReposi resultMode = 1 } - if (question.value?.isNotEmpty() == true && _options.value?.isNotEmpty() == true) { + if (_question.value?.isNotEmpty() == true && _options.value?.isNotEmpty() == true) { repository.createPoll( - roomToken, question.value!!, _options.value!!.map { it.pollOption }, resultMode, + roomToken, _question.value!!, _options.value!!.map { it.pollOption }, resultMode, maxVotes ) ?.doOnSubscribe { disposable = it } @@ -97,6 +94,7 @@ class PollCreateViewModel @Inject constructor(private val repository: PollReposi fun setQuestion(question: String) { _question.value = question + updateCreationState() } fun setPrivatePoll(checked: Boolean) { @@ -107,6 +105,44 @@ class PollCreateViewModel @Inject constructor(private val repository: PollReposi _multipleAnswer.value = checked } + fun optionsItemTextChanged() { + updateCreationState() + } + + private fun updateCreationState() { + _viewState.value = PollCreationState(enableAddOptionButton(), enableCreatePollButton()) + } + + private fun enableCreatePollButton(): Boolean { + return _question.value?.isNotEmpty() == true && atLeastTwoOptionsAreFilled() + } + + private fun atLeastTwoOptionsAreFilled(): Boolean { + if (_options.value != null) { + var filledOptions = 0 + _options.value?.forEach { + if (it.pollOption.isNotEmpty()) { + filledOptions++ + } + if (filledOptions >= 2) { + return true + } + } + } + return false + } + + private fun enableAddOptionButton(): Boolean { + if (_options.value != null && _options.value?.size != 0) { + _options.value?.forEach { + if (it.pollOption.isBlank()) { + return false + } + } + } + return true + } + inner class PollObserver : Observer { lateinit var poll: Poll @@ -118,11 +154,11 @@ class PollCreateViewModel @Inject constructor(private val repository: PollReposi } override fun onError(e: Throwable) { - _viewState.value = PollCreationFailedState() + _viewState.value = PollCreationFailedState } override fun onComplete() { - _viewState.value = PollCreatedState() + _viewState.value = PollCreatedState } } diff --git a/app/src/main/res/layout/dialog_poll_create.xml b/app/src/main/res/layout/dialog_poll_create.xml index 50b3e77a0..23989ba33 100644 --- a/app/src/main/res/layout/dialog_poll_create.xml +++ b/app/src/main/res/layout/dialog_poll_create.xml @@ -31,7 +31,6 @@ -