From 1853cac14639ff3da91c2ac0df02e3a9acf5b52a Mon Sep 17 00:00:00 2001 From: Kolya Opahle <k.opahle@sap.com> Date: Fri, 5 Jun 2020 17:13:47 +0200 Subject: [PATCH] Removing the registration fragment (#184) * Added the TestAlreadyPairedException to the web request builder * Added specific exceptions to all submission web requests * Moved setting activity of DialogHelper to show call * Re added the requestIDS to all listeners for later use * Added Exception live data to view model * Added error dialogs to RegisterDeviceFragment screen * Added null check to networkResponse in VolleyError * Added error dialogs to SubmissionTestResultFragment screen * Fixed wrong view model call * Added error dialogs to SubmissionResultPositiveOtherWarningFragment * Added missing imports * Revert "Added specific exceptions to all submission web requests" This reverts commit 88d9027e24dd8b8c0baae7478c15cb23af403a0f. * Revert "Added the TestAlreadyPairedException to the web request builder" This reverts commit a4fb8272d89dd1e508a50002827fbc0dc7d86919. * added specific error handing to services * Switched error handlers to retrofit * Extracted status code numbers to constants * Added final strings for http error handling * Removed RegisterDeviceFragment from app and added a Event helper * Lint fixes * removed error report for networking exceptions * Added event wrapper to scan status to allow for rescanning of failed qrs * linting * Switched most view model LiveData to Event Co-authored-by: marcmuschko <marc.muschko@sap.com> --- .../SubmissionQRCodeScanFragment.kt | 63 +++++++++-- .../SubmissionRegisterDeviceFragment.kt | 100 ------------------ ...ssionResultPositiveOtherWarningFragment.kt | 10 +- .../ui/submission/SubmissionTanFragment.kt | 63 ++++++++++- .../SubmissionTestResultFragment.kt | 8 +- .../ui/viewmodel/SubmissionViewModel.kt | 57 ++++++---- .../java/de/rki/coronawarnapp/util/Event.kt | 28 +++++ .../fragment_submission_register_device.xml | 78 -------------- .../src/main/res/navigation/nav_graph.xml | 25 ++--- 9 files changed, 191 insertions(+), 241 deletions(-) delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionRegisterDeviceFragment.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/Event.kt delete mode 100644 Corona-Warn-App/src/main/res/layout/fragment_submission_register_device.xml diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt index 928c49fc3..bcee7773c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt @@ -5,18 +5,20 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.fragment.app.viewModels -import androidx.lifecycle.Observer +import androidx.fragment.app.activityViewModels import com.google.zxing.BarcodeFormat import com.journeyapps.barcodescanner.BarcodeResult import com.journeyapps.barcodescanner.DefaultDecoderFactory import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentSubmissionQrCodeScanBinding +import de.rki.coronawarnapp.exception.TestAlreadyPairedException import de.rki.coronawarnapp.ui.BaseFragment import de.rki.coronawarnapp.ui.main.MainActivity import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.util.CameraPermissionHelper import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.util.observeEvent +import retrofit2.HttpException /** * A simple [BaseFragment] subclass. @@ -28,7 +30,7 @@ class SubmissionQRCodeScanFragment : BaseFragment() { private val TAG: String? = SubmissionQRCodeScanFragment::class.simpleName } - private val viewModel: SubmissionViewModel by viewModels() + private val viewModel: SubmissionViewModel by activityViewModels() private var _binding: FragmentSubmissionQrCodeScanBinding? = null private val binding: FragmentSubmissionQrCodeScanBinding get() = _binding!! @@ -55,6 +57,41 @@ class SubmissionQRCodeScanFragment : BaseFragment() { _binding = null } + private fun buildErrorDialog(exception: Exception): DialogHelper.DialogInstance { + return when (exception) { + is TestAlreadyPairedException -> DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_error_dialog_web_test_paired_title, + R.string.submission_error_dialog_web_test_paired_body, + R.string.submission_error_dialog_web_test_paired_button_positive, + null, + true, + ::navigateToDispatchScreen + ) + is HttpException -> DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_error_dialog_web_generic_error_title, + getString( + R.string.submission_error_dialog_web_generic_network_error_body, + exception.code() + ), + R.string.submission_error_dialog_web_generic_error_button_positive, + null, + true, + ::navigateToDispatchScreen + ) + else -> DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_error_dialog_web_generic_error_title, + R.string.submission_error_dialog_web_generic_error_body, + R.string.submission_error_dialog_web_generic_error_button_positive, + null, + true, + ::navigateToDispatchScreen + ) + } + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -72,7 +109,7 @@ class SubmissionQRCodeScanFragment : BaseFragment() { DefaultDecoderFactory(listOf(BarcodeFormat.QR_CODE)) binding.submissionQrCodeScanViewfinderView.setCameraPreview(binding.submissionQrCodeScanPreview) - viewModel.scanStatus.observe(viewLifecycleOwner, Observer { + viewModel.scanStatus.observeEvent(viewLifecycleOwner, { if (ScanStatus.SUCCESS == it) { showSuccessfulScanDialog() } @@ -81,6 +118,19 @@ class SubmissionQRCodeScanFragment : BaseFragment() { showInvalidScanDialog() } }) + + viewModel.registrationState.observeEvent(viewLifecycleOwner, { + if (ApiRequestState.SUCCESS == it) { + doNavigate( + SubmissionQRCodeScanFragmentDirections + .actionSubmissionQRCodeScanFragmentToSubmissionResultFragment() + ) + } + }) + + viewModel.registrationError.observeEvent(viewLifecycleOwner, { + DialogHelper.showDialog(buildErrorDialog(it)) + }) } private fun navigateToDispatchScreen() = @@ -98,10 +148,7 @@ class SubmissionQRCodeScanFragment : BaseFragment() { R.string.submission_qr_code_scan_successful_dialog_button_negative, true, { - doNavigate( - SubmissionQRCodeScanFragmentDirections - .actionSubmissionQRCodeScanFragmentToSubmissionRegisterDeviceFragment() - ) + viewModel.doDeviceRegistration() }, { viewModel.deleteTestGUID() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionRegisterDeviceFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionRegisterDeviceFragment.kt deleted file mode 100644 index 6a49eba8c..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionRegisterDeviceFragment.kt +++ /dev/null @@ -1,100 +0,0 @@ -package de.rki.coronawarnapp.ui.submission - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.activityViewModels -import androidx.lifecycle.Observer -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.databinding.FragmentSubmissionRegisterDeviceBinding -import de.rki.coronawarnapp.exception.TestAlreadyPairedException -import de.rki.coronawarnapp.ui.BaseFragment -import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel -import de.rki.coronawarnapp.util.DialogHelper -import retrofit2.HttpException - -class SubmissionRegisterDeviceFragment : BaseFragment() { - private val viewModel: SubmissionViewModel by activityViewModels() - private var _binding: FragmentSubmissionRegisterDeviceBinding? = null - private val binding: FragmentSubmissionRegisterDeviceBinding get() = _binding!! - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - _binding = FragmentSubmissionRegisterDeviceBinding.inflate(inflater) - binding.lifecycleOwner = this - return binding.root - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } - - private fun navigateToDispatchScreen() = doNavigate( - SubmissionRegisterDeviceFragmentDirections - .actionSubmissionRegisterDeviceFragmentToSubmissionDispatcherFragment() - ) - - private fun buildErrorDialog(exception: Exception): DialogHelper.DialogInstance { - return when (exception) { - is TestAlreadyPairedException -> DialogHelper.DialogInstance( - requireActivity(), - R.string.submission_error_dialog_web_test_paired_title, - R.string.submission_error_dialog_web_test_paired_body, - R.string.submission_error_dialog_web_test_paired_button_positive, - null, - true, - ::navigateToDispatchScreen - ) - is HttpException -> DialogHelper.DialogInstance( - requireActivity(), - R.string.submission_error_dialog_web_generic_error_title, - getString( - R.string.submission_error_dialog_web_generic_network_error_body, - exception.code() - ), - R.string.submission_error_dialog_web_generic_error_button_positive, - null, - true, - ::navigateToDispatchScreen - ) - else -> DialogHelper.DialogInstance( - requireActivity(), - R.string.submission_error_dialog_web_generic_error_title, - R.string.submission_error_dialog_web_generic_error_body, - R.string.submission_error_dialog_web_generic_error_button_positive, - null, - true, - ::navigateToDispatchScreen - ) - } - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - viewModel.registrationState.observe(viewLifecycleOwner, Observer { - if (ApiRequestState.SUCCESS == it) { - doNavigate( - SubmissionRegisterDeviceFragmentDirections - .actionSubmissionRegisterDeviceFragmentToSubmissionResultFragment() - ) - } - }) - - viewModel.registrationError.observe(viewLifecycleOwner, Observer { - if (it != null) { - DialogHelper.showDialog(buildErrorDialog(it)) - } - }) - } - - override fun onResume() { - super.onResume() - viewModel.doDeviceRegistration() - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt index 2322c093d..477722597 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt @@ -5,7 +5,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.activityViewModels -import androidx.lifecycle.Observer import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentSubmissionPositiveOtherWarningBinding @@ -16,6 +15,7 @@ import de.rki.coronawarnapp.ui.BaseFragment import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.util.observeEvent import retrofit2.HttpException class SubmissionResultPositiveOtherWarningFragment : BaseFragment(), @@ -117,13 +117,11 @@ class SubmissionResultPositiveOtherWarningFragment : BaseFragment(), super.onViewCreated(view, savedInstanceState) setButtonOnClickListener() - submissionViewModel.submissionError.observe(viewLifecycleOwner, Observer { - if (it != null) { - DialogHelper.showDialog(buildErrorDialog(it)) - } + submissionViewModel.submissionError.observeEvent(viewLifecycleOwner, { + DialogHelper.showDialog(buildErrorDialog(it)) }) - submissionViewModel.submissionState.observe(viewLifecycleOwner, Observer { + submissionViewModel.submissionState.observeEvent(viewLifecycleOwner, { if (it == ApiRequestState.SUCCESS) { doNavigate( SubmissionResultPositiveOtherWarningFragmentDirections diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt index c01259274..56b4c4608 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt @@ -5,8 +5,14 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.activityViewModels +import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentSubmissionTanBinding +import de.rki.coronawarnapp.exception.TestAlreadyPairedException import de.rki.coronawarnapp.ui.BaseFragment +import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel +import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.util.observeEvent +import retrofit2.HttpException /** * Fragment for TAN entry @@ -14,6 +20,7 @@ import de.rki.coronawarnapp.ui.BaseFragment class SubmissionTanFragment : BaseFragment() { private val viewModel: SubmissionTanViewModel by activityViewModels() + private val submissionViewModel: SubmissionViewModel by activityViewModels() private var _binding: FragmentSubmissionTanBinding? = null private val binding: FragmentSubmissionTanBinding get() = _binding!! @@ -34,18 +41,64 @@ class SubmissionTanFragment : BaseFragment() { _binding = null } + private fun buildErrorDialog(exception: Exception): DialogHelper.DialogInstance { + return when (exception) { + is TestAlreadyPairedException -> DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_error_dialog_web_test_paired_title, + R.string.submission_error_dialog_web_test_paired_body, + R.string.submission_error_dialog_web_test_paired_button_positive, + null, + true, + ::navigateToDispatchScreen + ) + is HttpException -> DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_error_dialog_web_generic_error_title, + getString( + R.string.submission_error_dialog_web_generic_network_error_body, + exception.code() + ), + R.string.submission_error_dialog_web_generic_error_button_positive, + null, + true, + ::navigateToDispatchScreen + ) + else -> DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_error_dialog_web_generic_error_title, + R.string.submission_error_dialog_web_generic_error_body, + R.string.submission_error_dialog_web_generic_error_button_positive, + null, + true, + ::navigateToDispatchScreen + ) + } + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.submissionTanInput.listener = { tan -> viewModel.tan.value = tan } binding.submissionTanButtonEnter.setOnClickListener { storeTanAndContinue() } - binding.submissionTanHeader.headerButtonBack.buttonIcon.setOnClickListener { close() } - } + binding.submissionTanHeader.headerButtonBack.buttonIcon.setOnClickListener { navigateToDispatchScreen() } - private fun close() { - doNavigate(SubmissionTanFragmentDirections.actionSubmissionTanFragmentToMainFragment()) + submissionViewModel.registrationState.observeEvent(viewLifecycleOwner, { + if (ApiRequestState.SUCCESS == it) { + doNavigate( + SubmissionTanFragmentDirections.actionSubmissionTanFragmentToSubmissionResultFragment() + ) + } + }) + + submissionViewModel.registrationError.observeEvent(viewLifecycleOwner, { + DialogHelper.showDialog(buildErrorDialog(it)) + }) } + private fun navigateToDispatchScreen() = + doNavigate(SubmissionTanFragmentDirections.actionSubmissionTanFragmentToSubmissionDispatcherFragment()) + private fun storeTanAndContinue() { // verify input format if (viewModel.isValidTanFormat.value != true) @@ -54,6 +107,6 @@ class SubmissionTanFragment : BaseFragment() { // store locally viewModel.storeTeletan() - doNavigate(SubmissionTanFragmentDirections.actionSubmissionTanFragmentToSubmissionRegisterDeviceFragment()) + submissionViewModel.doDeviceRegistration() } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt index 737e8f6e3..917c796df 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt @@ -5,13 +5,13 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.activityViewModels -import androidx.lifecycle.Observer import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentSubmissionTestResultBinding import de.rki.coronawarnapp.ui.BaseFragment import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.util.observeEvent import retrofit2.HttpException /** @@ -79,10 +79,8 @@ class SubmissionTestResultFragment : BaseFragment() { super.onViewCreated(view, savedInstanceState) setButtonOnClickListener() - submissionViewModel.uiStateError.observe(viewLifecycleOwner, Observer { - if (it != null) { - DialogHelper.showDialog(buildErrorDialog(it)) - } + submissionViewModel.uiStateError.observeEvent(viewLifecycleOwner, { + DialogHelper.showDialog(buildErrorDialog(it)) }) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt index bac24dc8d..39431e54f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt @@ -4,39 +4,38 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import de.rki.coronawarnapp.exception.ExceptionCategory -import de.rki.coronawarnapp.exception.report import de.rki.coronawarnapp.service.submission.SubmissionService import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.ui.submission.ScanStatus import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.Event import kotlinx.coroutines.launch import java.util.Date class SubmissionViewModel : ViewModel() { - private val _scanStatus = MutableLiveData(ScanStatus.STARTED) + private val _scanStatus = MutableLiveData(Event(ScanStatus.STARTED)) - private val _registrationState = MutableLiveData(ApiRequestState.IDLE) - private val _registrationError = MutableLiveData<Exception?>(null) + private val _registrationState = MutableLiveData(Event(ApiRequestState.IDLE)) + private val _registrationError = MutableLiveData<Event<Exception>>(null) private val _uiStateState = MutableLiveData(ApiRequestState.IDLE) - private val _uiStateError = MutableLiveData<Exception?>(null) + private val _uiStateError = MutableLiveData<Event<Exception>>(null) - private val _submissionState = MutableLiveData(ApiRequestState.IDLE) - private val _submissionError = MutableLiveData<Exception?>(null) + private val _submissionState = MutableLiveData(Event(ApiRequestState.IDLE)) + private val _submissionError = MutableLiveData<Event<Exception>>(null) - val scanStatus: LiveData<ScanStatus> = _scanStatus + val scanStatus: LiveData<Event<ScanStatus>> = _scanStatus - val registrationState: LiveData<ApiRequestState> = _registrationState - val registrationError: LiveData<Exception?> = _registrationError + val registrationState: LiveData<Event<ApiRequestState>> = _registrationState + val registrationError: LiveData<Event<Exception>> = _registrationError val uiStateState: LiveData<ApiRequestState> = _uiStateState - val uiStateError: LiveData<Exception?> = _uiStateError + val uiStateError: LiveData<Event<Exception>> = _uiStateError - val submissionState: LiveData<ApiRequestState> = _submissionState - val submissionError: LiveData<Exception?> = _submissionError + val submissionState: LiveData<Event<ApiRequestState>> = _submissionState + val submissionError: LiveData<Event<Exception>> = _submissionError val deviceRegistered get() = LocalData.registrationToken() != null @@ -46,14 +45,14 @@ class SubmissionViewModel : ViewModel() { SubmissionRepository.deviceUIState fun submitDiagnosisKeys() = - executeRequestWithState( + executeRequestWithStateForEvent( SubmissionService::asyncSubmitExposureKeys, _submissionState, _submissionError ) fun doDeviceRegistration() = - executeRequestWithState( + executeRequestWithStateForEvent( SubmissionService::asyncRegisterDevice, _registrationState, _registrationError @@ -70,9 +69,9 @@ class SubmissionViewModel : ViewModel() { if (SubmissionService.containsValidGUID(scanResult)) { val guid = SubmissionService.extractGUID(scanResult) SubmissionService.storeTestGUID(guid) - _scanStatus.value = ScanStatus.SUCCESS + _scanStatus.value = Event(ScanStatus.SUCCESS) } else { - _scanStatus.value = ScanStatus.INVALID + _scanStatus.value = Event(ScanStatus.INVALID) } } @@ -90,7 +89,7 @@ class SubmissionViewModel : ViewModel() { private fun executeRequestWithState( apiRequest: suspend () -> Unit, state: MutableLiveData<ApiRequestState>, - exceptionLiveData: MutableLiveData<Exception?>? = null + exceptionLiveData: MutableLiveData<Event<Exception>>? = null ) { state.value = ApiRequestState.STARTED viewModelScope.launch { @@ -98,9 +97,25 @@ class SubmissionViewModel : ViewModel() { apiRequest() state.value = ApiRequestState.SUCCESS } catch (err: Exception) { - exceptionLiveData?.value = err + exceptionLiveData?.value = Event(err) state.value = ApiRequestState.FAILED - err.report(ExceptionCategory.INTERNAL) + } + } + } + + private fun executeRequestWithStateForEvent( + apiRequest: suspend () -> Unit, + state: MutableLiveData<Event<ApiRequestState>>, + exceptionLiveData: MutableLiveData<Event<Exception>>? = null + ) { + state.value = Event(ApiRequestState.STARTED) + viewModelScope.launch { + try { + apiRequest() + state.value = Event(ApiRequestState.SUCCESS) + } catch (err: Exception) { + exceptionLiveData?.value = Event(err) + state.value = Event(ApiRequestState.FAILED) } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/Event.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/Event.kt new file mode 100644 index 000000000..586d04069 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/Event.kt @@ -0,0 +1,28 @@ +package de.rki.coronawarnapp.util + +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LiveData +import androidx.lifecycle.Observer + +/** + * Helper to supply live data that can only be observed once + */ +open class Event<out T>(private val eventContent: T) { + private var handled = false + + fun getContent(): T? { + return if (handled) { + null + } else { + handled = true + eventContent + } + } +} + +inline fun <T> LiveData<Event<T>>.observeEvent( + owner: LifecycleOwner, + crossinline onEvent: (T) -> Unit +) { + observe(owner, Observer { it?.getContent()?.let(onEvent) }) +} diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_register_device.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_register_device.xml deleted file mode 100644 index 359284ebf..000000000 --- a/Corona-Warn-App/src/main/res/layout/fragment_submission_register_device.xml +++ /dev/null @@ -1,78 +0,0 @@ -<?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" - xmlns:tools="http://schemas.android.com/tools"> - - <ScrollView - android:layout_width="match_parent" - android:layout_height="match_parent" - android:fillViewport="true" - tools:context=".ui.submission.SubmissionRegisterDeviceFragment"> - - <androidx.constraintlayout.widget.ConstraintLayout - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - - <TextView - android:id="@+id/submission_register_device_headline" - style="@style/textTitle" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:text="@string/submission_register_device_headline" - app:layout_constraintEnd_toStartOf="@+id/submission_register_device_guideline_end" - app:layout_constraintStart_toStartOf="@+id/submission_register_device_guideline_start" - app:layout_constraintTop_toTopOf="@+id/submission_register_device_guideline_top" /> - - <TextView - android:id="@+id/submission_register_device_text" - style="@style/textMultiline" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:text="@string/submission_register_device_body" - app:layout_constraintEnd_toStartOf="@+id/submission_register_device_guideline_end" - app:layout_constraintStart_toStartOf="@+id/submission_register_device_guideline_start" - app:layout_constraintTop_toBottomOf="@+id/submission_register_device_headline" /> - - <ProgressBar - android:id="@+id/submission_register_device_spinner" - style="?android:attr/progressBarStyle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:layout_constraintBottom_toTopOf="@+id/submission_register_device_guideline_bottom" - app:layout_constraintEnd_toStartOf="@+id/submission_register_device_guideline_end" - app:layout_constraintStart_toStartOf="@+id/submission_register_device_guideline_start" - app:layout_constraintTop_toBottomOf="@+id/submission_register_device_text" /> - - <androidx.constraintlayout.widget.Guideline - android:id="@+id/submission_register_device_guideline_start" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical" - app:layout_constraintGuide_begin="@dimen/guideline_start" /> - - <androidx.constraintlayout.widget.Guideline - android:id="@+id/submission_register_device_guideline_bottom" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal" - app:layout_constraintGuide_end="@dimen/guideline_bottom" /> - - <androidx.constraintlayout.widget.Guideline - android:id="@+id/submission_register_device_guideline_end" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical" - app:layout_constraintGuide_end="@dimen/guideline_end" /> - - <androidx.constraintlayout.widget.Guideline - android:id="@+id/submission_register_device_guideline_top" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal" - app:layout_constraintGuide_begin="@dimen/guideline_top" /> - - </androidx.constraintlayout.widget.ConstraintLayout> - - </ScrollView> -</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 c62db62a7..6ae74c712 100644 --- a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml +++ b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml @@ -242,13 +242,15 @@ android:label="fragment_submission_tan" tools:layout="@layout/fragment_submission_tan"> <action - android:id="@+id/action_submissionTanFragment_to_mainFragment" + android:id="@+id/action_submissionTanFragment_to_submissionDispatcherFragment" app:destination="@id/submissionDispatcherFragment" app:popUpTo="@id/submissionDispatcherFragment" app:popUpToInclusive="true" /> <action - android:id="@+id/action_submissionTanFragment_to_submissionRegisterDeviceFragment" - app:destination="@id/submissionRegisterDeviceFragment" /> + android:id="@+id/action_submissionTanFragment_to_submissionResultFragment" + app:destination="@id/submissionResultFragment" + app:popUpTo="@id/submissionResultFragment" + app:popUpToInclusive="true" /> </fragment> <fragment @@ -282,22 +284,9 @@ app:popUpTo="@id/submissionDispatcherFragment" app:popUpToInclusive="true" /> <action - android:id="@+id/action_submissionQRCodeScanFragment_to_submissionRegisterDeviceFragment" - app:destination="@id/submissionRegisterDeviceFragment" /> - </fragment> - <fragment - android:id="@+id/submissionRegisterDeviceFragment" - android:name="de.rki.coronawarnapp.ui.submission.SubmissionRegisterDeviceFragment" - android:label="SubmissionRegisterDeviceFragment"> - <action - android:id="@+id/action_submissionRegisterDeviceFragment_to_submissionResultFragment" + android:id="@+id/action_submissionQRCodeScanFragment_to_submissionResultFragment" app:destination="@id/submissionResultFragment" - app:popUpTo="@id/mainFragment" /> - <action - android:id="@+id/action_submissionRegisterDeviceFragment_to_submissionDispatcherFragment" - app:destination="@id/submissionDispatcherFragment" - app:popUpTo="@id/submissionDispatcherFragment" - app:popUpToInclusive="true" /> + app:popUpTo="@id/submissionResultFragment" /> </fragment> <fragment android:id="@+id/submissionDoneFragment" -- GitLab