diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/PcrTestSubmissionDoneCard.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/PcrTestSubmissionDoneCard.kt index d4ed6af6b785854ccaa27f593a538961a89bc8bb..7ddb6919692812dd506361473ff8b5ce6bed0964 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/PcrTestSubmissionDoneCard.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/PcrTestSubmissionDoneCard.kt @@ -24,7 +24,7 @@ class PcrTestSubmissionDoneCard( payloads: List<Any> ) -> Unit = { item, payloads -> val curItem = payloads.filterIsInstance<Item>().singleOrNull() ?: item - + itemView.setOnClickListener { curItem.onClickAction(item) } val userDate = curItem.state.getFormattedRegistrationDate() date.text = resources.getString(R.string.ag_homescreen_card_pcr_body_result_date, userDate) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/RapidTestSubmissionDoneCard.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/RapidTestSubmissionDoneCard.kt index c41df314763cbfb4c4262019318a6b22232249b0..22717b0201abdb410c92a1a8dc8187704ee74971 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/RapidTestSubmissionDoneCard.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/RapidTestSubmissionDoneCard.kt @@ -24,7 +24,7 @@ class RapidTestSubmissionDoneCard( payloads: List<Any> ) -> Unit = { item, payloads -> val curItem = payloads.filterIsInstance<Item>().singleOrNull() ?: item - + itemView.setOnClickListener { curItem.onClickAction(item) } val userDate = curItem.state.getFormattedRegistrationDate() date.text = resources.getString(R.string.ag_homescreen_card_rapid_body_result_date, userDate) } 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 488bfd1e58e55a168e99524693ff57781b5849e1..bdbd3098d005d6e943719e6e821b366cbbbe3e14 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 @@ -206,7 +206,10 @@ class HomeFragmentViewModel @AssistedInject constructor( ) } is SubmissionStatePCR.SubmissionDone -> PcrTestSubmissionDoneCard.Item(state) { - // TODO + routeToScreen.postValue( + HomeFragmentDirections + .actionMainFragmentToSubmissionTestResultKeysSharedFragment(CoronaTest.Type.PCR) + ) } } @@ -259,7 +262,10 @@ class HomeFragmentViewModel @AssistedInject constructor( submissionRepository.removeTestFromDevice(type = CoronaTest.Type.RAPID_ANTIGEN) } is SubmissionStateRAT.SubmissionDone -> RapidTestSubmissionDoneCard.Item(state) { - // TODO + routeToScreen.postValue( + HomeFragmentDirections + .actionMainFragmentToSubmissionTestResultKeysSharedFragment(CoronaTest.Type.RAPID_ANTIGEN) + ) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultKeysSharedFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultKeysSharedFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..d7de6021db80d802d076d64914d89865f00b9a7e --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultKeysSharedFragment.kt @@ -0,0 +1,94 @@ +package de.rki.coronawarnapp.ui.submission.testresult.positive + +import android.app.AlertDialog +import android.os.Bundle +import android.view.View +import android.view.accessibility.AccessibilityEvent +import androidx.core.view.isVisible +import androidx.fragment.app.Fragment +import androidx.navigation.fragment.navArgs +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.coronatest.type.CoronaTest +import de.rki.coronawarnapp.databinding.FragmentSubmissionTestResultPositiveKeysSharedBinding +import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat +import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.util.di.AutoInject +import de.rki.coronawarnapp.util.ui.observe2 +import de.rki.coronawarnapp.util.ui.popBackStack +import de.rki.coronawarnapp.util.ui.viewBindingLazy +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider +import de.rki.coronawarnapp.util.viewmodel.cwaViewModelsAssisted +import javax.inject.Inject + +/** + * [SubmissionTestResultKeysSharedFragment], the test result screen that is shown to the user if they have provided + * consent. + */ +class SubmissionTestResultKeysSharedFragment : + Fragment(R.layout.fragment_submission_test_result_positive_keys_shared), + AutoInject { + + private val navArgs by navArgs<SubmissionTestResultKeysSharedFragmentArgs>() + + @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory + private val viewModel: SubmissionTestResultKeysSharedViewModel by cwaViewModelsAssisted( + factoryProducer = { viewModelFactory }, + constructorCall = { factory, _ -> + factory as SubmissionTestResultKeysSharedViewModel.Factory + factory.create(navArgs.testType) + } + ) + + private val binding: FragmentSubmissionTestResultPositiveKeysSharedBinding by viewBindingLazy() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + viewModel.onTestOpened() + + binding.submissionDonePcrValidation.root.isVisible = viewModel.testType == CoronaTest.Type.RAPID_ANTIGEN + + binding.toolbar.setNavigationOnClickListener { + popBackStack() + } + + binding.deleteTest.setOnClickListener { + viewModel.onShowDeleteTestDialog() + } + + viewModel.uiState.observe2(this) { + binding.apply { + submissionTestResultSection.setTestResultSection(it.coronaTest) + } + } + + viewModel.showDeleteTestDialog.observe2(this) { showDeleteTestDialog() } + } + + override fun onResume() { + super.onResume() + binding.submissionTestResultContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT) + } + + private fun navigateBack() { + popBackStack() + } + + private fun showDeleteTestDialog() { + val removeTestDialog = DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_test_result_dialog_remove_test_title, + R.string.submission_test_result_dialog_remove_test_message, + R.string.submission_test_result_dialog_remove_test_button_positive, + R.string.submission_test_result_dialog_remove_test_button_negative, + positiveButtonFunction = { + viewModel.onDeleteTestConfirmed() + navigateBack() + } + ) + DialogHelper.showDialog(removeTestDialog).apply { + getButton(AlertDialog.BUTTON_POSITIVE) + .setTextColor(context.getColorCompat(R.color.colorTextSemanticRed)) + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultKeysSharedModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultKeysSharedModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..65ed0e6ecfa2c1aefe6596570e40ab769a38c565 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultKeysSharedModule.kt @@ -0,0 +1,18 @@ +package de.rki.coronawarnapp.ui.submission.testresult.positive + +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import de.rki.coronawarnapp.util.viewmodel.CWAViewModel +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelKey + +@Module +abstract class SubmissionTestResultKeysSharedModule { + @Binds + @IntoMap + @CWAViewModelKey(SubmissionTestResultKeysSharedViewModel::class) + abstract fun submissionTestResultKeysSharedFragment( + factory: SubmissionTestResultKeysSharedViewModel.Factory + ): CWAViewModelFactory<out CWAViewModel> +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultKeysSharedViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultKeysSharedViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..8e85122c6b61dc7938ecd1abd9754dfc02f84fbf --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultKeysSharedViewModel.kt @@ -0,0 +1,57 @@ +package de.rki.coronawarnapp.ui.submission.testresult.positive + +import androidx.lifecycle.LiveData +import androidx.lifecycle.asLiveData +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import de.rki.coronawarnapp.coronatest.type.CoronaTest.Type +import de.rki.coronawarnapp.submission.SubmissionRepository +import de.rki.coronawarnapp.ui.submission.testresult.TestResultUIState +import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents +import de.rki.coronawarnapp.util.coroutine.DispatcherProvider +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.filterNotNull +import kotlinx.coroutines.flow.map +import timber.log.Timber + +class SubmissionTestResultKeysSharedViewModel @AssistedInject constructor( + private val submissionRepository: SubmissionRepository, + @Assisted val testType: Type, + dispatcherProvider: DispatcherProvider +) : CWAViewModel(dispatcherProvider = dispatcherProvider) { + + init { + Timber.v("init() coronaTestType=%s", testType) + } + + val uiState: LiveData<TestResultUIState> = submissionRepository.testForType(type = testType) + .filterNotNull() + .map { test -> + TestResultUIState(coronaTest = test) + }.asLiveData(context = Dispatchers.Default) + + val routeToScreen: SingleLiveEvent<SubmissionNavigationEvents> = SingleLiveEvent() + + val showDeleteTestDialog = SingleLiveEvent<Unit>() + + fun onTestOpened() = launch { + submissionRepository.setViewedTestResult(type = testType) + } + + fun onShowDeleteTestDialog() { + showDeleteTestDialog.postValue(Unit) + } + + fun onDeleteTestConfirmed() { + submissionRepository.removeTestFromDevice(type = testType) + } + + @AssistedFactory + interface Factory : CWAViewModelFactory<SubmissionTestResultKeysSharedViewModel> { + fun create(testType: Type): SubmissionTestResultKeysSharedViewModel + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionFragmentModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionFragmentModule.kt index 40b436ea56a0bf12eb637bcd3797854b2aa9d07e..2c573ff236da8691de9a51a61c6689b147ffa87c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionFragmentModule.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionFragmentModule.kt @@ -32,6 +32,8 @@ import de.rki.coronawarnapp.ui.submission.testresult.pending.SubmissionTestResul import de.rki.coronawarnapp.ui.submission.testresult.pending.SubmissionTestResultPendingModule import de.rki.coronawarnapp.ui.submission.testresult.positive.SubmissionTestResultConsentGivenFragment import de.rki.coronawarnapp.ui.submission.testresult.positive.SubmissionTestResultConsentGivenModule +import de.rki.coronawarnapp.ui.submission.testresult.positive.SubmissionTestResultKeysSharedFragment +import de.rki.coronawarnapp.ui.submission.testresult.positive.SubmissionTestResultKeysSharedModule import de.rki.coronawarnapp.ui.submission.testresult.positive.SubmissionTestResultNoConsentFragment import de.rki.coronawarnapp.ui.submission.testresult.positive.SubmissionTestResultNoConsentModule import de.rki.coronawarnapp.ui.submission.warnothers.SubmissionResultPositiveOtherWarningNoConsentFragment @@ -39,7 +41,7 @@ import de.rki.coronawarnapp.ui.submission.warnothers.SubmissionResultPositiveOth import de.rki.coronawarnapp.ui.submission.yourconsent.SubmissionYourConsentFragment import de.rki.coronawarnapp.ui.submission.yourconsent.SubmissionYourConsentModule -@Suppress("FunctionNaming", "MaxLineLength") +@Suppress("FunctionNaming", "MaxLineLength", "TooManyFunctions") @Module internal abstract class SubmissionFragmentModule { @@ -105,4 +107,7 @@ internal abstract class SubmissionFragmentModule { @ContributesAndroidInjector(modules = [RATResultNegativeModule::class]) abstract fun submissionNegativeRATResultScreen(): RATResultNegativeFragment + + @ContributesAndroidInjector(modules = [SubmissionTestResultKeysSharedModule::class]) + abstract fun submissionTestResultKeysSharedScreen(): SubmissionTestResultKeysSharedFragment } diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result_positive_keys_shared.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result_positive_keys_shared.xml new file mode 100644 index 0000000000000000000000000000000000000000..7f26366943bd40fbdf4faf1306c7d6efcd6be2bc --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result_positive_keys_shared.xml @@ -0,0 +1,153 @@ +<?xml version="1.0" encoding="utf-8"?> +<layout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/submission_test_result_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:accessibilityLiveRegion="assertive" + android:contentDescription="@string/submission_test_result_headline"> + + <androidx.appcompat.widget.Toolbar + android:id="@+id/toolbar" + style="@style/CWAToolbar.Close" + android:layout_width="match_parent" + android:layout_height="wrap_content" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:title="@string/submission_test_result_consent_given_heading" /> + + <ScrollView + android:id="@+id/scroll_view" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginBottom="12dp" + android:fillViewport="true" + app:layout_constraintBottom_toTopOf="@id/delete_test" + app:layout_constraintTop_toBottomOf="@id/toolbar"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:focusable="true"> + + <de.rki.coronawarnapp.ui.view.TestResultSectionView + android:id="@+id/submission_test_result_section" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginHorizontal="12dp" + android:focusable="true" + android:importantForAccessibility="yes" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <TextView + android:id="@+id/submission_done_text" + style="@style/subtitle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="24dp" + android:focusable="true" + android:text="@string/submission_done_body" + android:textStyle="bold" + app:layout_constraintEnd_toEndOf="@id/guideline_end" + app:layout_constraintStart_toStartOf="@id/guideline_start" + app:layout_constraintTop_toBottomOf="@id/submission_test_result_section" /> + + <TextView + android:id="@+id/submission_done_subtitle" + style="@style/headline5" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_normal" + android:accessibilityHeading="true" + android:focusable="true" + android:text="@string/submission_done_subtitle" + app:layout_constraintEnd_toEndOf="@id/guideline_end" + app:layout_constraintStart_toStartOf="@id/guideline_start" + app:layout_constraintTop_toBottomOf="@id/submission_done_text" /> + + <include + android:id="@+id/submission_done_pcr_validation" + layout="@layout/include_submission_behaviour_row" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_normal" + app:body="@{@string/submission_done_pcr_validation}" + app:icon="@{@drawable/ic_faq_information}" + app:layout_constraintEnd_toEndOf="@id/guideline_end" + app:layout_constraintStart_toStartOf="@id/guideline_start" + app:layout_constraintTop_toBottomOf="@id/submission_done_subtitle" /> + + <include + android:id="@+id/submission_done_contagious" + layout="@layout/include_submission_behaviour_row" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_normal" + app:body="@{@string/submission_done_contagious}" + app:icon="@{@drawable/ic_phone_white}" + app:layout_constraintEnd_toEndOf="@id/guideline_end" + app:layout_constraintStart_toStartOf="@id/guideline_start" + app:layout_constraintTop_toBottomOf="@id/submission_done_pcr_validation" /> + + <include + android:id="@+id/submission_done_isolate" + layout="@layout/include_submission_behaviour_row" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_normal" + app:body="@{@string/submission_done_isolate}" + app:icon="@{@drawable/ic_risk_details_home}" + app:layout_constraintEnd_toEndOf="@id/guideline_end" + app:layout_constraintStart_toStartOf="@id/guideline_start" + app:layout_constraintTop_toBottomOf="@id/submission_done_contagious" /> + + <include + layout="@layout/include_submission_done_further_info" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_normal" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/submission_done_isolate" /> + + <include layout="@layout/merge_guidelines_side" /> + + </androidx.constraintlayout.widget.ConstraintLayout> + </ScrollView> + + <Button + android:id="@+id/delete_test" + style="@style/buttonPrimary" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginVertical="16dp" + android:text="@string/submission_test_result_pending_remove_test_button" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="@id/guideline_end" + app:layout_constraintStart_toStartOf="@id/guideline_start" + app:layout_constraintTop_toBottomOf="@id/guideline_action" /> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_action" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + app:layout_constraintGuide_end="@dimen/guideline_action" /> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_action_large" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + app:layout_constraintGuide_end="@dimen/guideline_action_large" /> + + <include layout="@layout/merge_guidelines_side" /> + + </androidx.constraintlayout.widget.ConstraintLayout> + +</layout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml index bfa756731ac7755907337488500703bb9deb018a..a120516f8ed5d5fa664256029c21f00b80ad4cf6 100644 --- a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml +++ b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml @@ -67,6 +67,9 @@ <action android:id="@+id/action_mainFragment_to_submissionNegativeAntigenTestResultFragment" app:destination="@id/submissionNegativeAntigenTestResultFragment" /> + <action + android:id="@+id/action_mainFragment_to_submissionTestResultKeysSharedFragment" + app:destination="@id/submissionTestResultKeysSharedFragment" /> </fragment> <fragment @@ -788,4 +791,13 @@ android:name="testType" app:argType="de.rki.coronawarnapp.coronatest.type.CoronaTest$Type"/> </fragment> + <fragment + android:id="@+id/submissionTestResultKeysSharedFragment" + android:name="de.rki.coronawarnapp.ui.submission.testresult.positive.SubmissionTestResultKeysSharedFragment" + android:label="SubmissionTestResultKeysSharedFragment" + tools:layout="@layout/fragment_submission_test_result_positive_keys_shared"> + <argument + android:name="testType" + app:argType="de.rki.coronawarnapp.coronatest.type.CoronaTest$Type" /> + </fragment> </navigation>