diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/notification/ShareTestResultNotificationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/notification/ShareTestResultNotificationService.kt index 8167c755062461038f838520f8be4f17dd77b85f..fc4799ce95d70c5def84b4f89cc4c349e6c54ba6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/notification/ShareTestResultNotificationService.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/notification/ShareTestResultNotificationService.kt @@ -1,5 +1,6 @@ package de.rki.coronawarnapp.coronatest.notification +import de.rki.coronawarnapp.bugreporting.reportProblem import de.rki.coronawarnapp.coronatest.CoronaTestRepository import de.rki.coronawarnapp.coronatest.latestPCRT import de.rki.coronawarnapp.coronatest.latestRAT @@ -10,6 +11,7 @@ import de.rki.coronawarnapp.main.CWASettings import de.rki.coronawarnapp.notification.NotificationConstants.POSITIVE_RESULT_NOTIFICATION_TOTAL_COUNT import de.rki.coronawarnapp.util.coroutine.AppScope import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import timber.log.Timber @@ -26,7 +28,6 @@ class ShareTestResultNotificationService @Inject constructor( fun setup() { Timber.d("setup()") - // Schedule positive test reminders schedulePositiveTestsReminder() // if no PCR test is stored or if it was deleted, we reset the reminder resetPositivePCRTestReminder() @@ -59,54 +60,48 @@ class ShareTestResultNotificationService @Inject constructor( private fun resetPositivePCRTestReminder() { Timber.tag(TAG).v("resetPositivePCRTestReminder") - try { - coronaTestRepository.latestPCRT - .onEach { - if (it == null) { - resetSharePositiveTestResultNotification(PCR) - } + coronaTestRepository.latestPCRT // This should not crash ,it is just a flow already constructed + .onEach { + if (it == null) { + resetSharePositiveTestResultNotification(PCR) } - .launchIn(appScope) - } catch (e: Exception) { - Timber.tag(TAG).e(e, "Failed to reset positive test result reminder for PCR test.") - } + } + // Catch error in onEach block + .catch { it.reportProblem("Failed to reset positive test result reminder for PCR test.") } + .launchIn(appScope) } private fun resetPositiveRATTestReminder() { Timber.tag(TAG).v("resetPositiveRATTestReminder") - try { - coronaTestRepository.latestRAT - .onEach { - if (it == null) { - resetSharePositiveTestResultNotification(RAPID_ANTIGEN) - } + coronaTestRepository.latestRAT // This should not crash ,it is just a flow already constructed + .onEach { + if (it == null) { + resetSharePositiveTestResultNotification(RAPID_ANTIGEN) } - .launchIn(appScope) - } catch (e: Exception) { - Timber.tag(TAG).e(e, "Failed to reset positive test result reminder for RAT test.") - } + } + // Catch error in onEach block + .catch { it.reportProblem("Failed to reset positive test result reminder for RAT test.") } + .launchIn(appScope) } private fun schedulePositiveTestsReminder() { Timber.tag(TAG).v("schedulePositiveTestsReminder") - try { - coronaTestRepository.coronaTests - .onEach { tests -> - // schedule reminder if test wasn't submitted - tests.filter { test -> - test.isSubmissionAllowed && !test.isSubmitted - }.forEach { test -> - maybeScheduleSharePositiveTestResultReminder(test.type) - } - - // cancel the reminder when test is submitted - tests.filter { it.isSubmitted } - .forEach { notification.cancelSharePositiveTestResultNotification(it.type) } + coronaTestRepository.coronaTests // This should not crash ,it is just a flow already constructed + .onEach { tests -> + // schedule reminder if test wasn't submitted + tests.filter { test -> + test.isSubmissionAllowed && !test.isSubmitted + }.forEach { test -> + maybeScheduleSharePositiveTestResultReminder(test.type) } - .launchIn(appScope) - } catch (e: Exception) { - Timber.e(e, "Failed to schedule positive test result reminder.") - } + + // cancel the reminder when test is submitted + tests.filter { it.isSubmitted } + .forEach { notification.cancelSharePositiveTestResultNotification(it.type) } + } + // Catch error in onEach block + .catch { it.reportProblem("Failed to schedule positive test result reminder.") } + .launchIn(appScope) } private fun maybeScheduleSharePositiveTestResultReminder(testType: CoronaTest.Type) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/notification/PCRTestResultAvailableNotificationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/notification/PCRTestResultAvailableNotificationService.kt index 1a2dd6872c13a09509dd74816e9bae3b6f8dbb1a..ac6b2653a2132dfa85687d8d2d1f6ff9363f079a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/notification/PCRTestResultAvailableNotificationService.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/notification/PCRTestResultAvailableNotificationService.kt @@ -3,6 +3,7 @@ package de.rki.coronawarnapp.coronatest.type.pcr.notification import android.content.Context import androidx.navigation.NavDeepLinkBuilder import de.rki.coronawarnapp.coronatest.CoronaTestRepository +import de.rki.coronawarnapp.coronatest.errors.CoronaTestNotFoundException import de.rki.coronawarnapp.coronatest.latestPCRT import de.rki.coronawarnapp.coronatest.server.CoronaTestResult import de.rki.coronawarnapp.coronatest.type.common.TestResultAvailableNotificationService @@ -64,7 +65,11 @@ class PCRTestResultAvailableNotificationService @Inject constructor( notSentYet && isInteresting -> { Timber.tag(TAG).d("Showing PCR test result notification.") showTestResultAvailableNotification(test) - coronaTestRepository.updateResultNotification(identifier = test.identifier, sent = true) + try { + coronaTestRepository.updateResultNotification(identifier = test.identifier, sent = true) + } catch (e: CoronaTestNotFoundException) { + Timber.tag(TAG).e(e, "updateResultNotification failed") + } notificationHelper.cancelCurrentNotification( NotificationConstants.NEW_MESSAGE_RISK_LEVEL_SCORE_NOTIFICATION_ID ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/notification/RATTestResultAvailableNotificationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/notification/RATTestResultAvailableNotificationService.kt index 49fd8b04f991b4596609052462ea70fa4e9bb9aa..25a66a488359f4e7478f9a7d4671eef062d52693 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/notification/RATTestResultAvailableNotificationService.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/notification/RATTestResultAvailableNotificationService.kt @@ -3,6 +3,7 @@ package de.rki.coronawarnapp.coronatest.type.rapidantigen.notification import android.content.Context import androidx.navigation.NavDeepLinkBuilder import de.rki.coronawarnapp.coronatest.CoronaTestRepository +import de.rki.coronawarnapp.coronatest.errors.CoronaTestNotFoundException import de.rki.coronawarnapp.coronatest.latestRAT import de.rki.coronawarnapp.coronatest.server.CoronaTestResult import de.rki.coronawarnapp.coronatest.type.common.TestResultAvailableNotificationService @@ -63,7 +64,11 @@ class RATTestResultAvailableNotificationService @Inject constructor( notSentYet && isInteresting -> { Timber.tag(TAG).d("Showing RA test result notification.") showTestResultAvailableNotification(test) - coronaTestRepository.updateResultNotification(identifier = test.identifier, sent = true) + try { + coronaTestRepository.updateResultNotification(identifier = test.identifier, sent = true) + } catch (e: CoronaTestNotFoundException) { + Timber.tag(TAG).e(e, "updateResultNotification failed") + } notificationHelper.cancelCurrentNotification( NotificationConstants.NEW_MESSAGE_RISK_LEVEL_SCORE_NOTIFICATION_ID ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionRepository.kt index 70549aee1c17eb4acd80e6bdc2b7004a6e08b1ad..02092bb927dd58f9f18a50efabd426d89e152d1b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionRepository.kt @@ -15,6 +15,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @@ -44,9 +45,9 @@ class SubmissionRepository @Inject constructor( val currentSymptoms = submissionSettings.symptoms // to be used by new submission flow screens - fun giveConsentToSubmission(type: CoronaTest.Type) { + suspend fun giveConsentToSubmission(type: CoronaTest.Type) { Timber.tag(TAG).v("giveConsentToSubmission(type=%s)", type) - scope.launch { + withContext(scope.coroutineContext) { val test = coronaTestRepository.coronaTests.first().singleOrNull { it.type == type } ?: throw IllegalStateException("No test of type $type available") Timber.tag(TAG).v("giveConsentToSubmission(type=$type): %s", test) @@ -55,9 +56,9 @@ class SubmissionRepository @Inject constructor( } // to be used by new submission flow screens - fun revokeConsentToSubmission(type: CoronaTest.Type) { + suspend fun revokeConsentToSubmission(type: CoronaTest.Type) { Timber.tag(TAG).v("revokeConsentToSubmission(type=%s)", type) - scope.launch { + withContext(scope.coroutineContext) { val test = coronaTestRepository.coronaTests.first().singleOrNull { it.type == type } ?: throw IllegalStateException("No test of type $type available") @@ -66,9 +67,9 @@ class SubmissionRepository @Inject constructor( } // to be set to true once the user has opened and viewed their test result - fun setViewedTestResult(type: CoronaTest.Type) { + suspend fun setViewedTestResult(type: CoronaTest.Type) { Timber.tag(TAG).v("setViewedTestResult(type=%s)", type) - scope.launch { + withContext(scope.coroutineContext) { val test = coronaTestRepository.coronaTests.first().singleOrNull { it.type == type } ?: throw IllegalStateException("No test of type $type available") @@ -76,10 +77,10 @@ class SubmissionRepository @Inject constructor( } } - fun refreshTest(type: CoronaTest.Type? = null) { + suspend fun refreshTest(type: CoronaTest.Type? = null) { Timber.tag(TAG).v("refreshTest(type=%s)", type) - scope.launch { + withContext(scope.coroutineContext) { coronaTestRepository.refresh(type = type) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt index 0921d2f093d0da987c76535badef71cc4db242f2..bda8566ff07baf6857daa64eafd76c1da555013b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt @@ -136,6 +136,10 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject { }?.show() } } + + viewModel.errorEvent.observe2(this) { + it.toErrorDialogBuilder(requireContext()).show() + } } override fun onResume() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt index 922423eaaf0b071377d7af7e80cbc67caa0e69ad..2ab3ce80e760ff68cba51e7909ff93506910d316 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt @@ -8,6 +8,7 @@ import dagger.assisted.AssistedInject import de.rki.coronawarnapp.appconfig.AppConfigProvider import de.rki.coronawarnapp.appconfig.CoronaTestConfig import de.rki.coronawarnapp.coronatest.CoronaTestRepository +import de.rki.coronawarnapp.coronatest.errors.CoronaTestNotFoundException import de.rki.coronawarnapp.coronatest.latestPCRT import de.rki.coronawarnapp.coronatest.latestRAT import de.rki.coronawarnapp.coronatest.testErrorsSingleEvent @@ -74,6 +75,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach +import timber.log.Timber @Suppress("LongParameterList") class HomeFragmentViewModel @AssistedInject constructor( @@ -100,6 +102,7 @@ class HomeFragmentViewModel @AssistedInject constructor( val openFAQUrlEvent = SingleLiveEvent<Unit>() val openIncompatibleEvent = SingleLiveEvent<Unit>() val openTraceLocationOrganizerFlow = SingleLiveEvent<Unit>() + val errorEvent = SingleLiveEvent<Throwable>() val tracingHeaderState: LiveData<TracingHeaderState> = tracingStatus.generalStatus .map { it.toHeaderState() } @@ -286,7 +289,6 @@ class HomeFragmentViewModel @AssistedInject constructor( ) { tracingItem, testPCR, testRAT, statsData, coronaTestParameters -> val statePCR = testPCR.toSubmissionState() val stateRAT = testRAT.toSubmissionState(timeStamper.nowUTC, coronaTestParameters) - val bothTestStates = setOf(statePCR, stateRAT) mutableListOf<HomeItem>().apply { when { statePCR is SubmissionStatePCR.TestPositive || statePCR is SubmissionStatePCR.SubmissionDone -> { @@ -374,7 +376,12 @@ class HomeFragmentViewModel @AssistedInject constructor( fun refreshRequiredData() { launch { - submissionRepository.refreshTest() + try { + submissionRepository.refreshTest() + } catch (e: CoronaTestNotFoundException) { + Timber.e(e, "refreshTest failed") + errorEvent.postValue(e) + } tracingRepository.refreshRiskLevel() } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableViewModel.kt index dadb6672622aee60d7d16d7732f0da963f30bba4..5e30dd35e67d393d7c1eb6d979cf24dc95330955 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableViewModel.kt @@ -98,10 +98,6 @@ class SubmissionTestResultAvailableViewModel @AssistedInject constructor( } ) - init { - submissionRepository.refreshTest(type = testType) - } - fun goBack() { showCloseDialog.postValue(Unit) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/invalid/SubmissionTestResultInvalidFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/invalid/SubmissionTestResultInvalidFragment.kt index 260b40ed42ac2e2ac116bac144dba491046fd0c4..0214619816cb56365f8a727bb575cf764c31198d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/invalid/SubmissionTestResultInvalidFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/invalid/SubmissionTestResultInvalidFragment.kt @@ -37,6 +37,8 @@ class SubmissionTestResultInvalidFragment : Fragment(R.layout.fragment_submissio override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + viewModel.onTestOpened() + binding.apply { submissionTestResultButtonInvalidRemoveTest.setOnClickListener { removeTestAfterConfirmation() } submissionTestResultHeader.headerButtonBack.buttonIcon.setOnClickListener { popBackStack() } @@ -54,7 +56,6 @@ class SubmissionTestResultInvalidFragment : Fragment(R.layout.fragment_submissio override fun onResume() { super.onResume() binding.submissionTestResultContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) - viewModel.onTestOpened() } private fun removeTestAfterConfirmation() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/negative/SubmissionTestResultNegativeFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/negative/SubmissionTestResultNegativeFragment.kt index 082c4a3b8bd6a1da185ffabdde0718ee0ef2e5e5..7e164e0881f6b3549839d1a379d1c2d295b72110 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/negative/SubmissionTestResultNegativeFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/negative/SubmissionTestResultNegativeFragment.kt @@ -37,6 +37,8 @@ class SubmissionTestResultNegativeFragment : Fragment(R.layout.fragment_submissi override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + viewModel.onTestOpened() + binding.apply { submissionTestResultButtonNegativeRemoveTest.setOnClickListener { removeTestAfterConfirmation() } submissionTestResultHeader.headerButtonBack.buttonIcon.setOnClickListener { popBackStack() } @@ -54,7 +56,6 @@ class SubmissionTestResultNegativeFragment : Fragment(R.layout.fragment_submissi override fun onResume() { super.onResume() binding.submissionTestResultContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) - viewModel.onTestOpened() } private fun removeTestAfterConfirmation() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt index 096b1c81a56c7455a3f398ea0f8683c87a1d676a..31e7e029ebd06b913f46ce5e2c62a49d3e44ae7c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt @@ -7,6 +7,7 @@ import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import androidx.navigation.fragment.navArgs import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentSubmissionTestResultPendingBinding import de.rki.coronawarnapp.exception.http.CwaClientError import de.rki.coronawarnapp.exception.http.CwaServerError @@ -63,7 +64,7 @@ class SubmissionTestResultPendingFragment : Fragment(R.layout.fragment_submissio binding.apply { submissionTestResultButtonPendingRefresh.setOnClickListener { - pendingViewModel.refreshDeviceUIState() + pendingViewModel.updateTestResult() binding.submissionTestResultSection.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED) } @@ -90,12 +91,14 @@ class SubmissionTestResultPendingFragment : Fragment(R.layout.fragment_submissio pendingViewModel.routeToScreen.observe2(this) { it?.let { doNavigate(it) } ?: navigateToMainScreen() } + pendingViewModel.errorEvent.observe2(this) { + it.toErrorDialogBuilder(requireContext()).show() + } } override fun onResume() { super.onResume() binding.submissionTestResultContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) - pendingViewModel.refreshDeviceUIState() skipInitialTestResultRefresh = false pendingViewModel.cwaWebExceptionLiveData.observeOnce(this.viewLifecycleOwner) { exception -> handleError(exception) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingViewModel.kt index d7300a8b70e8f2db57eb47152aaed28e85dec75c..d6f6e854ebe333abc5a5ef14905c5352a3eaccdc 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingViewModel.kt @@ -35,6 +35,7 @@ class SubmissionTestResultPendingViewModel @AssistedInject constructor( } val routeToScreen = SingleLiveEvent<NavDirections?>() + val errorEvent = SingleLiveEvent<Throwable>() val showRedeemedTokenWarning = SingleLiveEvent<Unit>() val consentGiven = submissionRepository.testForType(type = testType).map { @@ -103,9 +104,13 @@ class SubmissionTestResultPendingViewModel @AssistedInject constructor( routeToScreen.postValue(null) } - fun refreshDeviceUIState() = launch { - Timber.v("refreshDeviceUIState()") - submissionRepository.refreshTest(type = testType) + fun updateTestResult() = launch { + Timber.v("updateTestResult()") + try { + submissionRepository.refreshTest(type = testType) + } catch (e: Exception) { + errorEvent.postValue(e) + } } fun onConsentClicked() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt index 8c6448f7b5684357020b97961cdf31bee20c28e2..5ac4b198130999fcf14501a6e81fcf7b63caaf09 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt @@ -43,6 +43,8 @@ class SubmissionTestResultNoConsentFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + viewModel.onTestOpened() + val backCallback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { showCancelDialog() @@ -70,7 +72,6 @@ class SubmissionTestResultNoConsentFragment : override fun onResume() { super.onResume() appShortcutsHelper.removeAppShortcut() - viewModel.onTestOpened() binding.submissionTestResultContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentFragment.kt index 4a7463b4d99504fe70f1d397840088db8efb1816..6fbff88ab60419f4f7ff9ddd8ec708d5c73736a6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentFragment.kt @@ -6,6 +6,7 @@ import android.view.accessibility.AccessibilityEvent import androidx.fragment.app.Fragment import androidx.navigation.fragment.navArgs import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentSubmissionYourConsentBinding import de.rki.coronawarnapp.ui.main.MainActivity import de.rki.coronawarnapp.util.di.AutoInject @@ -76,6 +77,10 @@ class SubmissionYourConsentFragment : Fragment(R.layout.fragment_submission_your } ) } + + vm.errorEvent.observe2(this) { + it.toErrorDialogBuilder(requireContext()).show() + } } override fun onResume() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentViewModel.kt index 13788225fdd54b616c69c5dfd8e46ec3ccd54a3c..826af6f621028d7e8260849191993a50fada4a5a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentViewModel.kt @@ -28,6 +28,7 @@ class SubmissionYourConsentViewModel @AssistedInject constructor( } val clickEvent: SingleLiveEvent<SubmissionYourConsentEvents> = SingleLiveEvent() + val errorEvent = SingleLiveEvent<Throwable>() private val consentFlow = submissionRepository.testForType(type = testType) .filterNotNull() .map { it.isAdvancedConsentGiven } @@ -41,12 +42,17 @@ class SubmissionYourConsentViewModel @AssistedInject constructor( } fun switchConsent() = launch { - if (consentFlow.first()) { - Timber.v("revokeConsentToSubmission()") - submissionRepository.revokeConsentToSubmission(type = testType) - } else { - Timber.v("giveConsentToSubmission()") - submissionRepository.giveConsentToSubmission(type = testType) + try { + if (consentFlow.first()) { + Timber.v("revokeConsentToSubmission()") + submissionRepository.revokeConsentToSubmission(type = testType) + } else { + Timber.v("giveConsentToSubmission()") + submissionRepository.giveConsentToSubmission(type = testType) + } + } catch (e: Exception) { + Timber.e(e, "switchConsent()") + errorEvent.postValue(e) } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/testresult/pending/SubmissionTestResultPendingViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/testresult/pending/SubmissionTestResultPendingViewModelTest.kt index 4d4c07cbafcb1e682049f28e99e49d875d106588..9db51d8a72e1bc6963746d1fc014be953b9eb4af 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/testresult/pending/SubmissionTestResultPendingViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/testresult/pending/SubmissionTestResultPendingViewModelTest.kt @@ -7,6 +7,7 @@ import de.rki.coronawarnapp.ui.submission.testresult.pending.SubmissionTestResul import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.Runs +import io.mockk.coEvery import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.just @@ -35,7 +36,7 @@ class SubmissionTestResultPendingViewModelTest : BaseTest() { submissionRepository.apply { every { testForType(any()) } returns testFlow - every { setViewedTestResult(any()) } just Runs + coEvery { setViewedTestResult(any()) } just Runs } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt index c3f66c812d1ff2ba55f9ab120f21185b31435381..41eb4280816b12a78fe0c6ba1e830ae58188aeb9 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt @@ -45,7 +45,7 @@ class SubmissionConsentViewModelTest { fun setUp() { MockKAnnotations.init(this) every { interoperabilityRepository.countryList } returns MutableStateFlow(countryList) - every { submissionRepository.giveConsentToSubmission(any()) } just Runs + coEvery { submissionRepository.giveConsentToSubmission(any()) } just Runs coEvery { qrCodeRegistrationStateProcessor.showRedeemedTokenWarning } returns SingleLiveEvent() coEvery { qrCodeRegistrationStateProcessor.registrationState } returns MutableLiveData( QrCodeRegistrationStateProcessor.RegistrationState(ApiRequestState.IDLE) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testavailable/SubmissionTestResultAvailableViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testavailable/SubmissionTestResultAvailableViewModelTest.kt index fad77e25164561a6928eb11a15575266f5f2804b..163c05530dcae7e07429b90c5fe66c0a88419128 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testavailable/SubmissionTestResultAvailableViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testavailable/SubmissionTestResultAvailableViewModelTest.kt @@ -14,6 +14,7 @@ import de.rki.coronawarnapp.ui.submission.resultavailable.SubmissionTestResultAv import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.Runs +import io.mockk.coEvery import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.just @@ -55,7 +56,7 @@ class SubmissionTestResultAvailableViewModelTest : BaseTest() { // TODO Check specific behavior submissionRepository.apply { - every { refreshTest(any()) } just Runs + coEvery { refreshTest(any()) } just Runs every { testForType(type = any()) } returns coronaTestFlow } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModelTest.kt index 3e16e938556fca6f03e13e043987cc0dffff9dcc..a69425f454903005cd4e9d07ab0b6742cfc58157 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModelTest.kt @@ -13,6 +13,8 @@ import de.rki.coronawarnapp.submission.auto.AutoSubmission import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryUpdater import io.mockk.MockKAnnotations import io.mockk.Runs +import io.mockk.coEvery +import io.mockk.coVerify import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.just @@ -57,7 +59,7 @@ class SubmissionResultPositiveOtherWarningNoConsentViewModelTest : BaseTest() { every { interoperabilityRepository.countryList } returns emptyFlow() submissionRepository.apply { - every { giveConsentToSubmission(any()) } just Runs + coEvery { giveConsentToSubmission(any()) } just Runs every { testForType(any()) } returns coronaTestFlow } @@ -87,7 +89,7 @@ class SubmissionResultPositiveOtherWarningNoConsentViewModelTest : BaseTest() { viewModel.onConsentButtonClicked() - verify { submissionRepository.giveConsentToSubmission(any()) } + coVerify { submissionRepository.giveConsentToSubmission(any()) } verify { tekHistoryUpdater.updateTEKHistoryOrRequestPermission() } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentViewModelTest.kt index 5a81ac156199fde1b94883142a459884d1cb0791..df449ddd86a9903b40a22f84c9e97e03bcf7d848 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentViewModelTest.kt @@ -7,11 +7,12 @@ import de.rki.coronawarnapp.ui.Country import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.Runs +import io.mockk.coEvery +import io.mockk.coVerify import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.just import io.mockk.mockk -import io.mockk.verify import kotlinx.coroutines.flow.MutableStateFlow import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -41,8 +42,8 @@ class SubmissionYourConsentViewModelTest : BaseTest() { MockKAnnotations.init(this) every { submissionRepository.testForType(any()) } returns coronaTestFlow every { interoperabilityRepository.countryList } returns MutableStateFlow(countryList) - every { submissionRepository.giveConsentToSubmission(any()) } just Runs - every { submissionRepository.revokeConsentToSubmission(any()) } just Runs + coEvery { submissionRepository.giveConsentToSubmission(any()) } just Runs + coEvery { submissionRepository.revokeConsentToSubmission(any()) } just Runs } private fun createViewModel(): SubmissionYourConsentViewModel = SubmissionYourConsentViewModel( @@ -75,7 +76,7 @@ class SubmissionYourConsentViewModelTest : BaseTest() { } createViewModel().switchConsent() - verify(exactly = 1) { submissionRepository.revokeConsentToSubmission(any()) } + coVerify(exactly = 1) { submissionRepository.revokeConsentToSubmission(any()) } } @Test @@ -85,7 +86,7 @@ class SubmissionYourConsentViewModelTest : BaseTest() { } createViewModel().switchConsent() - verify(exactly = 1) { submissionRepository.giveConsentToSubmission(any()) } + coVerify(exactly = 1) { submissionRepository.giveConsentToSubmission(any()) } } @Test