From fd69ed4bc94563ce46c532a518dbcd59b809f499 Mon Sep 17 00:00:00 2001 From: Lukas Lechner <lukas.lechner@sap.com> Date: Mon, 22 Feb 2021 16:35:06 +0100 Subject: [PATCH] Skip consent screen on subsequent survey participations (EXPOSUREAPP-5278) (#2433) * Skip consent screen on subsequent survey participates * Import Surveys.ConsentResult to make code more readable * Improve wording, change ConsentResult.NotNeeded to ConsentResult.AlreadyGiven --- .../ui/tracing/TracingDetailsFragmentTest.kt | 7 +++-- .../datadonation/survey/Surveys.kt | 30 +++++++++++++++++++ .../ui/details/TracingDetailsFragment.kt | 5 ++++ .../TracingDetailsFragmentViewModel.kt | 21 +++++++++++-- .../details/TracingDetailsNavigationEvents.kt | 3 +- 5 files changed, 61 insertions(+), 5 deletions(-) diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingDetailsFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingDetailsFragmentTest.kt index cd1ae371d..b9da670a2 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingDetailsFragmentTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingDetailsFragmentTest.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.MutableLiveData import androidx.test.ext.junit.runners.AndroidJUnit4 import dagger.Module import dagger.android.ContributesAndroidInjector +import de.rki.coronawarnapp.datadonation.survey.Surveys import de.rki.coronawarnapp.risk.storage.RiskLevelStorage import de.rki.coronawarnapp.storage.TracingRepository import de.rki.coronawarnapp.tracing.GeneralTracingStatus @@ -24,12 +25,12 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import testhelpers.BaseUITest -import testhelpers.takeScreenshot import testhelpers.Screenshot import testhelpers.SystemUIDemoModeRule import testhelpers.TestDispatcherProvider import testhelpers.launchFragment2 import testhelpers.launchFragmentInContainer2 +import testhelpers.takeScreenshot import tools.fastlane.screengrab.locale.LocaleTestRule @RunWith(AndroidJUnit4::class) @@ -41,6 +42,7 @@ class TracingDetailsFragmentTest : BaseUITest() { @MockK lateinit var tracingDetailsItemProvider: TracingDetailsItemProvider @MockK lateinit var tracingStateProviderFactory: TracingStateProvider.Factory @MockK lateinit var tracingRepository: TracingRepository + @MockK lateinit var surveys: Surveys private lateinit var viewModel: TracingDetailsFragmentViewModel @@ -63,7 +65,8 @@ class TracingDetailsFragmentTest : BaseUITest() { riskLevelStorage = riskLevelStorage, tracingDetailsItemProvider = tracingDetailsItemProvider, tracingStateProviderFactory = tracingStateProviderFactory, - tracingRepository = tracingRepository + tracingRepository = tracingRepository, + surveys = surveys ) ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/Surveys.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/Surveys.kt index 6914f0d81..121025261 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/Surveys.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/Surveys.kt @@ -37,6 +37,36 @@ class Surveys @Inject constructor( } } + suspend fun isConsentNeeded(type: Type): ConsentResult { + + when (type) { + Type.HIGH_RISK_ENCOUNTER -> { + + // If no OTP was ever authorized, we need a consent. + val authResult = oneTimePasswordRepo.otpAuthorizationResult ?: return ConsentResult.Needed + + // If we already have an authorized OTP for this high-risk state + // we can skip the consent and directly show the url in the browser. + // We know that the otp belongs to the current high-risk state, because the authResult gets + // invalidated on high to low risk state transitions. + if (authResult.authorized && !authResult.invalidated) { + val surveyLink = urlProvider.provideUrl(type, authResult.uuid) + return ConsentResult.AlreadyGiven(surveyLink) + } + + // Finally, we need a consent for stored OTPs where the authorization failed (authorized == false) + // or when the app shows a new high-risk card (and therefore authResult was previously invalidated when the + // risk changed from high to low) + return ConsentResult.Needed + } + } + } + + sealed class ConsentResult { + object Needed : ConsentResult() + data class AlreadyGiven(val surveyLink: String) : ConsentResult() + } + suspend fun requestDetails(type: Type): Survey { val config = appConfigProvider.getAppConfig().survey Timber.v("Requested survey: %s", config) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragment.kt index b21bf698e..7732c3938 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragment.kt @@ -8,6 +8,7 @@ import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.LinearLayoutManager import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.TracingDetailsFragmentLayoutBinding +import de.rki.coronawarnapp.util.ExternalActionHelper import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.diffutil.update import de.rki.coronawarnapp.util.ui.doNavigate @@ -55,6 +56,10 @@ class TracingDetailsFragment : Fragment(R.layout.tracing_details_fragment_layout is TracingDetailsNavigationEvents.NavigateToSurveyConsentFragment -> doNavigate( TracingDetailsFragmentDirections.actionRiskDetailsFragmentToSurveyConsentFragment(it.type) ) + is TracingDetailsNavigationEvents.NavigateToSurveyUrlInBrowser -> ExternalActionHelper.openUrl( + this, + it.url + ) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragmentViewModel.kt index df6725509..e7fa20879 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragmentViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragmentViewModel.kt @@ -4,6 +4,9 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.asLiveData import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import de.rki.coronawarnapp.datadonation.survey.Surveys +import de.rki.coronawarnapp.datadonation.survey.Surveys.ConsentResult.AlreadyGiven +import de.rki.coronawarnapp.datadonation.survey.Surveys.ConsentResult.Needed import de.rki.coronawarnapp.risk.RiskState import de.rki.coronawarnapp.risk.storage.RiskLevelStorage import de.rki.coronawarnapp.risk.tryLatestResultsWithDefaults @@ -42,7 +45,8 @@ class TracingDetailsFragmentViewModel @AssistedInject constructor( riskLevelStorage: RiskLevelStorage, tracingDetailsItemProvider: TracingDetailsItemProvider, tracingStateProviderFactory: TracingStateProvider.Factory, - private val tracingRepository: TracingRepository + private val tracingRepository: TracingRepository, + private val surveys: Surveys ) : CWAViewModel(dispatcherProvider = dispatcherProvider) { private val tracingStateProvider by lazy { tracingStateProviderFactory.create(isDetailsMode = true) } @@ -108,7 +112,20 @@ class TracingDetailsFragmentViewModel @AssistedInject constructor( fun onItemClicked(item: DetailsItem) { when (item) { is UserSurveyBox.Item -> - routeToScreen.postValue(TracingDetailsNavigationEvents.NavigateToSurveyConsentFragment(item.type)) + launch { + when (val consentResult = surveys.isConsentNeeded(Surveys.Type.HIGH_RISK_ENCOUNTER)) { + is Needed -> routeToScreen.postValue( + TracingDetailsNavigationEvents.NavigateToSurveyConsentFragment( + item.type + ) + ) + is AlreadyGiven -> routeToScreen.postValue( + TracingDetailsNavigationEvents.NavigateToSurveyUrlInBrowser( + consentResult.surveyLink + ) + ) + } + } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsNavigationEvents.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsNavigationEvents.kt index 221ebc91e..9ba870a63 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsNavigationEvents.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsNavigationEvents.kt @@ -3,5 +3,6 @@ package de.rki.coronawarnapp.tracing.ui.details import de.rki.coronawarnapp.datadonation.survey.Surveys sealed class TracingDetailsNavigationEvents { - class NavigateToSurveyConsentFragment(val type: Surveys.Type) : TracingDetailsNavigationEvents() + data class NavigateToSurveyConsentFragment(val type: Surveys.Type) : TracingDetailsNavigationEvents() + data class NavigateToSurveyUrlInBrowser(val url: String) : TracingDetailsNavigationEvents() } -- GitLab