From f89c5feaa1666b042c4f2764e74aa5bfe089c524 Mon Sep 17 00:00:00 2001
From: Fabian-K <fabian.kajzar@sap.com>
Date: Fri, 12 Jun 2020 11:35:47 +0200
Subject: [PATCH] TAN Input a11y: repeat error messages (#410)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* TAN Input a11y: repeat error messages

* lint fix 🤦‍♂️

Co-authored-by: Jakob Möller <jakob.moeller@sap.com>
---
 .../ui/submission/SubmissionTanFragment.kt    | 35 +++++++++++++++++--
 .../ui/submission/SubmissionTanViewModel.kt   | 11 ------
 .../de/rki/coronawarnapp/ui/view/TanInput.kt  | 14 +-------
 .../res/layout/include_submission_tan.xml     | 13 ++++---
 .../submission/SubmissionTanViewModelTest.kt  | 18 ----------
 5 files changed, 41 insertions(+), 50 deletions(-)

diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt
index a1188ed16..ea5639dcf 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt
@@ -7,6 +7,7 @@ import android.view.ViewGroup
 import android.view.accessibility.AccessibilityEvent
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
+import androidx.fragment.app.viewModels
 import androidx.navigation.fragment.findNavController
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentSubmissionTanBinding
@@ -18,14 +19,17 @@ import de.rki.coronawarnapp.ui.doNavigate
 import de.rki.coronawarnapp.ui.main.MainActivity
 import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel
 import de.rki.coronawarnapp.util.DialogHelper
+import de.rki.coronawarnapp.util.TanHelper
 import de.rki.coronawarnapp.util.observeEvent
+import kotlinx.android.synthetic.main.include_submission_tan.submission_tan_error
+import kotlinx.android.synthetic.main.include_submission_tan.submission_tan_character_error
 
 /**
  * Fragment for TAN entry
  */
 class SubmissionTanFragment : Fragment() {
 
-    private val viewModel: SubmissionTanViewModel by activityViewModels()
+    private val viewModel: SubmissionTanViewModel by viewModels()
     private val submissionViewModel: SubmissionViewModel by activityViewModels()
     private var _binding: FragmentSubmissionTanBinding? = null
     private val binding: FragmentSubmissionTanBinding get() = _binding!!
@@ -97,8 +101,20 @@ class SubmissionTanFragment : Fragment() {
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
-        binding.submissionTanContent.submissionTanInput.listener =
-            { tan -> viewModel.tan.value = tan }
+        binding.submissionTanContent.submissionTanInput.listener = { tan ->
+            resetError()
+
+            viewModel.tan.value = tan
+
+            if (tan != null) {
+                if (!TanHelper.allCharactersValid(tan))
+                    showCharacterError()
+
+                if (tan.length == TanConstants.MAX_LENGTH && !TanHelper.isChecksumValid(tan))
+                    showTanError()
+            }
+        }
+
         binding.submissionTanButtonEnter.setOnClickListener { storeTanAndContinue() }
         binding.submissionTanHeader.headerButtonBack.buttonIcon.setOnClickListener { goBack() }
 
@@ -120,6 +136,19 @@ class SubmissionTanFragment : Fragment() {
         })
     }
 
+    private fun resetError() {
+        submission_tan_character_error.visibility = View.GONE
+        submission_tan_error.visibility = View.GONE
+    }
+
+    private fun showCharacterError() {
+        submission_tan_character_error.visibility = View.VISIBLE
+    }
+
+    private fun showTanError() {
+        submission_tan_error.visibility = View.VISIBLE
+    }
+
     override fun onResume() {
         super.onResume()
         binding.submissionTanRoot.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt
index e42d6c9a2..849aebddf 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt
@@ -23,17 +23,6 @@ class SubmissionTanViewModel : ViewModel() {
                     TanHelper.allCharactersValid(it)
         }
 
-    val tanChecksumValid =
-        Transformations.map(tan) {
-            ((it !== null && it.trim().length == TanConstants.MAX_LENGTH) &&
-                    TanHelper.isChecksumValid(it).not()).not()
-        }
-
-    val tanCharactersValid =
-        Transformations.map(tan) {
-            !((it != null) && TanHelper.allCharactersValid(it).not())
-        }
-
     fun storeTeletan() {
         val teletan = tan.value!!
         Timber.d("Storing teletan $teletan")
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/TanInput.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/TanInput.kt
index 66b26f262..91a3e227e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/TanInput.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/TanInput.kt
@@ -14,7 +14,6 @@ import androidx.core.view.children
 import androidx.core.widget.doOnTextChanged
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.ui.submission.TanConstants
-import de.rki.coronawarnapp.ui.submission.TanConstants.MAX_LENGTH
 import de.rki.coronawarnapp.util.TanHelper
 import kotlinx.android.synthetic.main.view_tan_input_edittext.view.tan_input_edittext
 import java.util.Locale
@@ -40,7 +39,7 @@ class TanInput(context: Context, attrs: AttributeSet) : ViewGroup(context, attrs
             TanConstants.ALPHA_NUMERIC_CHARS.contains(it)
         }
     }
-    private var lengthFilter = InputFilter.LengthFilter(MAX_LENGTH)
+    private var lengthFilter = InputFilter.LengthFilter(TanConstants.MAX_LENGTH)
 
     var listener: ((String?) -> Unit)? = null
 
@@ -78,20 +77,9 @@ class TanInput(context: Context, attrs: AttributeSet) : ViewGroup(context, attrs
         }
     }
 
-    private fun limitLength(length: Int?) {
-        lengthFilter = InputFilter.LengthFilter(if (length != null) length else MAX_LENGTH)
-        tan_input_edittext.filters = arrayOf(whitespaceFilter, alphaNumericFilter, lengthFilter)
-    }
-
     private fun updateTan(text: CharSequence?) {
         this.tan = text?.toString()?.toUpperCase(Locale.ROOT)
         updateDigits()
-        tan?.let {
-            limitLength(
-                if (TanHelper.allCharactersValid(it)) null
-                else it.length
-            )
-        }
         notifyListener()
     }
 
diff --git a/Corona-Warn-App/src/main/res/layout/include_submission_tan.xml b/Corona-Warn-App/src/main/res/layout/include_submission_tan.xml
index b86713c29..e1b02f87c 100644
--- a/Corona-Warn-App/src/main/res/layout/include_submission_tan.xml
+++ b/Corona-Warn-App/src/main/res/layout/include_submission_tan.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools">
 
     <data>
 
@@ -52,10 +53,11 @@
                 android:accessibilityLiveRegion="assertive"
                 android:text="@string/submission_tan_character_error"
                 android:textColor="@color/colorTextSemanticRed"
-                android:visibility="@{FormatterSubmissionHelper.formatShowTanCharacterError(viewmodel.tanCharactersValid, viewmodel.tanChecksumValid)}"
+                android:visibility="gone"
                 app:layout_constraintEnd_toStartOf="@+id/guideline_end"
                 app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@id/submission_tan_input" />
+                app:layout_constraintTop_toBottomOf="@id/submission_tan_input"
+                tools:visibility="visible" />
 
             <TextView
                 android:id="@+id/submission_tan_error"
@@ -66,10 +68,11 @@
                 android:accessibilityLiveRegion="assertive"
                 android:text="@string/submission_tan_error"
                 android:textColor="@color/colorTextSemanticRed"
-                android:visibility="@{FormatterHelper.formatVisibility(!viewmodel.tanChecksumValid)}"
+                android:visibility="gone"
                 app:layout_constraintEnd_toStartOf="@+id/guideline_end"
                 app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@id/submission_tan_input" />
+                app:layout_constraintTop_toBottomOf="@id/submission_tan_character_error"
+                tools:visibility="visible" />
 
             <include layout="@layout/merge_guidelines_side" />
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModelTest.kt
index 96973d9dc..805e97506 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModelTest.kt
@@ -14,15 +14,6 @@ import org.junit.Test
 class SubmissionTanViewModelTest {
     private var viewModel: SubmissionTanViewModel = SubmissionTanViewModel()
 
-    @Test
-    fun allCharactersValid() {
-        viewModel.tan.postValue("ABCD")
-        viewModel.tanCharactersValid.value?.let { assertTrue(it) }
-
-        viewModel.tan.postValue("ABCD0")
-        viewModel.tanCharactersValid.value?.let { assertFalse(it) }
-    }
-
     @Test
     fun tanFormatValid() {
         viewModel.tan.postValue("ZWFPC7NG47")
@@ -38,15 +29,6 @@ class SubmissionTanViewModelTest {
         viewModel.isValidTanFormat.value?.let { assertFalse(it) }
     }
 
-    @Test
-    fun checksumValid() {
-        viewModel.tan.postValue("ZWFPC7NG47")
-        viewModel.tanChecksumValid.value?.let { assertTrue(it) }
-
-        viewModel.tan.postValue("ZWFPC7NG48")
-        viewModel.tanChecksumValid.value?.let { assertFalse(it) }
-    }
-
     @Test
     fun testTanStorage() {
         val sr = mockk<SubmissionRepository> {
-- 
GitLab