mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 10:25:35 +03:00
Show error dialog rather than toast. Add validation to keyword field for slashes and dots.
This commit is contained in:
parent
9d663413a9
commit
68eaefbc9c
5 changed files with 78 additions and 34 deletions
|
@ -17,6 +17,7 @@
|
|||
package im.vector.app.core.preference
|
||||
|
||||
import android.content.Context
|
||||
import android.text.Editable
|
||||
import android.util.AttributeSet
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.Button
|
||||
|
@ -25,7 +26,10 @@ import androidx.core.view.children
|
|||
import androidx.preference.PreferenceViewHolder
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.chip.ChipGroup
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.addTextChangedListenerOnce
|
||||
import im.vector.app.core.platform.SimpleTextWatcher
|
||||
|
||||
class KeywordPreference : VectorPreference {
|
||||
|
||||
|
@ -36,6 +40,7 @@ class KeywordPreference : VectorPreference {
|
|||
}
|
||||
|
||||
private var keywordsEnabled = true
|
||||
private var isCurrentKeywordValid = true
|
||||
|
||||
private var _keywords: LinkedHashSet<String> = linkedSetOf()
|
||||
|
||||
|
@ -78,6 +83,7 @@ class KeywordPreference : VectorPreference {
|
|||
val chipEditText = holder.findViewById(R.id.chipEditText) as? EditText ?: return
|
||||
val chipGroup = holder.findViewById(R.id.chipGroup) as? ChipGroup ?: return
|
||||
val addKeywordButton = holder.findViewById(R.id.addKeywordButton) as? Button ?: return
|
||||
val chipTextInputLayout = holder.findViewById(R.id.chipTextInputLayout) as? TextInputLayout ?: return
|
||||
|
||||
chipEditText.text = null
|
||||
chipGroup.removeAllViews()
|
||||
|
@ -90,30 +96,57 @@ class KeywordPreference : VectorPreference {
|
|||
chipGroup.isEnabled = keywordsEnabled
|
||||
chipGroup.children.forEach { it.isEnabled = keywordsEnabled }
|
||||
|
||||
fun addKeyword(): Boolean {
|
||||
val keyword = chipEditText.text.toString().trim()
|
||||
if (keyword.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
listener?.didAddKeyword(keyword)
|
||||
onPreferenceChangeListener?.onPreferenceChange(this, _keywords)
|
||||
notifyChanged()
|
||||
chipEditText.text = null
|
||||
return true
|
||||
}
|
||||
|
||||
chipEditText.addTextChangedListenerOnce(onTextChangeListener(chipTextInputLayout, addKeywordButton))
|
||||
chipEditText.setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId != EditorInfo.IME_ACTION_DONE) {
|
||||
return@setOnEditorActionListener false
|
||||
}
|
||||
return@setOnEditorActionListener addKeyword()
|
||||
return@setOnEditorActionListener addKeyword(chipEditText)
|
||||
}
|
||||
chipEditText.setOnFocusChangeListener { _, hasFocus ->
|
||||
listener?.onFocusDidChange(hasFocus)
|
||||
}
|
||||
|
||||
addKeywordButton.setOnClickListener {
|
||||
addKeyword()
|
||||
addKeyword(chipEditText)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addKeyword(chipEditText: EditText): Boolean {
|
||||
val keyword = chipEditText.text.toString().trim()
|
||||
|
||||
if (!isCurrentKeywordValid || keyword.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
|
||||
listener?.didAddKeyword(keyword)
|
||||
onPreferenceChangeListener?.onPreferenceChange(this, _keywords)
|
||||
notifyChanged()
|
||||
chipEditText.text = null
|
||||
return true
|
||||
}
|
||||
|
||||
private fun onTextChangeListener(chipTextInputLayout: TextInputLayout, addKeywordButton: Button) = object : SimpleTextWatcher() {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
val keyword = s.toString().trim()
|
||||
val errorMessage = when {
|
||||
keyword.startsWith(".") -> {
|
||||
context.getString(R.string.settings_notification_keyword_contains_dot)
|
||||
}
|
||||
keyword.contains("\\") -> {
|
||||
context.getString(R.string.settings_notification_keyword_contains_invalid_character, "\\")
|
||||
}
|
||||
keyword.contains("/") -> {
|
||||
context.getString(R.string.settings_notification_keyword_contains_invalid_character, "/")
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
chipTextInputLayout.isErrorEnabled = errorMessage != null
|
||||
chipTextInputLayout.error = errorMessage
|
||||
val keywordValid = errorMessage == null
|
||||
addKeywordButton.isEnabled = keywordsEnabled && keywordValid
|
||||
this@KeywordPreference.isCurrentKeywordValid = keywordValid
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.os.Bundle
|
|||
import android.view.View
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.DaggerScreenComponent
|
||||
import im.vector.app.core.di.HasScreenInjector
|
||||
|
@ -160,9 +161,22 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), HasScree
|
|||
}
|
||||
activity?.runOnUiThread {
|
||||
if (errorMessage != null && errorMessage.isNotBlank()) {
|
||||
activity?.toast(errorMessage)
|
||||
displayErrorDialog(errorMessage)
|
||||
}
|
||||
hideLoadingView()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun displayErrorDialog(throwable: Throwable) {
|
||||
displayErrorDialog(errorFormatter.toHumanReadable(throwable))
|
||||
}
|
||||
|
||||
protected fun displayErrorDialog(errorMessage: String) {
|
||||
MaterialAlertDialogBuilder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorMessage)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import im.vector.app.core.preference.KeywordPreference
|
|||
import im.vector.app.core.preference.VectorCheckboxPreference
|
||||
import im.vector.app.core.preference.VectorPreference
|
||||
import im.vector.app.core.preference.VectorPreferenceCategory
|
||||
import im.vector.app.core.utils.toast
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -68,7 +67,7 @@ class VectorSettingsKeywordAndMentionsNotificationPreferenceFragment
|
|||
|
||||
val footerPreference = findPreference<VectorPreference>("SETTINGS_KEYWORDS_FOOTER")!!
|
||||
footerPreference.isIconSpaceReserved = false
|
||||
|
||||
val host = this
|
||||
keywordPreference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
val keywords = editKeywordPreference.keywords
|
||||
val newChecked = newValue as Boolean
|
||||
|
@ -82,17 +81,15 @@ class VectorSettingsKeywordAndMentionsNotificationPreferenceFragment
|
|||
keywordPreference.isChecked = newChecked
|
||||
editKeywordPreference.isEnabled = newChecked
|
||||
}
|
||||
result.onFailure {
|
||||
result.onFailure { failure ->
|
||||
refreshDisplay()
|
||||
activity?.toast(errorFormatter.toHumanReadable(it))
|
||||
host.displayErrorDialog(failure)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
val host = this
|
||||
editKeywordPreference.listener = object: KeywordPreference.Listener {
|
||||
|
||||
override fun onFocusDidChange(hasFocus: Boolean) {
|
||||
host.keywordsHasFocus = true
|
||||
}
|
||||
|
@ -147,37 +144,35 @@ class VectorSettingsKeywordAndMentionsNotificationPreferenceFragment
|
|||
val newActions = standardAction.actions ?: return
|
||||
val newRule = PushRule(actions = newActions.toJson(), pattern = keyword, enabled = enabled, ruleId = keyword)
|
||||
displayLoadingView()
|
||||
val host = this
|
||||
lifecycleScope.launch {
|
||||
val result = runCatching {
|
||||
session.addPushRule(RuleKind.CONTENT, newRule)
|
||||
}
|
||||
hideLoadingView()
|
||||
if (!isAdded) {
|
||||
return@launch
|
||||
}
|
||||
hideLoadingView()
|
||||
// Already added to UI, no-op on success
|
||||
result.onFailure {
|
||||
// Just display an error on failure, keywords have not been added to the UI
|
||||
activity?.toast(errorFormatter.toHumanReadable(it))
|
||||
}
|
||||
|
||||
result.onFailure(host::displayErrorDialog)
|
||||
}
|
||||
}
|
||||
|
||||
fun removeKeyword(keyword: String) {
|
||||
displayLoadingView()
|
||||
val host = this
|
||||
lifecycleScope.launch {
|
||||
val result = runCatching {
|
||||
session.removePushRule(RuleKind.CONTENT, keyword)
|
||||
}
|
||||
hideLoadingView()
|
||||
if (!isAdded) {
|
||||
return@launch
|
||||
}
|
||||
hideLoadingView()
|
||||
// Already added to UI, no-op on success
|
||||
result.onFailure {
|
||||
// Just display an error on failure, keywords have not been added to the UI
|
||||
activity?.toast(errorFormatter.toHumanReadable(it))
|
||||
}
|
||||
|
||||
result.onFailure(host::displayErrorDialog)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.app.features.settings.notifications
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.Preference
|
||||
import im.vector.app.core.preference.VectorCheckboxPreference
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.features.settings.VectorSettingsBaseFragment
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.pushrules.RuleKind
|
||||
|
@ -57,6 +56,7 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
|
|||
val newActions = standardAction.actions
|
||||
displayLoadingView()
|
||||
|
||||
val host = this
|
||||
lifecycleScope.launch {
|
||||
val result = runCatching {
|
||||
session.updatePushRuleActions(kind,
|
||||
|
@ -64,17 +64,17 @@ abstract class VectorSettingsPushRuleNotificationPreferenceFragment
|
|||
enabled,
|
||||
newActions)
|
||||
}
|
||||
hideLoadingView()
|
||||
if (!isAdded) {
|
||||
return@launch
|
||||
}
|
||||
hideLoadingView()
|
||||
result.onSuccess {
|
||||
preference.isChecked = checked
|
||||
}
|
||||
result.onFailure { failure ->
|
||||
// Restore the previous value
|
||||
refreshDisplay()
|
||||
activity?.toast(errorFormatter.toHumanReadable(failure))
|
||||
host.displayErrorDialog(failure)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1097,6 +1097,8 @@
|
|||
<string name="settings_notification_notify_me_for">Notify me for</string>
|
||||
<string name="settings_notification_your_keywords">Your keywords</string>
|
||||
<string name="settings_notification_new_keyword">Add new keyword</string>
|
||||
<string name="settings_notification_keyword_contains_dot">Keywords cannot start with \'.\'</string>
|
||||
<string name="settings_notification_keyword_contains_invalid_character">Keywords cannot contain \'%s\'</string>
|
||||
|
||||
<string name="settings_notification_privacy">Notification privacy</string>
|
||||
<string name="settings_notification_troubleshoot">Troubleshoot Notifications</string>
|
||||
|
|
Loading…
Reference in a new issue