diff --git a/Corona-Warn-App/build.gradle b/Corona-Warn-App/build.gradle index 9653605022da69e297462df12aef60690fcb26d2..cbd96348fae59b17623cd6b6414f0302f9c522f6 100644 --- a/Corona-Warn-App/build.gradle +++ b/Corona-Warn-App/build.gradle @@ -32,8 +32,8 @@ android { applicationId 'de.rki.coronawarnapp' minSdkVersion 23 targetSdkVersion 29 - versionCode 27 - versionName "1.0.0" + versionCode 28 + versionName "1.0.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField "String", "DOWNLOAD_CDN_URL", "\"$DOWNLOAD_CDN_URL\"" diff --git a/Corona-Warn-App/src/main/assets/terms_de.html b/Corona-Warn-App/src/main/assets/terms_de.html index fe94001fbca8a76ec1bdef282504bfaeb5d38b15..75d8382d4fdbba30f81be696f080e2bbfa052759 100644 --- a/Corona-Warn-App/src/main/assets/terms_de.html +++ b/Corona-Warn-App/src/main/assets/terms_de.html @@ -453,7 +453,7 @@ </p> <p> Eine ausführliche Anleitung zur Einrichtung der App unter iOS und Android - finden Sie unter [<em>Link</em>]. Die Anleitung dient lediglich der + finden Sie unter https://www.coronawarn.app/de/. Die Anleitung dient lediglich der Erläuterung und ist nicht Teil dieser Nutzungsbedingungen. </p> <p> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/InternalExposureNotificationPermissionHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/InternalExposureNotificationPermissionHelper.kt index 8891ecf4c886121cb5f558a8ed78acc47f861ea3..8f323857cad69c59d4cef408d21a50dd02062786 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/InternalExposureNotificationPermissionHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/InternalExposureNotificationPermissionHelper.kt @@ -69,11 +69,6 @@ class InternalExposureNotificationPermissionHelper( ResolutionRequestCodes.REQUEST_CODE_START_EXPOSURE_NOTIFICATION.code ) } catch (exception: Exception) { - exception.report( - ExceptionCategory.EXPOSURENOTIFICATION, - TAG, - null - ) returnError(exception) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt index c2390c53934f19b59cd874e6c890433efbdb3601..2b41203d1a08328f616c4eb19594fb2118b0ef29 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt @@ -89,7 +89,6 @@ class SettingsTracingFragment : Fragment(), override fun onFailure(exception: Exception?) { tracingViewModel.refreshIsTracingEnabled() - exception?.report(ExceptionCategory.EXPOSURENOTIFICATION) } private fun setButtonOnClickListener() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt index 92c15d7fcc3c1004d61795872581049075b4e6c7..663e77847cdd0b6906002fbc4386f64c3f9492d1 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt @@ -8,6 +8,7 @@ import android.view.ViewGroup import android.view.accessibility.AccessibilityEvent import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels +import androidx.lifecycle.Observer import androidx.navigation.fragment.findNavController import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey import de.rki.coronawarnapp.R @@ -35,8 +36,6 @@ class SubmissionResultPositiveOtherWarningFragment : Fragment(), private var _binding: FragmentSubmissionPositiveOtherWarningBinding? = null private val binding: FragmentSubmissionPositiveOtherWarningBinding get() = _binding!! - private var submissionRequested = false - private var submissionFailed = false private lateinit var internalExposureNotificationPermissionHelper: InternalExposureNotificationPermissionHelper @@ -44,20 +43,6 @@ class SubmissionResultPositiveOtherWarningFragment : Fragment(), super.onResume() binding.submissionPositiveOtherPrivacyContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) tracingViewModel.refreshIsTracingEnabled() - if (submissionRequested && !submissionFailed) { - internalExposureNotificationPermissionHelper.requestPermissionToShareKeys() - } - } - - override fun onKeySharePermissionGranted(keys: List<TemporaryExposureKey>) { - super.onKeySharePermissionGranted(keys) - submissionViewModel.submitDiagnosisKeys(keys) - } - - override fun onFailure(exception: Exception?) { - binding.submissionPositiveOtherWarningButtonNext.isEnabled = true - binding.submissionPositiveOtherWarningSpinner.visibility = View.GONE - submissionFailed = true } override fun onCreateView( @@ -68,6 +53,7 @@ class SubmissionResultPositiveOtherWarningFragment : Fragment(), internalExposureNotificationPermissionHelper = InternalExposureNotificationPermissionHelper(this, this) _binding = FragmentSubmissionPositiveOtherWarningBinding.inflate(inflater) + binding.submissionViewModel = submissionViewModel binding.lifecycleOwner = this return binding.root } @@ -141,17 +127,7 @@ class SubmissionResultPositiveOtherWarningFragment : Fragment(), DialogHelper.showDialog(buildErrorDialog(it)) }) - submissionViewModel.submissionState.observeEvent(viewLifecycleOwner, { - binding.submissionPositiveOtherWarningButtonNext.isEnabled = when (it) { - ApiRequestState.STARTED -> false - else -> true - } - - binding.submissionPositiveOtherWarningSpinner.visibility = when (it) { - ApiRequestState.STARTED -> View.VISIBLE - else -> View.GONE - } - + submissionViewModel.submissionState.observe(viewLifecycleOwner, Observer { if (it == ApiRequestState.SUCCESS) { findNavController().doNavigate( SubmissionResultPositiveOtherWarningFragmentDirections @@ -163,8 +139,6 @@ class SubmissionResultPositiveOtherWarningFragment : Fragment(), private fun setButtonOnClickListener() { binding.submissionPositiveOtherWarningButtonNext.setOnClickListener { - binding.submissionPositiveOtherWarningButtonNext.isEnabled = false - binding.submissionPositiveOtherWarningSpinner.visibility = View.VISIBLE initiateWarningOthers() } binding.submissionPositiveOtherWarningHeader.headerButtonBack.buttonIcon.setOnClickListener { @@ -190,7 +164,6 @@ class SubmissionResultPositiveOtherWarningFragment : Fragment(), return } - submissionRequested = true internalExposureNotificationPermissionHelper.requestPermissionToShareKeys() } @@ -200,4 +173,13 @@ class SubmissionResultPositiveOtherWarningFragment : Fragment(), resultCode ) } + + // InternalExposureNotificationPermissionHelper - callbacks + override fun onKeySharePermissionGranted(keys: List<TemporaryExposureKey>) { + super.onKeySharePermissionGranted(keys) + submissionViewModel.submitDiagnosisKeys(keys) + } + + override fun onFailure(exception: Exception?) { + } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt index 75fb016f71cd714e60f5619b02b04533ba0de779..95f2943ede4839da8c22d7c829dc534be427f405 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt @@ -28,7 +28,7 @@ class SubmissionViewModel : ViewModel() { private val _uiStateState = MutableLiveData(ApiRequestState.IDLE) private val _uiStateError = MutableLiveData<Event<CwaWebException>>(null) - private val _submissionState = MutableLiveData(Event(ApiRequestState.IDLE)) + private val _submissionState = MutableLiveData(ApiRequestState.IDLE) private val _submissionError = MutableLiveData<Event<CwaWebException>>(null) val scanStatus: LiveData<Event<ScanStatus>> = _scanStatus @@ -39,7 +39,7 @@ class SubmissionViewModel : ViewModel() { val uiStateState: LiveData<ApiRequestState> = _uiStateState val uiStateError: LiveData<Event<CwaWebException>> = _uiStateError - val submissionState: LiveData<Event<ApiRequestState>> = _submissionState + val submissionState: LiveData<ApiRequestState> = _submissionState val submissionError: LiveData<Event<CwaWebException>> = _submissionError val deviceRegistered get() = LocalData.registrationToken() != null @@ -49,19 +49,47 @@ class SubmissionViewModel : ViewModel() { val deviceUiState: LiveData<DeviceUIState> = SubmissionRepository.deviceUIState - fun submitDiagnosisKeys(keys: List<TemporaryExposureKey>) = - executeRequestWithStateForEvent( - { SubmissionService.asyncSubmitExposureKeys(keys) }, - _submissionState, - _submissionError - ) + fun submitDiagnosisKeys(keys: List<TemporaryExposureKey>) = viewModelScope.launch { + try { + _submissionState.value = ApiRequestState.STARTED + SubmissionService.asyncSubmitExposureKeys(keys) + _submissionState.value = ApiRequestState.SUCCESS + } catch (err: CwaWebException) { + _submissionError.value = Event(err) + _submissionState.value = ApiRequestState.FAILED + } catch (err: TransactionException) { + if (err.cause is CwaWebException) { + _submissionError.value = Event(err.cause) + } else { + err.report(ExceptionCategory.INTERNAL) + } + _submissionState.value = ApiRequestState.FAILED + } catch (err: Exception) { + _submissionState.value = ApiRequestState.FAILED + err.report(ExceptionCategory.INTERNAL) + } + } - fun doDeviceRegistration() = - executeRequestWithStateForEvent( - SubmissionService::asyncRegisterDevice, - _registrationState, - _registrationError - ) + fun doDeviceRegistration() = viewModelScope.launch { + try { + _registrationState.value = Event(ApiRequestState.STARTED) + SubmissionService.asyncRegisterDevice() + _registrationState.value = Event(ApiRequestState.SUCCESS) + } catch (err: CwaWebException) { + _registrationError.value = Event(err) + _registrationState.value = Event(ApiRequestState.FAILED) + } catch (err: TransactionException) { + if (err.cause is CwaWebException) { + _registrationError.value = Event(err.cause) + } else { + err.report(ExceptionCategory.INTERNAL) + } + _registrationState.value = Event(ApiRequestState.FAILED) + } catch (err: Exception) { + _registrationState.value = Event(ApiRequestState.FAILED) + err.report(ExceptionCategory.INTERNAL) + } + } fun refreshDeviceUIState() = executeRequestWithState( @@ -109,31 +137,4 @@ class SubmissionViewModel : ViewModel() { } } } - - private fun executeRequestWithStateForEvent( - apiRequest: suspend () -> Unit, - state: MutableLiveData<Event<ApiRequestState>>, - exceptionLiveData: MutableLiveData<Event<CwaWebException>>? = null - ) { - state.value = Event(ApiRequestState.STARTED) - viewModelScope.launch { - try { - apiRequest() - state.value = Event(ApiRequestState.SUCCESS) - } catch (err: CwaWebException) { - exceptionLiveData?.value = Event(err) - state.value = Event(ApiRequestState.FAILED) - } catch (err: TransactionException) { - if (err.cause is CwaWebException) { - exceptionLiveData?.value = Event(err.cause) - } else { - err.report(ExceptionCategory.INTERNAL) - } - state.value = Event(ApiRequestState.FAILED) - } catch (err: Exception) { - state.value = Event(ApiRequestState.FAILED) - err.report(ExceptionCategory.INTERNAL) - } - } - } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt index 10004cdffc7d5f33c48d8507ab3e35a78c40de9c..5d93578b11d500499650e901cb517d0b087e4cb7 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt @@ -21,6 +21,12 @@ fun formatTestResultSpinnerVisible(uiStateState: ApiRequestState?): Int = fun formatTestResultVisible(uiStateState: ApiRequestState?): Int = formatVisibility(uiStateState == ApiRequestState.SUCCESS) +fun formatSubmitButtonEnabled(apiRequestState: ApiRequestState) = + apiRequestState == ApiRequestState.IDLE || apiRequestState == ApiRequestState.FAILED + +fun formatSubmitSpinnerVisible(apiRequestState: ApiRequestState) = + formatVisibility(apiRequestState == ApiRequestState.STARTED) + fun formatTestResultStatusText(uiState: DeviceUIState?): String { val appContext = CoronaWarnApplication.getAppContext() return when (uiState) { @@ -192,8 +198,3 @@ fun formatShowRiskStatusCard(deviceUiState: DeviceUIState?): Int = deviceUiState != DeviceUIState.PAIRED_POSITIVE_TELETAN && deviceUiState != DeviceUIState.SUBMITTED_FINAL ) - -fun formatShowTanCharacterError( - charactersValid: Boolean, - checksumValid: Boolean -): Int = formatVisibility(checksumValid && !charactersValid) diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_positive_other_warning.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_positive_other_warning.xml index 638b1c894201a6da1191a8b311e1c360fd2db843..92dd63fe970143b79ed2d6532880d1dece9b2fa8 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_submission_positive_other_warning.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_positive_other_warning.xml @@ -3,11 +3,22 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> + <data> + + <import type="de.rki.coronawarnapp.util.formatter.FormatterSubmissionHelper" /> + + <variable + name="submissionViewModel" + type="de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel" /> + + </data> + + <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/submission_positive_other_privacy_container" - android:contentDescription="@string/submission_positive_other_warning_title" android:layout_width="match_parent" android:layout_height="match_parent" + android:contentDescription="@string/submission_positive_other_warning_title" android:fillViewport="true" tools:context=".ui.submission.SubmissionResultPositiveOtherWarningFragment"> @@ -38,6 +49,7 @@ style="@style/buttonPrimary" android:layout_width="@dimen/match_constraint" android:layout_height="wrap_content" + android:enabled="@{FormatterSubmissionHelper.formatSubmitButtonEnabled(submissionViewModel.submissionState)}" android:text="@string/submission_positive_other_warning_button" android:textAllCaps="true" app:layout_constraintBottom_toBottomOf="parent" @@ -52,7 +64,7 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_large" android:indeterminate="true" - android:visibility="gone" + android:visibility="@{FormatterSubmissionHelper.formatSubmitSpinnerVisible(submissionViewModel.submissionState)}" app:layout_constraintBottom_toBottomOf="@+id/submission_positive_other_warning_button_next" app:layout_constraintEnd_toEndOf="@+id/submission_positive_other_warning_button_next" app:layout_constraintStart_toStartOf="@+id/submission_positive_other_warning_button_next" diff --git a/Corona-Warn-App/src/main/res/values-de/strings.xml b/Corona-Warn-App/src/main/res/values-de/strings.xml index dd23faa71c8d93e70d6118da77bae6fd24a405c7..2288d8e612eb76998fdc4fd4df0ebbfc74376a25 100644 --- a/Corona-Warn-App/src/main/res/values-de/strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/strings.xml @@ -839,7 +839,7 @@ <!-- YTXT: Body text for step 2 of contact page--> <string name="submission_contact_step_2_body">"Test per TAN-Eingabe in der App registrieren"</string> <!-- YTXT: Body text for operating hours in contact page--> - <string name="submission_contact_operating_hours_body">"Sprachen: Deutsch, Englisch, Türkisch \nErreichbarkeit:\nMo - Fr: 08:00 - 22:00 Uhr\nSa - So: 10:00 - 22:00 Uhr\nDer Anruf ist kostenfrei."</string> + <string name="submission_contact_operating_hours_body">"Sprachen:\nDeutsch, Englisch, Türkisch\n\nErreichbarkeit:\nMo - So: Täglich 24 Stunden\n\nDer Anruf ist kostenfrei."</string> <!-- XACT: Submission contact page title --> <string name="submission_contact_accessibility_title">"TAN-Anfrage per Telefonanruf"</string> diff --git a/Corona-Warn-App/src/main/res/values-en/strings.xml b/Corona-Warn-App/src/main/res/values-en/strings.xml index 61f0ab3ff371190ec509517d85b6282d18223fb2..f0973f098b4aacffccb1f6e2369ba319bb24c06b 100644 --- a/Corona-Warn-App/src/main/res/values-en/strings.xml +++ b/Corona-Warn-App/src/main/res/values-en/strings.xml @@ -839,7 +839,7 @@ <!-- YTXT: Body text for step 2 of contact page--> <string name="submission_contact_step_2_body">"Register the test by entering the TAN in the app."</string> <!-- YTXT: Body text for operating hours in contact page--> - <string name="submission_contact_operating_hours_body">"Languages: \nGerman, English, Turkish\n\nBusiness hours:\nMonday to Friday: 8am - 10pm; \nSaturday to Sunday: 10am - 10pm\n\nThe call is free of charge."</string> + <string name="submission_contact_operating_hours_body">"Languages: \nGerman, English, Turkish\n\nBusiness hours:\nMonday to Sunday: 24 hours\n\nThe call is free of charge."</string> <!-- XACT: Submission contact page title --> <string name="submission_contact_accessibility_title">"Call the hotline and request a TAN"</string> diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml index 61f0ab3ff371190ec509517d85b6282d18223fb2..f0973f098b4aacffccb1f6e2369ba319bb24c06b 100644 --- a/Corona-Warn-App/src/main/res/values/strings.xml +++ b/Corona-Warn-App/src/main/res/values/strings.xml @@ -839,7 +839,7 @@ <!-- YTXT: Body text for step 2 of contact page--> <string name="submission_contact_step_2_body">"Register the test by entering the TAN in the app."</string> <!-- YTXT: Body text for operating hours in contact page--> - <string name="submission_contact_operating_hours_body">"Languages: \nGerman, English, Turkish\n\nBusiness hours:\nMonday to Friday: 8am - 10pm; \nSaturday to Sunday: 10am - 10pm\n\nThe call is free of charge."</string> + <string name="submission_contact_operating_hours_body">"Languages: \nGerman, English, Turkish\n\nBusiness hours:\nMonday to Sunday: 24 hours\n\nThe call is free of charge."</string> <!-- XACT: Submission contact page title --> <string name="submission_contact_accessibility_title">"Call the hotline and request a TAN"</string>