From df7a5fbb314675010062660824f7c5a6bff5e3b9 Mon Sep 17 00:00:00 2001 From: Kolya Opahle <k.opahle@sap.com> Date: Mon, 16 Nov 2020 18:23:30 +0100 Subject: [PATCH] =?UTF-8?q?Cannot=20delete=20tests=20older=20than=2021=20d?= =?UTF-8?q?ays=20-=20DE:=20Tests=20die=20=C3=A4lter=20als=2021=20Tage=20si?= =?UTF-8?q?nd,=20k=C3=B6nnen=20nicht=20gel=C3=B6scht=20werden=20(EXPOSUREA?= =?UTF-8?q?PP-2398)=20(#1586)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 1. Replaced redundant uiStateState during test result fetch with a NetworkRequestWrapper that is able to represent multiple states. This allows for better request state handling throughout the app 2. Completely removed the SubmissionViewModel 3. Failure to fetch the test should now always display the invalid test card on the home screen Signed-off-by: Kolya Opahle <k.opahle@sap.com> * Keep displaying fetching card on server errors as this usually does not indicate any problems with the test itself Signed-off-by: Kolya Opahle <k.opahle@sap.com> * Fixing unit tests (mostly just syntax, one test case changed due to new card) Signed-off-by: Kolya Opahle <k.opahle@sap.com> * Promoted unknown host exception to server exception Co-authored-by: chris-cwa <69595386+chris-cwa@users.noreply.github.com> Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com> --- .../ui/TestRiskLevelCalculationFragment.kt | 7 +- ...iskLevelCalculationFragmentCWAViewModel.kt | 6 + .../fragment_test_risk_level_calculation.xml | 6 +- .../exception/http/CwaWebException.kt | 2 +- .../rki/coronawarnapp/http/HttpErrorParser.kt | 3 + .../storage/SubmissionRepository.kt | 34 ++- .../ui/main/home/SubmissionCardState.kt | 137 +++++++----- .../main/home/SubmissionCardsStateProvider.kt | 8 +- .../SubmissionTestResultFragment.kt | 11 +- .../SubmissionTestResultViewModel.kt | 25 ++- .../testresult/TestResultUIState.kt | 5 +- .../ui/viewmodel/SubmissionViewModel.kt | 12 -- .../util/NetworkRequestWrapper.kt | 30 +++ .../formatter/FormatterSubmissionHelper.kt | 139 ++++++------ .../fragment_submission_symptom_calendar.xml | 4 - .../fragment_submission_symptom_intro.xml | 4 - .../fragment_submission_test_result.xml | 4 +- ...de_submission_symptom_length_selection.xml | 4 - .../res/layout/include_test_result_card.xml | 2 +- .../main/home/HomeFragmentViewModelTest.kt | 6 +- .../main/home/SubmissionCardStateTest.kt | 21 +- .../home/SubmissionCardsStateProviderTest.kt | 11 +- .../FormatterSubmissionHelperTest.kt | 197 ++++++++++-------- 23 files changed, 386 insertions(+), 292 deletions(-) delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt index 0867b6e6b..f9834cdc7 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt @@ -15,7 +15,6 @@ import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange import de.rki.coronawarnapp.sharing.ExposureSharingService import de.rki.coronawarnapp.test.menu.ui.TestMenuItem import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel -import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.viewBindingLazy @@ -39,7 +38,6 @@ class TestRiskLevelCalculationFragment : Fragment(R.layout.fragment_test_risk_le ) private val settingsViewModel: SettingsViewModel by activityViewModels() - private val submissionViewModel: SubmissionViewModel by activityViewModels() private val binding: FragmentTestRiskLevelCalculationBinding by viewBindingLazy() @@ -51,7 +49,10 @@ class TestRiskLevelCalculationFragment : Fragment(R.layout.fragment_test_risk_le } binding.settingsViewModel = settingsViewModel - binding.submissionViewModel = submissionViewModel + + vm.showRiskStatusCard.observe2(this) { + binding.showRiskStatusCard = it + } binding.buttonRetrieveDiagnosisKeys.setOnClickListener { vm.retrieveDiagnosisKeys() } binding.buttonProvideKeyViaQr.setOnClickListener { vm.scanLocalQRCodeAndProvide() } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt index 765ac237e..0294d6b5b 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt @@ -22,11 +22,13 @@ import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange import de.rki.coronawarnapp.storage.AppDatabase import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.RiskLevelRepository +import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.task.TaskController import de.rki.coronawarnapp.task.common.DefaultTaskRequest import de.rki.coronawarnapp.task.submitBlocking import de.rki.coronawarnapp.ui.tracing.card.TracingCardStateProvider import de.rki.coronawarnapp.util.KeyFileHelper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.di.AppInjector @@ -35,6 +37,7 @@ import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.sample import kotlinx.coroutines.withContext import timber.log.Timber @@ -63,6 +66,9 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( val riskLevelResetEvent = SingleLiveEvent<Unit>() val apiKeysProvidedEvent = SingleLiveEvent<DiagnosisKeyProvidedEvent>() val riskScoreState = MutableLiveData<RiskScoreState>(RiskScoreState()) + val showRiskStatusCard = SubmissionRepository.deviceUIStateFlow.map { + it.withSuccess(false) { true } + }.asLiveData(dispatcherProvider.Default) val tracingCardState = tracingCardStateProvider.state .sample(150L) diff --git a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml index 9e29d88d4..a58a1ff43 100644 --- a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml +++ b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml @@ -11,8 +11,8 @@ <import type="de.rki.coronawarnapp.util.formatter.FormatterSubmissionHelper" /> <variable - name="submissionViewModel" - type="de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel" /> + name="showRiskStatusCard" + type="Boolean" /> <variable name="settingsViewModel" @@ -48,7 +48,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_normal" - android:visibility="@{FormatterSubmissionHelper.formatShowRiskStatusCard(submissionViewModel.deviceUiState)}" + gone="@{showRiskStatusCard == null || !showRiskStatusCard}" android:focusable="true" android:backgroundTint="@{tracingCard.getRiskInfoContainerBackgroundTint(context)}" android:backgroundTintMode="src_over"> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt index 4fa8b6eff..fc89eff46 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt @@ -27,7 +27,6 @@ open class CwaSuccessResponseWithCodeMismatchNotSupportedError(statusCode: Int) open class CwaInformationalNotSupportedError(statusCode: Int) : CwaWebException(statusCode) open class CwaRedirectNotSupportedError(statusCode: Int) : CwaWebException(statusCode) -class CwaUnknownHostException : CwaWebException(901) class BadRequestException : CwaClientError(400) class UnauthorizedException : CwaClientError(401) class ForbiddenException : CwaClientError(403) @@ -44,5 +43,6 @@ class ServiceUnavailableException : CwaServerError(503) class GatewayTimeoutException : CwaServerError(504) class HTTPVersionNotSupported : CwaServerError(505) class NetworkAuthenticationRequiredException : CwaServerError(511) +class CwaUnknownHostException : CwaServerError(597) class NetworkReadTimeoutException : CwaServerError(598) class NetworkConnectTimeoutException : CwaServerError(599) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt index bc347abb9..1061abc7e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt @@ -26,6 +26,7 @@ import de.rki.coronawarnapp.exception.http.UnauthorizedException import de.rki.coronawarnapp.exception.http.UnsupportedMediaTypeException import okhttp3.Interceptor import okhttp3.Response +import java.net.SocketTimeoutException import java.net.UnknownHostException import javax.net.ssl.HttpsURLConnection @@ -66,6 +67,8 @@ class HttpErrorParser : Interceptor { throw CwaWebException(code) } } + } catch (err: SocketTimeoutException) { + throw NetworkConnectTimeoutException() } catch (err: UnknownHostException) { throw CwaUnknownHostException() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt index b601e6d77..62ae3efc8 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt @@ -1,16 +1,13 @@ package de.rki.coronawarnapp.storage -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.asLiveData import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.service.submission.SubmissionService -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState -import de.rki.coronawarnapp.util.Event +import de.rki.coronawarnapp.util.NetworkRequestWrapper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.di.AppInjector import de.rki.coronawarnapp.util.formatter.TestResult import de.rki.coronawarnapp.worker.BackgroundWorkScheduler @@ -26,15 +23,12 @@ object SubmissionRepository { AppInjector.component.appScope } - val uiStateStateFlowInternal = MutableStateFlow(ApiRequestState.IDLE) - val uiStateStateFlow: Flow<ApiRequestState> = uiStateStateFlowInternal - val uiStateState: LiveData<ApiRequestState> = uiStateStateFlow.asLiveData() - private val testResultReceivedDateFlowInternal = MutableStateFlow(Date()) val testResultReceivedDateFlow: Flow<Date> = testResultReceivedDateFlowInternal - private val deviceUIStateFlowInternal = MutableStateFlow(DeviceUIState.UNPAIRED) - val deviceUIStateFlow: Flow<DeviceUIState> = deviceUIStateFlowInternal + private val deviceUIStateFlowInternal = + MutableStateFlow<NetworkRequestWrapper<DeviceUIState, Throwable>>(NetworkRequestWrapper.RequestIdle) + val deviceUIStateFlow: Flow<NetworkRequestWrapper<DeviceUIState, Throwable>> = deviceUIStateFlowInternal private val testResultFlow = MutableStateFlow<TestResult?>(null) @@ -80,37 +74,33 @@ object SubmissionRepository { LocalData.teletan(teletan) } - private val uiStateErrorInternal = MutableLiveData<Event<CwaWebException>>(null) - val uiStateError: LiveData<Event<CwaWebException>> = uiStateErrorInternal - // TODO this should be more UI agnostic fun refreshDeviceUIState(refreshTestResult: Boolean = true) { var refresh = refreshTestResult - deviceUIStateFlowInternal.value.let { + deviceUIStateFlowInternal.value.withSuccess { if (it != DeviceUIState.PAIRED_NO_RESULT && it != DeviceUIState.UNPAIRED) { refresh = false Timber.d("refreshDeviceUIState: Change refresh, state ${it.name} doesn't require refresh") } } - uiStateStateFlowInternal.value = ApiRequestState.STARTED + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestStarted + appScope.launch { try { refreshUIState(refresh) - uiStateStateFlowInternal.value = ApiRequestState.SUCCESS } catch (err: CwaWebException) { - uiStateErrorInternal.postValue(Event(err)) - uiStateStateFlowInternal.value = ApiRequestState.FAILED + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestFailed(err) } catch (err: Exception) { + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestFailed(err) err.report(ExceptionCategory.INTERNAL) } } } fun reset() { - uiStateStateFlowInternal.value = ApiRequestState.IDLE - deviceUIStateFlowInternal.value = DeviceUIState.UNPAIRED + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestIdle } // TODO this should be more UI agnostic @@ -132,6 +122,6 @@ object SubmissionRepository { } } } - deviceUIStateFlowInternal.value = uiState + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestSuccessful(uiState) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt index 6592ad0ba..517a077b3 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt @@ -3,7 +3,7 @@ package de.rki.coronawarnapp.ui.main.home import android.content.Context import android.graphics.drawable.Drawable import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.ui.submission.ApiRequestState +import de.rki.coronawarnapp.exception.http.CwaServerError import de.rki.coronawarnapp.util.DeviceUIState import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_ERROR import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_NEGATIVE @@ -12,72 +12,113 @@ import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE_TELETAN import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_REDEEMED import de.rki.coronawarnapp.util.DeviceUIState.SUBMITTED_FINAL +import de.rki.coronawarnapp.util.NetworkRequestWrapper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess data class SubmissionCardState( - val deviceUiState: DeviceUIState, - val isDeviceRegistered: Boolean, - val uiStateState: ApiRequestState + val deviceUiState: NetworkRequestWrapper<DeviceUIState, Throwable>, + val isDeviceRegistered: Boolean ) { - fun isRiskCardVisible(): Boolean = deviceUiState != PAIRED_POSITIVE && - deviceUiState != PAIRED_POSITIVE_TELETAN && - deviceUiState != SUBMITTED_FINAL + fun isRiskCardVisible(): Boolean = + deviceUiState.withSuccess(true) { + when (it) { + PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN, SUBMITTED_FINAL -> false + else -> true + } + } fun isUnregisteredCardVisible(): Boolean = !isDeviceRegistered fun isFetchingCardVisible(): Boolean = - isDeviceRegistered && (uiStateState == ApiRequestState.STARTED || uiStateState == ApiRequestState.FAILED) + isDeviceRegistered && when (deviceUiState) { + is NetworkRequestWrapper.RequestFailed -> deviceUiState.error is CwaServerError + is NetworkRequestWrapper.RequestStarted -> true + else -> false + } fun isFailedCardVisible(): Boolean = - isDeviceRegistered && uiStateState == ApiRequestState.SUCCESS && deviceUiState == PAIRED_REDEEMED + isDeviceRegistered && when (deviceUiState) { + is NetworkRequestWrapper.RequestFailed -> deviceUiState.error !is CwaServerError + is NetworkRequestWrapper.RequestSuccessful -> deviceUiState.data == PAIRED_REDEEMED + else -> false + } - fun isPositiveSubmissionCardVisible(): Boolean = uiStateState == ApiRequestState.SUCCESS && - (deviceUiState == PAIRED_POSITIVE || - deviceUiState == PAIRED_POSITIVE_TELETAN) + fun isPositiveSubmissionCardVisible(): Boolean = + deviceUiState.withSuccess(false) { + when (it) { + PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN -> true + else -> false + } + } fun isSubmissionDoneCardVisible(): Boolean = - uiStateState == ApiRequestState.SUCCESS && deviceUiState == SUBMITTED_FINAL + when (deviceUiState) { + is NetworkRequestWrapper.RequestSuccessful -> deviceUiState.data == SUBMITTED_FINAL + else -> false + } fun isContentCardVisible(): Boolean = - uiStateState == ApiRequestState.SUCCESS && (deviceUiState == PAIRED_ERROR || - deviceUiState == PAIRED_NEGATIVE || - deviceUiState == PAIRED_NO_RESULT) + deviceUiState.withSuccess(false) { + when (it) { + PAIRED_ERROR, PAIRED_NEGATIVE, PAIRED_NO_RESULT -> true + else -> false + } + } - fun getContentCardTitleText(c: Context): String = when (deviceUiState) { - PAIRED_ERROR, PAIRED_REDEEMED, PAIRED_NEGATIVE -> R.string.submission_status_card_title_available - PAIRED_NO_RESULT -> R.string.submission_status_card_title_pending - else -> R.string.submission_status_card_title_pending - }.let { c.getString(it) } + fun getContentCardTitleText(c: Context): String = + deviceUiState.withSuccess(R.string.submission_status_card_title_pending) { + when (it) { + PAIRED_ERROR, PAIRED_REDEEMED, PAIRED_NEGATIVE -> R.string.submission_status_card_title_available + PAIRED_NO_RESULT -> R.string.submission_status_card_title_pending + else -> R.string.submission_status_card_title_pending + } + }.let { c.getString(it) } - fun getContentCardSubTitleText(c: Context): String = when (deviceUiState) { - PAIRED_NEGATIVE -> R.string.submission_status_card_subtitle_negative - PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_subtitle_invalid - else -> null - }?.let { c.getString(it) } ?: "" + fun getContentCardSubTitleText(c: Context): String = + deviceUiState.withSuccess(null) { + when (it) { + PAIRED_NEGATIVE -> R.string.submission_status_card_subtitle_negative + PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_subtitle_invalid + else -> null + } + }?.let { c.getString(it) } ?: "" - fun getContentCardSubTitleTextColor(c: Context): Int = when (deviceUiState) { - PAIRED_NEGATIVE -> R.color.colorTextSemanticGreen - PAIRED_ERROR, PAIRED_REDEEMED -> R.color.colorTextSemanticNeutral - else -> R.color.colorTextPrimary1 - }.let { c.getColor(it) } + fun getContentCardSubTitleTextColor(c: Context): Int = + deviceUiState.withSuccess(R.color.colorTextPrimary1) { + when (it) { + PAIRED_NEGATIVE -> R.color.colorTextSemanticGreen + PAIRED_ERROR, PAIRED_REDEEMED -> R.color.colorTextSemanticNeutral + else -> R.color.colorTextPrimary1 + } + }.let { c.getColor(it) } - fun isContentCardStatusTextVisible(): Boolean = when (deviceUiState) { - PAIRED_NEGATIVE, PAIRED_REDEEMED, PAIRED_ERROR -> true - else -> false - } + fun isContentCardStatusTextVisible(): Boolean = + deviceUiState.withSuccess(false) { + when (it) { + PAIRED_NEGATIVE, PAIRED_REDEEMED, PAIRED_ERROR -> true + else -> false + } + } - fun getContentCardBodyText(c: Context): String = when (deviceUiState) { - PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_body_invalid - PAIRED_NEGATIVE -> R.string.submission_status_card_body_negative - PAIRED_NO_RESULT -> R.string.submission_status_card_body_pending - else -> R.string.submission_status_card_body_pending - }.let { c.getString(it) } + fun getContentCardBodyText(c: Context): String = + deviceUiState.withSuccess(R.string.submission_status_card_body_pending) { + when (it) { + PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_body_invalid + PAIRED_NEGATIVE -> R.string.submission_status_card_body_negative + PAIRED_NO_RESULT -> R.string.submission_status_card_body_pending + else -> R.string.submission_status_card_body_pending + } + }.let { c.getString(it) } - fun getContentCardIcon(c: Context): Drawable? = when (deviceUiState) { - PAIRED_NO_RESULT -> R.drawable.ic_main_illustration_pending - PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN -> R.drawable.ic_main_illustration_pending - PAIRED_NEGATIVE -> R.drawable.ic_main_illustration_negative - PAIRED_ERROR, PAIRED_REDEEMED -> R.drawable.ic_main_illustration_invalid - else -> R.drawable.ic_main_illustration_invalid - }.let { c.getDrawable(it) } + fun getContentCardIcon(c: Context): Drawable? = + deviceUiState.withSuccess(R.drawable.ic_main_illustration_invalid) { + when (it) { + PAIRED_NO_RESULT -> R.drawable.ic_main_illustration_pending + PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN -> R.drawable.ic_main_illustration_pending + PAIRED_NEGATIVE -> R.drawable.ic_main_illustration_negative + PAIRED_ERROR, PAIRED_REDEEMED -> R.drawable.ic_main_illustration_invalid + else -> R.drawable.ic_main_illustration_invalid + } + }.let { c.getDrawable(it) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt index 087c1e1f7..9fc9fa976 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt @@ -3,8 +3,6 @@ package de.rki.coronawarnapp.ui.main.home import dagger.Reusable import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.SubmissionRepository -import de.rki.coronawarnapp.ui.submission.ApiRequestState -import de.rki.coronawarnapp.util.DeviceUIState import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.onCompletion @@ -17,12 +15,10 @@ import javax.inject.Inject class SubmissionCardsStateProvider @Inject constructor() { val state: Flow<SubmissionCardState> = combine( - SubmissionRepository.deviceUIStateFlow, - SubmissionRepository.uiStateStateFlow + SubmissionRepository.deviceUIStateFlow ) { args -> SubmissionCardState( - deviceUiState = args[0] as DeviceUIState, - uiStateState = args[1] as ApiRequestState, + deviceUiState = args[0], isDeviceRegistered = LocalData.registrationToken() != null ) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt index a1d42d396..0de5f0efa 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt @@ -15,8 +15,8 @@ import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withFailure import de.rki.coronawarnapp.util.di.AutoInject -import de.rki.coronawarnapp.util.observeEvent import de.rki.coronawarnapp.util.ui.doNavigate import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.viewBindingLazy @@ -79,6 +79,11 @@ class SubmissionTestResultFragment : Fragment(R.layout.fragment_submission_test_ viewModel.uiState.observe2(this) { binding.uiState = it + it.deviceUiState.withFailure { + if (it is CwaWebException) { + DialogHelper.showDialog(buildErrorDialog(it)) + } + } } // registers callback when the os level back is pressed @@ -99,10 +104,6 @@ class SubmissionTestResultFragment : Fragment(R.layout.fragment_submission_test_ DialogHelper.showDialog(tracingRequiredDialog) } - viewModel.uiStateError.observeEvent(viewLifecycleOwner) { - DialogHelper.showDialog(buildErrorDialog(it)) - } - viewModel.showRedeemedTokenWarning.observe2(this) { val dialog = DialogHelper.DialogInstance( requireActivity(), diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt index 97586ba50..370ecbf29 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt @@ -3,7 +3,6 @@ package de.rki.coronawarnapp.ui.submission.testresult import androidx.lifecycle.LiveData import androidx.lifecycle.asLiveData import com.squareup.inject.assisted.AssistedInject -import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.nearby.ENFClient import de.rki.coronawarnapp.notification.TestResultNotificationService import de.rki.coronawarnapp.service.submission.SubmissionService @@ -12,7 +11,7 @@ import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.submission.Symptoms import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents import de.rki.coronawarnapp.util.DeviceUIState -import de.rki.coronawarnapp.util.Event +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel @@ -37,20 +36,22 @@ class SubmissionTestResultViewModel @AssistedInject constructor( private val tokenErrorMutex = Mutex() val uiState: LiveData<TestResultUIState> = combineTransform( - SubmissionRepository.uiStateStateFlow, SubmissionRepository.deviceUIStateFlow, SubmissionRepository.testResultReceivedDateFlow - ) { apiRequestState, deviceUiState, resultDate -> + ) { deviceUiState, resultDate -> tokenErrorMutex.withLock { - if (!wasRedeemedTokenErrorShown && deviceUiState == DeviceUIState.PAIRED_REDEEMED) { - wasRedeemedTokenErrorShown = true - showRedeemedTokenWarning.postValue(Unit) + if (!wasRedeemedTokenErrorShown) { + deviceUiState.withSuccess { + if (it == DeviceUIState.PAIRED_REDEEMED) { + wasRedeemedTokenErrorShown = true + showRedeemedTokenWarning.postValue(Unit) + } + } } } TestResultUIState( - apiRequestState = apiRequestState, deviceUiState = deviceUiState, testResultReceivedDate = resultDate ).let { emit(it) } @@ -58,11 +59,13 @@ class SubmissionTestResultViewModel @AssistedInject constructor( suspend fun observeTestResultToSchedulePositiveTestResultReminder() = SubmissionRepository.deviceUIStateFlow - .first { it == DeviceUIState.PAIRED_POSITIVE || it == DeviceUIState.PAIRED_POSITIVE_TELETAN } + .first { request -> + request.withSuccess(false) { + it == DeviceUIState.PAIRED_POSITIVE || it == DeviceUIState.PAIRED_POSITIVE_TELETAN + } + } .also { testResultNotificationService.schedulePositiveTestResultReminder() } - val uiStateError: LiveData<Event<CwaWebException>> = SubmissionRepository.uiStateError - fun onBackPressed() { routeToScreen.postValue(SubmissionNavigationEvents.NavigateToMainActivity) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt index b1909eb80..a34a02cad 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt @@ -1,11 +1,10 @@ package de.rki.coronawarnapp.ui.submission.testresult -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import java.util.Date data class TestResultUIState( - val apiRequestState: ApiRequestState, - val deviceUiState: DeviceUIState, + val deviceUiState: NetworkRequestWrapper<DeviceUIState, Throwable>, val testResultReceivedDate: Date? ) 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 deleted file mode 100644 index 6b668e6c4..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt +++ /dev/null @@ -1,12 +0,0 @@ -package de.rki.coronawarnapp.ui.viewmodel - -import androidx.lifecycle.LiveData -import androidx.lifecycle.asLiveData -import de.rki.coronawarnapp.storage.SubmissionRepository -import de.rki.coronawarnapp.util.DeviceUIState -import de.rki.coronawarnapp.util.viewmodel.CWAViewModel - -class SubmissionViewModel : CWAViewModel() { - - val deviceUiState: LiveData<DeviceUIState> = SubmissionRepository.deviceUIStateFlow.asLiveData() -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt new file mode 100644 index 000000000..47d1c57e4 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt @@ -0,0 +1,30 @@ +package de.rki.coronawarnapp.util + +sealed class NetworkRequestWrapper<out T, out U> { + object RequestIdle : NetworkRequestWrapper<Nothing, Nothing>() + object RequestStarted : NetworkRequestWrapper<Nothing, Nothing>() + data class RequestSuccessful<T, U>(val data: T) : NetworkRequestWrapper<T, U>() + data class RequestFailed<T, U>(val error: U) : NetworkRequestWrapper<T, U>() + + companion object { + fun <T, U, W> NetworkRequestWrapper<T, U>?.withSuccess(without: W, block: (data: T) -> W): W { + return if (this is RequestSuccessful) { + block(this.data) + } else { + without + } + } + + fun <T, U> NetworkRequestWrapper<T, U>?.withSuccess(block: (data: T) -> Unit) { + if (this is RequestSuccessful) { + block(this.data) + } + } + + fun <T, U> NetworkRequestWrapper<T, U>?.withFailure(block: (error: U) -> Unit) { + if (this is RequestFailed) { + block(this.error) + } + } + } +} 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 156f8efee..e573e2023 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 @@ -8,11 +8,13 @@ import android.text.Spannable import android.text.SpannableString import android.text.SpannableStringBuilder import android.text.style.ForegroundColorSpan +import android.view.View import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.R import de.rki.coronawarnapp.submission.Symptoms -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.TimeAndDateExtensions.toUIFormat import java.util.Date import java.util.Locale @@ -49,33 +51,37 @@ fun isEnableSymptomCalendarButtonByState(currentState: Symptoms.StartOf?): Boole return currentState != null } -fun formatTestResultSpinnerVisible(uiStateState: ApiRequestState?): Int = - formatVisibility(uiStateState != ApiRequestState.SUCCESS) - -fun formatTestResultVisible(uiStateState: ApiRequestState?): Int = - formatVisibility(uiStateState == ApiRequestState.SUCCESS) - -fun formatTestResultStatusText(uiState: DeviceUIState?): String { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NEGATIVE -> appContext.getString(R.string.test_result_card_status_negative) - DeviceUIState.PAIRED_POSITIVE, - DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getString(R.string.test_result_card_status_positive) - else -> appContext.getString(R.string.test_result_card_status_invalid) +fun formatTestResultSpinnerVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.VISIBLE) { + View.GONE } -} -fun formatTestResultStatusColor(uiState: DeviceUIState?): Int { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NEGATIVE -> appContext.getColor(R.color.colorTextSemanticGreen) - DeviceUIState.PAIRED_POSITIVE, - DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getColor(R.color.colorTextSemanticRed) - else -> appContext.getColor(R.color.colorTextSemanticRed) +fun formatTestResultVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { + View.VISIBLE } -} -fun formatTestResult(uiState: DeviceUIState?): Spannable { +fun formatTestResultStatusText(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): String = + uiState.withSuccess(R.string.test_result_card_status_invalid) { + when (it) { + DeviceUIState.PAIRED_NEGATIVE -> R.string.test_result_card_status_negative + DeviceUIState.PAIRED_POSITIVE, + DeviceUIState.PAIRED_POSITIVE_TELETAN -> R.string.test_result_card_status_positive + else -> R.string.test_result_card_status_invalid + } + }.let { CoronaWarnApplication.getAppContext().getString(it) } + +fun formatTestResultStatusColor(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(R.color.colorTextSemanticRed) { + when (it) { + DeviceUIState.PAIRED_NEGATIVE -> R.color.colorTextSemanticGreen + DeviceUIState.PAIRED_POSITIVE, + DeviceUIState.PAIRED_POSITIVE_TELETAN -> R.color.colorTextSemanticRed + else -> R.color.colorTextSemanticRed + } + }.let { CoronaWarnApplication.getAppContext().getColor(it) } + +fun formatTestResult(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Spannable { val appContext = CoronaWarnApplication.getAppContext() return SpannableStringBuilder() .append(appContext.getString(R.string.test_result_card_virus_name_text)) @@ -87,33 +93,36 @@ fun formatTestResult(uiState: DeviceUIState?): Spannable { ) } -fun formatTestResultCardContent(uiState: DeviceUIState?): Spannable { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NO_RESULT -> - SpannableString(appContext.getString(R.string.test_result_card_status_pending)) - DeviceUIState.PAIRED_ERROR, - DeviceUIState.PAIRED_REDEEMED -> - SpannableString(appContext.getString(R.string.test_result_card_status_invalid)) - - DeviceUIState.PAIRED_POSITIVE, - DeviceUIState.PAIRED_POSITIVE_TELETAN, - DeviceUIState.PAIRED_NEGATIVE -> formatTestResult(uiState) - else -> SpannableString("") +fun formatTestResultCardContent(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Spannable { + return uiState.withSuccess(SpannableString("")) { + val appContext = CoronaWarnApplication.getAppContext() + when (it) { + DeviceUIState.PAIRED_NO_RESULT -> + SpannableString(appContext.getString(R.string.test_result_card_status_pending)) + DeviceUIState.PAIRED_ERROR, + DeviceUIState.PAIRED_REDEEMED -> + SpannableString(appContext.getString(R.string.test_result_card_status_invalid)) + + DeviceUIState.PAIRED_POSITIVE, + DeviceUIState.PAIRED_POSITIVE_TELETAN, + DeviceUIState.PAIRED_NEGATIVE -> formatTestResult(uiState) + else -> SpannableString("") + } } } -fun formatTestStatusIcon(uiState: DeviceUIState?): Drawable? { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NO_RESULT -> appContext.getDrawable(R.drawable.ic_test_result_illustration_pending) - DeviceUIState.PAIRED_POSITIVE_TELETAN, - DeviceUIState.PAIRED_POSITIVE -> appContext.getDrawable(R.drawable.ic_test_result_illustration_positive) - DeviceUIState.PAIRED_NEGATIVE -> appContext.getDrawable(R.drawable.ic_test_result_illustration_negative) - DeviceUIState.PAIRED_ERROR, - DeviceUIState.PAIRED_REDEEMED -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid) - else -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid) - } +fun formatTestStatusIcon(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Drawable? { + return uiState.withSuccess(R.drawable.ic_test_result_illustration_invalid) { + when (it) { + DeviceUIState.PAIRED_NO_RESULT -> R.drawable.ic_test_result_illustration_pending + DeviceUIState.PAIRED_POSITIVE_TELETAN, + DeviceUIState.PAIRED_POSITIVE -> R.drawable.ic_test_result_illustration_positive + DeviceUIState.PAIRED_NEGATIVE -> R.drawable.ic_test_result_illustration_negative + DeviceUIState.PAIRED_ERROR, + DeviceUIState.PAIRED_REDEEMED -> R.drawable.ic_test_result_illustration_invalid + else -> R.drawable.ic_test_result_illustration_invalid + } + }.let { CoronaWarnApplication.getAppContext().getDrawable(it) } } fun formatTestResultRegisteredAtText(registeredAt: Date?): String { @@ -122,24 +131,30 @@ fun formatTestResultRegisteredAtText(registeredAt: Date?): String { .format(registeredAt?.toUIFormat(appContext)) } -fun formatTestResultPendingStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_NO_RESULT) +fun formatTestResultPendingStepsVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { formatVisibility(it == DeviceUIState.PAIRED_NO_RESULT) } -fun formatTestResultNegativeStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_NEGATIVE) +fun formatTestResultNegativeStepsVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { formatVisibility(it == DeviceUIState.PAIRED_NEGATIVE) } -fun formatTestResultPositiveStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_POSITIVE || uiState == DeviceUIState.PAIRED_POSITIVE_TELETAN) +fun formatTestResultPositiveStepsVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { + formatVisibility(it == DeviceUIState.PAIRED_POSITIVE || it == DeviceUIState.PAIRED_POSITIVE_TELETAN) + } -fun formatTestResultInvalidStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_ERROR || uiState == DeviceUIState.PAIRED_REDEEMED) +fun formatTestResultInvalidStepsVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { + formatVisibility(it == DeviceUIState.PAIRED_ERROR || it == DeviceUIState.PAIRED_REDEEMED) + } -fun formatShowRiskStatusCard(deviceUiState: DeviceUIState?): Int = - formatVisibility( - deviceUiState != DeviceUIState.PAIRED_POSITIVE && - deviceUiState != DeviceUIState.PAIRED_POSITIVE_TELETAN && - deviceUiState != DeviceUIState.SUBMITTED_FINAL - ) +fun formatShowRiskStatusCard(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { + formatVisibility( + it != DeviceUIState.PAIRED_POSITIVE && + it != DeviceUIState.PAIRED_POSITIVE_TELETAN && + it != DeviceUIState.SUBMITTED_FINAL + ) + } fun formatCountryIsoTagToLocalizedName(isoTag: String?): String { val country = if (isoTag != null) Locale("", isoTag).displayCountry else "" diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml index a34166dd5..ecf73ebc4 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml @@ -9,10 +9,6 @@ <import type="de.rki.coronawarnapp.submission.Symptoms.StartOf" /> - <variable - name="submissionViewModel" - type="de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel" /> - </data> <ScrollView diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_intro.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_intro.xml index 0fb5a5e02..e57734171 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_intro.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_intro.xml @@ -7,10 +7,6 @@ <import type="de.rki.coronawarnapp.util.formatter.FormatterSubmissionHelper" /> - <variable - name="submissionViewModel" - type="de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel" /> - </data> <ScrollView diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml index 3521faa0f..9b40a94aa 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml @@ -34,7 +34,7 @@ style="?android:attr/progressBarStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:visibility="@{FormatterSubmissionHelper.formatTestResultSpinnerVisible(uiState.apiRequestState)}" + android:visibility="@{FormatterSubmissionHelper.formatTestResultSpinnerVisible(uiState.deviceUiState)}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -48,7 +48,7 @@ android:layout_width="@dimen/match_constraint" android:layout_height="@dimen/match_constraint" android:layout_marginBottom="@dimen/button_padding_top_bottom" - android:visibility="@{FormatterSubmissionHelper.formatTestResultVisible(uiState.apiRequestState)}" + android:visibility="@{FormatterSubmissionHelper.formatTestResultVisible(uiState.deviceUiState)}" app:layout_constraintBottom_toTopOf="@+id/include_submission_test_result_buttons" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/Corona-Warn-App/src/main/res/layout/include_submission_symptom_length_selection.xml b/Corona-Warn-App/src/main/res/layout/include_submission_symptom_length_selection.xml index d95f4ed9f..6cbbd3180 100644 --- a/Corona-Warn-App/src/main/res/layout/include_submission_symptom_length_selection.xml +++ b/Corona-Warn-App/src/main/res/layout/include_submission_symptom_length_selection.xml @@ -8,10 +8,6 @@ <import type="de.rki.coronawarnapp.submission.Symptoms.StartOf" /> - <variable - name="submissionViewModel" - type="de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel" /> - </data> <androidx.constraintlayout.widget.ConstraintLayout diff --git a/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml b/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml index dcdcdea37..01364c789 100644 --- a/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml +++ b/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml @@ -13,7 +13,7 @@ <variable name="deviceUIState" - type="de.rki.coronawarnapp.util.DeviceUIState" /> + type="de.rki.coronawarnapp.util.NetworkRequestWrapper<de.rki.coronawarnapp.util.DeviceUIState,java.lang.Throwable>" /> </data> <androidx.constraintlayout.widget.ConstraintLayout diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt index 44a4980d7..c636f8180 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt @@ -9,12 +9,12 @@ import de.rki.coronawarnapp.ui.main.home.HomeFragmentViewModel import de.rki.coronawarnapp.ui.main.home.SubmissionCardState import de.rki.coronawarnapp.ui.main.home.SubmissionCardsStateProvider import de.rki.coronawarnapp.ui.main.home.TracingHeaderState -import de.rki.coronawarnapp.ui.submission.ApiRequestState.SUCCESS import de.rki.coronawarnapp.ui.tracing.card.TracingCardState import de.rki.coronawarnapp.ui.tracing.card.TracingCardStateProvider import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE_TELETAN +import de.rki.coronawarnapp.util.NetworkRequestWrapper import de.rki.coronawarnapp.util.security.EncryptionErrorResetTool import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations @@ -128,7 +128,7 @@ class HomeFragmentViewModelTest : BaseTest() { @Test fun `positive test result notification is triggered on positive QR code result`() { - val state = SubmissionCardState(PAIRED_POSITIVE, true, SUCCESS) + val state = SubmissionCardState(NetworkRequestWrapper.RequestSuccessful(PAIRED_POSITIVE), true) every { submissionCardsStateProvider.state } returns flowOf(state) every { testResultNotificationService.schedulePositiveTestResultReminder() } returns Unit @@ -142,7 +142,7 @@ class HomeFragmentViewModelTest : BaseTest() { @Test fun `positive test result notification is triggered on positive TeleTan code result`() { - val state = SubmissionCardState(PAIRED_POSITIVE_TELETAN, true, SUCCESS) + val state = SubmissionCardState(NetworkRequestWrapper.RequestSuccessful(PAIRED_POSITIVE_TELETAN), true) every { submissionCardsStateProvider.state } returns flowOf(state) every { testResultNotificationService.schedulePositiveTestResultReminder() } returns Unit diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt index 37d908b10..e661eb23a 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt @@ -5,6 +5,7 @@ import de.rki.coronawarnapp.R import de.rki.coronawarnapp.ui.main.home.SubmissionCardState import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.clearAllMocks @@ -33,12 +34,18 @@ class SubmissionCardStateTest : BaseTest() { private fun instance( deviceUiState: DeviceUIState = mockk(), isDeviceRegistered: Boolean = true, - uiStateState: ApiRequestState = mockk() - ) = SubmissionCardState( - deviceUiState = deviceUiState, - isDeviceRegistered = isDeviceRegistered, - uiStateState = uiStateState - ) + uiStateState: ApiRequestState = ApiRequestState.SUCCESS + ) = + when (uiStateState) { + ApiRequestState.SUCCESS -> + SubmissionCardState(NetworkRequestWrapper.RequestSuccessful(deviceUiState), isDeviceRegistered) + ApiRequestState.FAILED -> + SubmissionCardState(NetworkRequestWrapper.RequestFailed(mockk()), isDeviceRegistered) + ApiRequestState.STARTED -> + SubmissionCardState(NetworkRequestWrapper.RequestStarted, isDeviceRegistered) + ApiRequestState.IDLE -> + SubmissionCardState(NetworkRequestWrapper.RequestIdle, isDeviceRegistered) + } @Test fun `risk card visibility`() { @@ -163,7 +170,7 @@ class SubmissionCardStateTest : BaseTest() { isFetchingCardVisible() shouldBe false } instance(isDeviceRegistered = true, uiStateState = ApiRequestState.FAILED).apply { - isFetchingCardVisible() shouldBe true + isFetchingCardVisible() shouldBe false } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt index 2eaac14f6..b5bc2d451 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt @@ -5,8 +5,8 @@ import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.ui.main.home.SubmissionCardState import de.rki.coronawarnapp.ui.main.home.SubmissionCardsStateProvider -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.clearAllMocks @@ -46,20 +46,19 @@ class SubmissionCardsStateProviderTest : BaseTest() { @Test fun `state is combined correctly`() = runBlockingTest { - every { SubmissionRepository.deviceUIStateFlow } returns flow { emit(DeviceUIState.PAIRED_POSITIVE) } - every { SubmissionRepository.uiStateStateFlow } returns flow { emit(ApiRequestState.SUCCESS) } + every { SubmissionRepository.deviceUIStateFlow } returns flow { + emit(NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>(DeviceUIState.PAIRED_POSITIVE)) + } every { LocalData.registrationToken() } returns "token" createInstance().apply { state.first() shouldBe SubmissionCardState( - deviceUiState = DeviceUIState.PAIRED_POSITIVE, - uiStateState = ApiRequestState.SUCCESS, + deviceUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), isDeviceRegistered = true ) verify { SubmissionRepository.deviceUIStateFlow - SubmissionRepository.uiStateStateFlow LocalData.registrationToken() } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt index c83108653..c7f8e7b15 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt @@ -8,8 +8,8 @@ import android.text.style.ForegroundColorSpan import android.view.View import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import io.mockk.MockKAnnotations import io.mockk.every import io.mockk.impl.annotations.MockK @@ -74,52 +74,76 @@ class FormatterSubmissionHelperTest { every { context.getDrawable(R.drawable.ic_test_result_illustration_negative) } returns drawable } - private fun formatTestResultSpinnerVisibleBase(oUiStateState: ApiRequestState?, iResult: Int) { - val result = formatTestResultSpinnerVisible(uiStateState = oUiStateState) + private fun formatTestResultSpinnerVisibleBase( + oUiStateState: NetworkRequestWrapper<DeviceUIState, Throwable>?, + iResult: Int + ) { + val result = formatTestResultSpinnerVisible(uiState = oUiStateState) assertThat(result, `is`(iResult)) } - private fun formatTestResultVisibleBase(oUiStateState: ApiRequestState?, iResult: Int) { - val result = formatTestResultVisible(uiStateState = oUiStateState) + private fun formatTestResultVisibleBase( + oUiStateState: NetworkRequestWrapper<DeviceUIState, Throwable>?, + iResult: Int + ) { + val result = formatTestResultVisible(uiState = oUiStateState) assertThat(result, `is`(iResult)) } - private fun formatTestResultStatusTextBase(oUiState: DeviceUIState?, iResult: String) { + private fun formatTestResultStatusTextBase( + oUiState: NetworkRequestWrapper<DeviceUIState, Throwable>?, + iResult: String + ) { val result = formatTestResultStatusText(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultStatusColorBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultStatusColorBase( + oUiState: NetworkRequestWrapper<DeviceUIState, Throwable>?, + iResult: Int + ) { val result = formatTestResultStatusColor(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestStatusIconBase(oUiState: DeviceUIState?) { + private fun formatTestStatusIconBase(oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?) { val result = formatTestStatusIcon(uiState = oUiState) assertThat(result, `is`(drawable)) } - private fun formatTestResultPendingStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultPendingStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?, + iResult: Int + ) { val result = formatTestResultPendingStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultNegativeStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultNegativeStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?, + iResult: Int + ) { val result = formatTestResultNegativeStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultPositiveStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultPositiveStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?, + iResult: Int + ) { val result = formatTestResultPositiveStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultInvalidStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultInvalidStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?, + iResult: Int + ) { val result = formatTestResultInvalidStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultBase(oUiState: DeviceUIState?) { + private fun formatTestResultBase(oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?) { mockkConstructor(SpannableStringBuilder::class) val spannableStringBuilder1 = @@ -147,19 +171,19 @@ class FormatterSubmissionHelperTest { fun formatTestResultSpinnerVisible() { formatTestResultSpinnerVisibleBase(oUiStateState = null, iResult = View.VISIBLE) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.FAILED, + oUiStateState = NetworkRequestWrapper.RequestFailed(mockk()), iResult = View.VISIBLE ) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.IDLE, + oUiStateState = NetworkRequestWrapper.RequestIdle, iResult = View.VISIBLE ) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.STARTED, + oUiStateState = NetworkRequestWrapper.RequestStarted, iResult = View.VISIBLE ) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.SUCCESS, + oUiStateState = NetworkRequestWrapper.RequestSuccessful(mockk()), iResult = View.GONE ) } @@ -167,10 +191,13 @@ class FormatterSubmissionHelperTest { @Test fun formatTestResultVisible() { formatTestResultVisibleBase(oUiStateState = null, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.FAILED, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.IDLE, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.STARTED, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.SUCCESS, iResult = View.VISIBLE) + formatTestResultVisibleBase(oUiStateState = NetworkRequestWrapper.RequestFailed(mockk()), iResult = View.GONE) + formatTestResultVisibleBase(oUiStateState = NetworkRequestWrapper.RequestIdle, iResult = View.GONE) + formatTestResultVisibleBase(oUiStateState = NetworkRequestWrapper.RequestStarted, iResult = View.GONE) + formatTestResultVisibleBase( + oUiStateState = NetworkRequestWrapper.RequestSuccessful(mockk()), + iResult = View.VISIBLE + ) } @Test @@ -180,35 +207,35 @@ class FormatterSubmissionHelperTest { iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = context.getString(R.string.test_result_card_status_negative) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = context.getString(R.string.test_result_card_status_positive) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = context.getString(R.string.test_result_card_status_positive) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = context.getString(R.string.test_result_card_status_invalid) ) } @@ -220,35 +247,35 @@ class FormatterSubmissionHelperTest { iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = context.getColor(R.color.colorTextSemanticGreen) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = context.getColor(R.color.colorTextSemanticRed) ) } @@ -256,49 +283,49 @@ class FormatterSubmissionHelperTest { @Test fun formatTestStatusIcon() { formatTestStatusIconBase(oUiState = null) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_NEGATIVE) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_ERROR) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_NO_RESULT) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_POSITIVE) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN) - formatTestStatusIconBase(oUiState = DeviceUIState.SUBMITTED_FINAL) - formatTestStatusIconBase(oUiState = DeviceUIState.SUBMITTED_INITIAL) - formatTestStatusIconBase(oUiState = DeviceUIState.UNPAIRED) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED)) } @Test fun formatTestResultPendingStepsVisible() { formatTestResultPendingStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.VISIBLE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -307,35 +334,35 @@ class FormatterSubmissionHelperTest { fun formatTestResultNegativeStepsVisible() { formatTestResultNegativeStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.VISIBLE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -344,35 +371,35 @@ class FormatterSubmissionHelperTest { fun formatTestResultPositiveStepsVisible() { formatTestResultPositiveStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.VISIBLE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.VISIBLE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -381,35 +408,35 @@ class FormatterSubmissionHelperTest { fun formatTestResultInvalidStepsVisible() { formatTestResultInvalidStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.VISIBLE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -417,14 +444,14 @@ class FormatterSubmissionHelperTest { @Test fun formatTestResult() { formatTestResultBase(oUiState = null) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_NEGATIVE) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_ERROR) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_NO_RESULT) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_POSITIVE) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN) - formatTestResultBase(oUiState = DeviceUIState.SUBMITTED_FINAL) - formatTestResultBase(oUiState = DeviceUIState.SUBMITTED_INITIAL) - formatTestResultBase(oUiState = DeviceUIState.UNPAIRED) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED)) } @After -- GitLab