diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/datadonation/ui/DataDonationTestFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/datadonation/ui/DataDonationTestFragment.kt index 50cc66cc563..abca7a9eba9 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/datadonation/ui/DataDonationTestFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/datadonation/ui/DataDonationTestFragment.kt @@ -15,7 +15,7 @@ import de.rki.coronawarnapp.databinding.FragmentTestDatadonationBinding import de.rki.coronawarnapp.datadonation.safetynet.SafetyNetException import de.rki.coronawarnapp.datadonation.survey.SurveyException import de.rki.coronawarnapp.test.menu.ui.TestMenuItem -import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.tryHumanReadableError import de.rki.coronawarnapp.util.ui.observe2 @@ -114,14 +114,12 @@ class DataDonationTestFragment : Fragment(R.layout.fragment_test_datadonation), vm.showErrorDialog.observe2(this) { val humanReadableError = it.tryHumanReadableError(requireContext()) - val dialog = DialogHelper.DialogInstance( - context = requireContext(), - title = R.string.datadonation_details_survey_consent_error_dialog_title, - message = humanReadableError.description, - positiveButton = R.string.datadonation_details_survey_consent_error_dialog_pos_button, - cancelable = false - ) - DialogHelper.showDialog(dialog) + displayDialog { + title(R.string.datadonation_details_survey_consent_error_dialog_title) + message(humanReadableError.description) + positiveButton(R.string.datadonation_details_survey_consent_error_dialog_pos_button) + setCancelable(false) + } } vm.currentSafetyNetExceptionType.observe2(this) { type -> diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragment.kt index b727fe035c3..bd0dfacb9fb 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragment.kt @@ -13,12 +13,12 @@ import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController -import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import com.jakewharton.processphoenix.ProcessPhoenix import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentTestDebugoptionsBinding import de.rki.coronawarnapp.test.menu.ui.TestMenuItem +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.observe2 @@ -49,11 +49,11 @@ class DebugOptionsFragment : Fragment(R.layout.fragment_test_debugoptions), Auto if (!chip.isPressed) return@setOnCheckedChangeListener val type = chip.text.toString() vm.selectEnvironmentType(type) - MaterialAlertDialogBuilder(requireContext()) - .setTitle("Restarting ↻") - .setMessage("Configuring $type environment. Get yourself a glass of water \uD83D\uDEB0") - .setCancelable(false) - .show() + displayDialog { + title("Restarting ↻") + message("Configuring $type environment. Get yourself a glass of water \uD83D\uDEB0") + setCancelable(false) + } ProcessPhoenix.triggerRebirth(context) } } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/presencetracing/ui/PresenceTracingTestFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/presencetracing/ui/PresenceTracingTestFragment.kt index 9db001fff63..744e732e4da 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/presencetracing/ui/PresenceTracingTestFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/presencetracing/ui/PresenceTracingTestFragment.kt @@ -13,10 +13,10 @@ import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentTestPresenceTracingBinding import de.rki.coronawarnapp.presencetracing.checkins.qrcode.TraceLocation import de.rki.coronawarnapp.test.menu.ui.TestMenuItem +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.observe2 @@ -94,9 +94,7 @@ class PresenceTracingTestFragment : Fragment(R.layout.fragment_test_presence_tra } } - viewModel.error.observe(viewLifecycleOwner) { - it.toErrorDialogBuilder(requireContext()).show() - } + viewModel.error.observe(viewLifecycleOwner) { displayDialog { setError(it) } } viewModel.submissionResult.observe(viewLifecycleOwner) { Toast.makeText(requireContext(), "Organizer submission passed", Toast.LENGTH_LONG).show() diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragment.kt index a439eb3a02b..591d6e08910 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragment.kt @@ -7,10 +7,10 @@ import android.view.View import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentTestSubmissionBinding import de.rki.coronawarnapp.test.menu.ui.TestMenuItem import de.rki.coronawarnapp.tracing.ui.tracingConsentDialog +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.diffutil.update import de.rki.coronawarnapp.util.ui.observe2 @@ -51,9 +51,7 @@ class SubmissionTestFragment : Fragment(R.layout.fragment_test_submission), Auto startActivity(share) } - vm.errorEvents.observe2(this) { - it.toErrorDialogBuilder(requireContext()).show() - } + vm.errorEvents.observe2(this) { displayDialog { setError(it) } } binding.apply { tekRetrieval.setOnClickListener { vm.updateStorage() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/debuglog/ui/DebugLogFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/debuglog/ui/DebugLogFragment.kt index 58dc70e9d91..5ea89247f42 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/debuglog/ui/DebugLogFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/debuglog/ui/DebugLogFragment.kt @@ -10,12 +10,11 @@ import androidx.core.view.isGone import androidx.core.widget.NestedScrollView import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController -import com.google.android.material.dialog.MaterialAlertDialogBuilder import de.rki.coronawarnapp.R import de.rki.coronawarnapp.bugreporting.debuglog.internal.LogSnapshotter import de.rki.coronawarnapp.databinding.BugreportingDebuglogFragmentBinding +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.ContextExtensions.getDrawableCompat -import de.rki.coronawarnapp.util.DialogHelper import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.files.FileSharing import de.rki.coronawarnapp.util.ui.observe2 @@ -24,9 +23,9 @@ import de.rki.coronawarnapp.util.ui.setGone import de.rki.coronawarnapp.util.ui.viewBinding import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider import de.rki.coronawarnapp.util.viewmodel.cwaViewModels +import setTextWithUrl import java.time.Duration import java.time.Instant -import setTextWithUrl import javax.inject.Inject class DebugLogFragment : Fragment(R.layout.bugreporting_debuglog_fragment), AutoInject { @@ -160,31 +159,25 @@ class DebugLogFragment : Fragment(R.layout.bugreporting_debuglog_fragment), Auto binding.debugLogHistoryContainer.setOnClickListener { vm.onIdHistoryPress() } } - private fun showLogDeletionRequest() = DialogHelper.showDialog( - DialogHelper.DialogInstance( - context = requireContext(), - title = R.string.debugging_debuglog_stop_confirmation_title, - message = R.string.debugging_debuglog_stop_confirmation_message, - positiveButton = R.string.debugging_debuglog_stop_confirmation_confirmation_button, - negativeButton = R.string.debugging_debuglog_stop_confirmation_discard_button, - positiveButtonFunction = { vm.stopAndDeleteDebugLog() }, - isDeleteDialog = true - ) - ) - - private fun showLowStorageError() { - MaterialAlertDialogBuilder(requireContext()).apply { - setTitle(R.string.errors_generic_headline_short) - setMessage(R.string.debugging_debuglog_start_low_storage_error) - setPositiveButton(android.R.string.ok) { _, _ -> /* dismiss */ } - setNeutralButton(R.string.menu_settings) { _, _ -> - try { - startActivity(Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS)) - } catch (e: Exception) { - Toast.makeText(requireContext(), e.toString(), Toast.LENGTH_LONG).show() - } + private fun showLogDeletionRequest() = displayDialog { + title(R.string.debugging_debuglog_stop_confirmation_title) + message(R.string.debugging_debuglog_stop_confirmation_message) + positiveButton(R.string.debugging_debuglog_stop_confirmation_confirmation_button) { vm.stopAndDeleteDebugLog() } + negativeButton(R.string.debugging_debuglog_stop_confirmation_discard_button) + setDeleteDialog(true) + } + + private fun showLowStorageError() = displayDialog { + title(R.string.errors_generic_headline_short) + message(R.string.debugging_debuglog_start_low_storage_error) + positiveButton(android.R.string.ok) + neutralButton(R.string.menu_settings) { + try { + startActivity(Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS)) + } catch (e: Exception) { + Toast.makeText(requireContext(), e.toString(), Toast.LENGTH_LONG).show() } - }.show() + } } private fun exportLog(snapshot: LogSnapshotter.Snapshot) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/debuglog/ui/upload/DebugLogUploadFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/debuglog/ui/upload/DebugLogUploadFragment.kt index 2b8dc8c9ace..727af4bfc32 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/debuglog/ui/upload/DebugLogUploadFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/debuglog/ui/upload/DebugLogUploadFragment.kt @@ -6,9 +6,9 @@ import android.view.accessibility.AccessibilityEvent import android.widget.Toast import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController -import com.google.android.material.dialog.MaterialAlertDialogBuilder import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.BugreportingDebuglogUploadFragmentBinding +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.popBackStack @@ -48,10 +48,10 @@ class DebugLogUploadFragment : Fragment(R.layout.bugreporting_debuglog_upload_fr } vm.errorEvent.observe2(this) { - MaterialAlertDialogBuilder(requireContext()).apply { - setTitle(getString(R.string.errors_generic_headline)) - setMessage(R.string.debugging_debuglog_share_try_again_later) - }.show() + displayDialog { + title(getString(R.string.errors_generic_headline)) + message(R.string.debugging_debuglog_share_try_again_later) + } } vm.uploadInProgress.observe2(this) { uploadDialog.setState(it) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/ui/ErrorDialog.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/ui/ErrorDialog.kt deleted file mode 100644 index a9160a17833..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/ui/ErrorDialog.kt +++ /dev/null @@ -1,51 +0,0 @@ -package de.rki.coronawarnapp.bugreporting.ui - -import android.content.Context -import android.text.SpannableString -import android.text.method.LinkMovementMethod -import android.text.util.Linkify -import android.widget.TextView -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.util.ContextExtensions.getColorStateListCompat -import de.rki.coronawarnapp.util.tryHumanReadableError -import java.util.regex.Pattern - -private fun MaterialAlertDialogBuilder.setMessageView( - message: String, - textHasLinks: Boolean, -) { - // create spannable and add links, removed stack trace links into nowhere - val spannable = SpannableString(message) - val httpPattern: Pattern = Pattern.compile("[a-z]+://[^ \\n]*") - Linkify.addLinks(spannable, httpPattern, "") - - val paddingStartEnd = context.resources.getDimension(R.dimen.spacing_normal).toInt() - val paddingLeftRight = context.resources.getDimension(R.dimen.spacing_small).toInt() - - val textView = TextView(context, null, R.style.TextAppearance_AppCompat_Subhead).apply { - text = spannable - linksClickable = true - movementMethod = LinkMovementMethod.getInstance() - setPadding( - paddingStartEnd, - paddingLeftRight, - paddingStartEnd, - paddingLeftRight - ) - setLinkTextColor(context.getColorStateListCompat(R.color.button_primary)) - setTextIsSelectable(!textHasLinks) - } - setView(textView) -} - -fun Throwable.toErrorDialogBuilder(context: Context) = - MaterialAlertDialogBuilder(context).apply { - val error = this@toErrorDialogBuilder - val humanReadable = error.tryHumanReadableError(context) - - setTitle(humanReadable.title ?: context.getString(R.string.errors_generic_headline_short)) - setMessageView(humanReadable.description, textHasLinks = true) - - setPositiveButton(R.string.errors_generic_button_positive) { _, _ -> } - } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsFragment.kt index 3a5f7454e08..63df2d5a783 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsFragment.kt @@ -11,7 +11,7 @@ import de.rki.coronawarnapp.contactdiary.ui.edit.ContactDiaryEditLocationsViewMo import de.rki.coronawarnapp.contactdiary.ui.edit.ContactDiaryEditLocationsViewModel.NavigationEvent.ShowLocationDetailFragment import de.rki.coronawarnapp.contactdiary.ui.edit.adapter.LocationEditAdapter import de.rki.coronawarnapp.databinding.ContactDiaryEditLocationsFragmentBinding -import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.diffutil.update import de.rki.coronawarnapp.util.ui.observe2 @@ -58,7 +58,7 @@ class ContactDiaryEditLocationsFragment : Fragment(R.layout.contact_diary_edit_l viewModel.navigationEvent.observe2(this) { when (it) { - ShowDeletionConfirmationDialog -> DialogHelper.showDialog(deleteAllLocationsConfirmationDialog) + ShowDeletionConfirmationDialog -> deleteAllLocationsConfirmationDialog() is ShowLocationDetailFragment -> { findNavController().navigate( ContactDiaryEditLocationsFragmentDirections @@ -85,17 +85,11 @@ class ContactDiaryEditLocationsFragment : Fragment(R.layout.contact_diary_edit_l binding.locationsRecyclerView.adapter = listAdapter } - private val deleteAllLocationsConfirmationDialog by lazy { - DialogHelper.DialogInstance( - requireActivity(), - R.string.contact_diary_delete_locations_title, - R.string.contact_diary_delete_locations_message, - R.string.contact_diary_delete_button_positive, - R.string.contact_diary_delete_button_negative, - positiveButtonFunction = { - viewModel.onDeleteAllConfirmedClick() - }, - isDeleteDialog = true - ) + private fun deleteAllLocationsConfirmationDialog() = displayDialog { + title(R.string.contact_diary_delete_locations_title) + message(R.string.contact_diary_delete_locations_message) + positiveButton(R.string.contact_diary_delete_button_positive) { viewModel.onDeleteAllLocationsClick() } + negativeButton(R.string.contact_diary_delete_button_negative) + setDeleteDialog(true) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditPersonsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditPersonsFragment.kt index d1f61fba243..9dee57b12c3 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditPersonsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditPersonsFragment.kt @@ -11,7 +11,7 @@ import de.rki.coronawarnapp.contactdiary.ui.edit.ContactDiaryEditPersonsViewMode import de.rki.coronawarnapp.contactdiary.ui.edit.ContactDiaryEditPersonsViewModel.NavigationEvent.ShowPersonDetailFragment import de.rki.coronawarnapp.contactdiary.ui.edit.adapter.PersonEditAdapter import de.rki.coronawarnapp.databinding.ContactDiaryEditPersonsFragmentBinding -import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.diffutil.update import de.rki.coronawarnapp.util.ui.addNavigationIconButtonId @@ -57,7 +57,7 @@ class ContactDiaryEditPersonsFragment : Fragment(R.layout.contact_diary_edit_per viewModel.navigationEvent.observe2(this) { when (it) { - ShowDeletionConfirmationDialog -> DialogHelper.showDialog(deleteAllPersonsConfirmationDialog) + ShowDeletionConfirmationDialog -> deleteAllPersonsConfirmationDialog() is ShowPersonDetailFragment -> { findNavController().navigate( ContactDiaryEditPersonsFragmentDirections @@ -88,17 +88,11 @@ class ContactDiaryEditPersonsFragment : Fragment(R.layout.contact_diary_edit_per binding.personsRecyclerView.adapter = listAdapter } - private val deleteAllPersonsConfirmationDialog by lazy { - DialogHelper.DialogInstance( - requireActivity(), - R.string.contact_diary_delete_persons_title, - R.string.contact_diary_delete_persons_message, - R.string.contact_diary_delete_button_positive, - R.string.contact_diary_delete_button_negative, - positiveButtonFunction = { - viewModel.onDeleteAllConfirmedClick() - }, - isDeleteDialog = true - ) + private fun deleteAllPersonsConfirmationDialog() = displayDialog { + title(R.string.contact_diary_delete_persons_title) + message(R.string.contact_diary_delete_persons_message) + positiveButton(R.string.contact_diary_delete_button_positive) { viewModel.onDeleteAllConfirmedClick() } + negativeButton(R.string.contact_diary_delete_button_negative) + setDeleteDialog(true) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationFragment.kt index 3d11932cc96..9ecf213ae72 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationFragment.kt @@ -11,7 +11,7 @@ import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.util.focusAndShowKeyboard import de.rki.coronawarnapp.contactdiary.util.hideKeyboard import de.rki.coronawarnapp.databinding.ContactDiaryAddLocationFragmentBinding -import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.setTextOnTextInput import de.rki.coronawarnapp.util.ui.observe2 @@ -54,9 +54,7 @@ class ContactDiaryAddLocationFragment : Fragment(R.layout.contact_diary_add_loca locationPhoneInput.setTextOnTextInput(location.phoneNumber, endIconVisible = false) locationEmailInput.setTextOnTextInput(location.emailAddress, endIconVisible = false) locationDeleteButton.visibility = View.VISIBLE - locationDeleteButton.setOnClickListener { - DialogHelper.showDialog(deleteLocationConfirmationDialog) - } + locationDeleteButton.setOnClickListener { deleteLocationConfirmationDialog() } locationSaveButton.setOnClickListener { viewModel.updateLocation( location, @@ -111,19 +109,15 @@ class ContactDiaryAddLocationFragment : Fragment(R.layout.contact_diary_add_loca } } - private val deleteLocationConfirmationDialog by lazy { - DialogHelper.DialogInstance( - requireActivity(), - R.string.contact_diary_delete_location_title, - R.string.contact_diary_delete_location_message, - R.string.contact_diary_delete_button_positive, - R.string.contact_diary_delete_button_negative, - positiveButtonFunction = { - navArgs.selectedLocation?.let { - viewModel.deleteLocation(it) - } - }, - isDeleteDialog = true - ) + private fun deleteLocationConfirmationDialog() = displayDialog { + title(R.string.contact_diary_delete_location_title) + message(R.string.contact_diary_delete_location_message) + positiveButton(R.string.contact_diary_delete_location_message) { + navArgs.selectedLocation?.let { + viewModel.deleteLocation(it) + } + } + negativeButton(R.string.contact_diary_delete_button_negative) + setDeleteDialog(true) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonFragment.kt index 3f33b75be37..2d5e2b5e2a4 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonFragment.kt @@ -11,7 +11,7 @@ import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.util.focusAndShowKeyboard import de.rki.coronawarnapp.contactdiary.util.hideKeyboard import de.rki.coronawarnapp.databinding.ContactDiaryAddPersonFragmentBinding -import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.setTextOnTextInput import de.rki.coronawarnapp.util.ui.observe2 @@ -56,9 +56,7 @@ class ContactDiaryAddPersonFragment : personPhoneNumberInput.setTextOnTextInput(person.phoneNumber, endIconVisible = false) personEmailInput.setTextOnTextInput(person.emailAddress, endIconVisible = false) personDeleteButton.visibility = View.VISIBLE - personDeleteButton.setOnClickListener { - DialogHelper.showDialog(deletePersonConfirmationDialog) - } + personDeleteButton.setOnClickListener { deletePersonConfirmationDialog() } personSaveButton.setOnClickListener { viewModel.updatePerson( person, @@ -111,19 +109,15 @@ class ContactDiaryAddPersonFragment : } } - private val deletePersonConfirmationDialog by lazy { - DialogHelper.DialogInstance( - requireActivity(), - R.string.contact_diary_delete_person_title, - R.string.contact_diary_delete_person_message, - R.string.contact_diary_delete_button_positive, - R.string.contact_diary_delete_button_negative, - positiveButtonFunction = { - navArgs.selectedPerson?.let { - viewModel.deletePerson(it) - } - }, - isDeleteDialog = true - ) + private fun deletePersonConfirmationDialog() = displayDialog { + title(R.string.contact_diary_delete_person_title) + message(R.string.contact_diary_delete_person_message) + positiveButton(R.string.contact_diary_delete_button_positive) { + navArgs.selectedPerson?.let { + viewModel.deletePerson(it) + } + } + negativeButton(R.string.contact_diary_delete_button_negative) + setDeleteDialog(true) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/pdf/ui/exportAll/DccExportAllOverviewFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/pdf/ui/exportAll/DccExportAllOverviewFragment.kt index bc78530cc9a..acf0133e453 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/pdf/ui/exportAll/DccExportAllOverviewFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/pdf/ui/exportAll/DccExportAllOverviewFragment.kt @@ -93,19 +93,21 @@ class DccExportAllOverviewFragment : Fragment(R.layout.fragment_dcc_export_all_o } } - private fun showErrorDialog() = displayDialog(onDismissAction = { navigateToPersonOverview() }) { - setTitle(R.string.export_all_error_title) - setMessage(R.string.export_all_error_message) - setNeutralButton(R.string.export_all_error_faq) { _, _ -> + private fun showErrorDialog() = displayDialog { + title(R.string.export_all_error_title) + message(R.string.export_all_error_message) + neutralButton(R.string.export_all_error_faq) { openUrl(R.string.certificate_export_all_error_dialog_faq_link) } - setPositiveButton(android.R.string.ok) { _, _ -> popBackStack() } + positiveButton(android.R.string.ok) { popBackStack() } + dismissAction { navigateToPersonOverview() } } - private fun showEmptyDialog() = displayDialog(onDismissAction = { navigateToPersonOverview() }) { - setTitle(R.string.export_all_no_pages_title) - setMessage(R.string.export_all_no_pages_message) - setPositiveButton(android.R.string.ok) { _, _ -> } + private fun showEmptyDialog() = displayDialog { + title(R.string.export_all_no_pages_title) + message(R.string.export_all_no_pages_message) + positiveButton(android.R.string.ok) + dismissAction { navigateToPersonOverview() } } private fun navigateToPersonOverview() = runCatching { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/pdf/ui/poster/CertificatePosterFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/pdf/ui/poster/CertificatePosterFragment.kt index 8d288f5827a..253d1d6113e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/pdf/ui/poster/CertificatePosterFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/pdf/ui/poster/CertificatePosterFragment.kt @@ -8,7 +8,6 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.navArgs import com.google.android.material.transition.MaterialSharedAxis import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.covidcertificate.pdf.ui.poster.CertificatePosterViewModel.UiState.Done import de.rki.coronawarnapp.covidcertificate.pdf.ui.poster.CertificatePosterViewModel.UiState.PDF import de.rki.coronawarnapp.covidcertificate.pdf.ui.poster.CertificatePosterViewModel.UiState.PrintResult @@ -73,7 +72,7 @@ class CertificatePosterFragment : Fragment(R.layout.certificate_poster_fragment) viewModel.error.observe2(this) { binding.progressLayout.isVisible = false - displayDialog(dialog = it.toErrorDialogBuilder(requireContext())) + displayDialog { setError(it) } } viewModel.uiState.observe2(this) { state -> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/details/PersonDetailsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/details/PersonDetailsFragment.kt index 3834fd1bc08..584e7e8a6b2 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/details/PersonDetailsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/details/PersonDetailsFragment.kt @@ -15,7 +15,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.appbar.AppBarLayout import com.google.android.material.transition.MaterialContainerTransform import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.covidcertificate.common.certificate.CwaCovidCertificate import de.rki.coronawarnapp.covidcertificate.validation.core.common.exception.DccValidationException import de.rki.coronawarnapp.covidcertificate.validation.ui.common.dccValidationNoInternetDialog @@ -144,7 +143,7 @@ class PersonDetailsFragment : Fragment(R.layout.person_details_fragment), AutoIn if (error is DccValidationException && error.errorCode == DccValidationException.ErrorCode.NO_NETWORK) { dccValidationNoInternetDialog() } else { - displayDialog(dialog = error.toErrorDialogBuilder(requireContext())) + displayDialog { setError(error) } } } @@ -173,16 +172,15 @@ class PersonDetailsFragment : Fragment(R.layout.person_details_fragment), AutoIn } private fun onDeleteCertificateDialog(certificate: CwaCovidCertificate, position: Int) = - displayDialog( - isDeleteDialog = true, - onDismissAction = { personDetailsAdapter.notifyItemChanged(position) } - ) { - setTitle(R.string.recycle_bin_recycle_certificate_dialog_title) - setMessage(R.string.recycle_bin_recycle_certificate_dialog_message) - setPositiveButton(R.string.recycle_bin_recycle_certificate_dialog_positive_button) { _, _ -> + displayDialog { + title(R.string.recycle_bin_recycle_certificate_dialog_title) + message(R.string.recycle_bin_recycle_certificate_dialog_message) + positiveButton(R.string.recycle_bin_recycle_certificate_dialog_positive_button) { viewModel.recycleCertificate(certificate) } - setNegativeButton(R.string.family_tests_list_deletion_alert_cancel_button) { _, _ -> } + negativeButton(R.string.family_tests_list_deletion_alert_cancel_button) + dismissAction { personDetailsAdapter.notifyItemChanged(position) } + setDeleteDialog(true) } private val globalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewFragment.kt index 322a8c93f5f..da93f29b8a8 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/person/ui/overview/PersonOverviewFragment.kt @@ -12,7 +12,6 @@ import androidx.recyclerview.widget.DefaultItemAnimator import com.google.android.material.transition.Hold import com.google.android.material.transition.MaterialSharedAxis import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.covidcertificate.person.ui.admission.AdmissionScenariosSharedViewModel import de.rki.coronawarnapp.covidcertificate.person.ui.details.PersonDetailsFragmentArgs import de.rki.coronawarnapp.covidcertificate.person.ui.overview.items.AdmissionTileProvider @@ -78,30 +77,31 @@ class PersonOverviewFragment : Fragment(R.layout.person_overview_fragment), Auto ) } - is ShowDeleteDialog -> displayDialog(cancelable = false, isDeleteDialog = true) { - setTitle(R.string.test_certificate_delete_dialog_title) - setMessage(R.string.test_certificate_delete_dialog_body) - setPositiveButton(R.string.test_certificate_delete_dialog_confirm_button) { _, _ -> + is ShowDeleteDialog -> displayDialog { + title(R.string.test_certificate_delete_dialog_title) + message(R.string.test_certificate_delete_dialog_body) + positiveButton(R.string.test_certificate_delete_dialog_confirm_button) { viewModel.deleteTestCertificate(event.containerId) } - setNegativeButton(R.string.test_certificate_delete_dialog_cancel_button) { _, _ -> } + negativeButton(R.string.test_certificate_delete_dialog_cancel_button) + setCancelable(false) + setDeleteDialog(true) } - is ShowRefreshErrorDialog -> displayDialog( - cancelable = false, - dialog = event.error.toErrorDialogBuilder(requireContext()) - ) { - setTitle(R.string.test_certificate_refresh_dialog_title) + is ShowRefreshErrorDialog -> displayDialog { + title(R.string.test_certificate_refresh_dialog_title) if (event.showTestCertificateFaq) - setNeutralButton(R.string.test_certificate_error_invalid_labid_faq) { _, _ -> + neutralButton(R.string.test_certificate_error_invalid_labid_faq) { openUrl(getString(R.string.test_certificate_error_invalid_labid_faq_link)) } + setCancelable(false) + setError(event.error) } is ShowMigrationInfoDialog -> displayDialog { - setTitle(R.string.certificate_migration_dialog_title) - setMessage(R.string.certificate_migration_dialog_message) - setPositiveButton(R.string.errors_generic_button_positive) { _, _ -> } + title(R.string.certificate_migration_dialog_title) + message(R.string.certificate_migration_dialog_message) + positiveButton(R.string.errors_generic_button_positive) } OpenCovPassInfo -> findNavController().navigate( @@ -121,7 +121,7 @@ class PersonOverviewFragment : Fragment(R.layout.person_overview_fragment), Auto ) } - is ShowAdmissionScenarioError -> displayDialog(dialog = event.error.toErrorDialogBuilder(requireContext())) + is ShowAdmissionScenarioError -> displayDialog { setError(event.error) } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/recovery/ui/details/RecoveryCertificateDetailsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/recovery/ui/details/RecoveryCertificateDetailsFragment.kt index b55b7209158..53e9433b095 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/recovery/ui/details/RecoveryCertificateDetailsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/recovery/ui/details/RecoveryCertificateDetailsFragment.kt @@ -14,7 +14,6 @@ import androidx.navigation.fragment.navArgs import coil.loadAny import com.google.android.material.appbar.AppBarLayout import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.covidcertificate.common.certificate.getValidQrCode import de.rki.coronawarnapp.covidcertificate.common.repository.RecoveryCertificateContainerId import de.rki.coronawarnapp.covidcertificate.recovery.core.RecoveryCertificate @@ -144,7 +143,7 @@ class RecoveryCertificateDetailsFragment : Fragment(R.layout.fragment_recovery_c if (error is DccValidationException && error.errorCode == DccValidationException.ErrorCode.NO_NETWORK) { dccValidationNoInternetDialog() } else { - displayDialog(dialog = error.toErrorDialogBuilder(requireContext())) + displayDialog { setError(error) } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/ui/details/TestCertificateDetailsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/ui/details/TestCertificateDetailsFragment.kt index 850b7346442..d5e220e7850 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/ui/details/TestCertificateDetailsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/ui/details/TestCertificateDetailsFragment.kt @@ -15,7 +15,6 @@ import androidx.navigation.fragment.navArgs import coil.loadAny import com.google.android.material.appbar.AppBarLayout import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.covidcertificate.common.certificate.getValidQrCode import de.rki.coronawarnapp.covidcertificate.common.repository.TestCertificateContainerId import de.rki.coronawarnapp.covidcertificate.test.core.TestCertificate @@ -177,7 +176,7 @@ class TestCertificateDetailsFragment : Fragment(R.layout.fragment_test_certifica if (error is DccValidationException && error.errorCode == DccValidationException.ErrorCode.NO_NETWORK) { dccValidationNoInternetDialog() } else { - displayDialog(dialog = error.toErrorDialogBuilder(requireContext())) + displayDialog { setError(error) } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/ui/onboarding/CovidCertificateOnboardingErrorDialogs.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/ui/onboarding/CovidCertificateOnboardingErrorDialogs.kt new file mode 100644 index 00000000000..12c7584e310 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/ui/onboarding/CovidCertificateOnboardingErrorDialogs.kt @@ -0,0 +1,31 @@ +package de.rki.coronawarnapp.covidcertificate.ui.onboarding + +import androidx.fragment.app.Fragment +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.covidcertificate.common.exception.InvalidHealthCertificateException +import de.rki.coronawarnapp.ui.dialog.displayDialog +import de.rki.coronawarnapp.util.ExternalActionHelper.openUrl + +fun Fragment.showCovidCertificateOnboardingErrorDialog(error: Throwable) = displayDialog { + if (error is InvalidHealthCertificateException) { + when { + error.isCertificateInvalid -> + neutralButton(R.string.error_button_dcc_faq) { + openUrl(R.string.error_button_dcc_faq_link) + } + + error.isSignatureInvalid -> { + title(R.string.dcc_signature_validation_dialog_title) + neutralButton(R.string.dcc_signature_validation_dialog_faq_button) { + openUrl(R.string.dcc_signature_validation_dialog_faq_link) + } + } + error.isAlreadyRegistered -> { + neutralButton(R.string.error_button_dcc_faq) { + openUrl(R.string.error_dcc_already_registered_faq_link) + } + } + } + } + setError(error) +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/ui/onboarding/CovidCertificateOnboardingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/ui/onboarding/CovidCertificateOnboardingFragment.kt index 6323a8880e7..f269c478ae5 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/ui/onboarding/CovidCertificateOnboardingFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/ui/onboarding/CovidCertificateOnboardingFragment.kt @@ -20,8 +20,6 @@ import de.rki.coronawarnapp.covidcertificate.test.ui.details.TestCertificateDeta import de.rki.coronawarnapp.covidcertificate.vaccination.ui.details.VaccinationDetailsFragment import de.rki.coronawarnapp.databinding.CovidCertificateOnboardingFragmentBinding import de.rki.coronawarnapp.qrcode.ui.QrcodeSharedViewModel -import de.rki.coronawarnapp.qrcode.ui.toQrCodeErrorDialogBuilder -import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.ContextExtensions.getDrawableCompat import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.popBackStack @@ -95,7 +93,7 @@ class CovidCertificateOnboardingFragment : Fragment(R.layout.covid_certificate_o findNavController().navigate(uri, navOption) } is CovidCertificateOnboardingViewModel.Event.Error -> - displayDialog(dialog = event.throwable.toQrCodeErrorDialogBuilder(requireContext())) + showCovidCertificateOnboardingErrorDialog(event.throwable) } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/details/VaccinationDetailsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/details/VaccinationDetailsFragment.kt index 850ecccc7c0..63d2d3f7c5b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/details/VaccinationDetailsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/details/VaccinationDetailsFragment.kt @@ -14,7 +14,6 @@ import androidx.navigation.fragment.navArgs import coil.loadAny import com.google.android.material.appbar.AppBarLayout import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.covidcertificate.common.certificate.getValidQrCode import de.rki.coronawarnapp.covidcertificate.common.repository.VaccinationCertificateContainerId import de.rki.coronawarnapp.covidcertificate.person.ui.overview.PersonColorShade @@ -117,7 +116,7 @@ class VaccinationDetailsFragment : Fragment(R.layout.fragment_vaccination_detail if (it is DccValidationException && it.errorCode == DccValidationException.ErrorCode.NO_NETWORK) { dccValidationNoInternetDialog() } else { - displayDialog(dialog = it.toErrorDialogBuilder(requireContext())) + displayDialog { setError(it) } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/validation/ui/common/DccValidationNoInternetErrorDialog.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/validation/ui/common/DccValidationNoInternetErrorDialog.kt index defdc1ab24c..21faa191807 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/validation/ui/common/DccValidationNoInternetErrorDialog.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/validation/ui/common/DccValidationNoInternetErrorDialog.kt @@ -5,7 +5,7 @@ import de.rki.coronawarnapp.R import de.rki.coronawarnapp.ui.dialog.displayDialog fun Fragment.dccValidationNoInternetDialog() = displayDialog { - setTitle(R.string.validation_start_no_internet_dialog_title) - setMessage(R.string.validation_start_no_internet_dialog_msg) - setPositiveButton(R.string.validation_start_no_internet_dialog_positive_button) { _, _ -> } + title(R.string.validation_start_no_internet_dialog_title) + message(R.string.validation_start_no_internet_dialog_msg) + positiveButton(R.string.validation_start_no_internet_dialog_positive_button) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/validation/ui/validationstart/ValidationStartFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/validation/ui/validationstart/ValidationStartFragment.kt index cb4dd779321..828f5cdf51c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/validation/ui/validationstart/ValidationStartFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/validation/ui/validationstart/ValidationStartFragment.kt @@ -14,7 +14,6 @@ import com.google.android.material.datepicker.MaterialDatePicker import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.TimeFormat import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.covidcertificate.validation.core.DccValidation import de.rki.coronawarnapp.covidcertificate.validation.core.country.DccCountry import de.rki.coronawarnapp.covidcertificate.validation.ui.common.dccValidationNoInternetDialog @@ -107,7 +106,7 @@ class ValidationStartFragment : Fragment(R.layout.validation_start_fragment), Au } is ShowErrorDialog -> { startValidationCheck.isLoading = false - displayDialog(dialog = event.error.toErrorDialogBuilder(requireContext())) + displayDialog { setError(event.error) } } is ShowNoInternetDialog -> { startValidationCheck.isLoading = false diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/consent/SurveyConsentBlockingProgressDialogFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/consent/SurveyConsentBlockingProgressDialogFragment.kt deleted file mode 100644 index c55a3335340..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/consent/SurveyConsentBlockingProgressDialogFragment.kt +++ /dev/null @@ -1,22 +0,0 @@ -package de.rki.coronawarnapp.datadonation.survey.consent - -import android.app.Dialog -import android.os.Bundle -import androidx.fragment.app.DialogFragment -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import de.rki.coronawarnapp.R - -class SurveyConsentBlockingProgressDialogFragment : DialogFragment() { - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - isCancelable = false - return MaterialAlertDialogBuilder(requireContext()) - .setView(R.layout.survey_consent_blocking_progress_dialog) - .setCancelable(false) - .create() - } - - companion object { - val TAG = SurveyConsentBlockingProgressDialogFragment::class.java.simpleName - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/consent/SurveyConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/consent/SurveyConsentFragment.kt index 048be0a8434..3ee3099253b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/consent/SurveyConsentFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/survey/consent/SurveyConsentFragment.kt @@ -2,13 +2,13 @@ package de.rki.coronawarnapp.datadonation.survey.consent import android.os.Bundle import android.view.View -import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.SurveyConsentFragmentBinding -import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.ui.dialog.CwaDialogFragment +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.ExternalActionHelper.openUrl import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.observe2 @@ -60,14 +60,11 @@ class SurveyConsentFragment : Fragment(R.layout.survey_consent_fragment), AutoIn } vm.showLoadingIndicator.observe2(this) { loading -> - if (loading) { - SurveyConsentBlockingProgressDialogFragment().show( - childFragmentManager, - SurveyConsentBlockingProgressDialogFragment.TAG - ) - } else { - childFragmentManager.findFragmentByTag(SurveyConsentBlockingProgressDialogFragment.TAG) - ?.let { (it as DialogFragment).dismiss() } + if (loading) showSurveyProgressDialog() + else { + val tag = SurveyConsentFragment::class.java.simpleName + CwaDialogFragment.TAG + childFragmentManager.findFragmentByTag(tag) + ?.let { (it as CwaDialogFragment).dismiss() } } } @@ -76,16 +73,15 @@ class SurveyConsentFragment : Fragment(R.layout.survey_consent_fragment), AutoIn } } - private fun showErrorDialog(message: String) { - context?.let { - val dialog = DialogHelper.DialogInstance( - context = it, - title = R.string.datadonation_details_survey_consent_error_dialog_title, - message = message, - positiveButton = R.string.datadonation_details_survey_consent_error_dialog_pos_button, - cancelable = false - ) - DialogHelper.showDialog(dialog) - } + private fun showSurveyProgressDialog() = displayDialog { + setCancelable(false) + setView(R.layout.survey_consent_blocking_progress_dialog) + } + + private fun showErrorDialog(message: String) = displayDialog { + title(R.string.datadonation_details_survey_consent_error_dialog_title) + message(message) + positiveButton(R.string.datadonation_details_survey_consent_error_dialog_pos_button) + setCancelable(false) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccreissuance/ui/consent/DccReissuanceConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccreissuance/ui/consent/DccReissuanceConsentFragment.kt index c3baf6e710a..7bd086299f0 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccreissuance/ui/consent/DccReissuanceConsentFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccreissuance/ui/consent/DccReissuanceConsentFragment.kt @@ -8,8 +8,8 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.google.android.material.transition.MaterialSharedAxis import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentDccReissuanceConsentBinding +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.diffutil.update import de.rki.coronawarnapp.util.ui.observe2 @@ -86,7 +86,7 @@ class DccReissuanceConsentFragment : Fragment(R.layout.fragment_dcc_reissuance_c when (event) { is DccReissuanceConsentViewModel.ReissuanceError -> { agreeButton.isLoading = false - event.error.toErrorDialogBuilder(requireContext()).show() + displayDialog { setError(event.error) } } DccReissuanceConsentViewModel.ReissuanceInProgress -> agreeButton.isLoading = true DccReissuanceConsentViewModel.ReissuanceSuccess -> { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/certificateselection/DccTicketingCertificateSelectionFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/certificateselection/DccTicketingCertificateSelectionFragment.kt index 2629b184977..c81db205d98 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/certificateselection/DccTicketingCertificateSelectionFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/certificateselection/DccTicketingCertificateSelectionFragment.kt @@ -8,8 +8,7 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.navGraphViewModels import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentDccTicketingCertificateSelectionBinding -import de.rki.coronawarnapp.dccticketing.ui.dialog.DccTicketingDialogType -import de.rki.coronawarnapp.dccticketing.ui.dialog.show +import de.rki.coronawarnapp.dccticketing.ui.dialog.dccTicketingConfirmCancellationDialog import de.rki.coronawarnapp.dccticketing.ui.shared.DccTicketingSharedViewModel import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.decorations.TopBottomPaddingDecorator @@ -56,16 +55,9 @@ class DccTicketingCertificateSelectionFragment : activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner) { viewModel.onUserCancel() } } - private fun showCloseDialog() { - DccTicketingDialogType.ConfirmCancellation.show( - fragment = this, - negativeButtonAction = { viewModel.closeScreen() } - ) - } - private fun navigate(event: DccTicketingCertificateSelectionEvents) { when (event) { - ShowCancelConfirmationDialog -> showCloseDialog() + ShowCancelConfirmationDialog -> dccTicketingConfirmCancellationDialog { viewModel.closeScreen() } CloseSelectionScreen -> popBackStack() is NavigateToConsentTwoFragment -> findNavController().navigate( DccTicketingCertificateSelectionFragmentDirections diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/consent/one/DccTicketingConsentOneFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/consent/one/DccTicketingConsentOneFragment.kt index d785f2e362f..6bb39f2e360 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/consent/one/DccTicketingConsentOneFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/consent/one/DccTicketingConsentOneFragment.kt @@ -12,13 +12,12 @@ import androidx.navigation.navGraphViewModels import com.google.android.material.transition.MaterialSharedAxis import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentDccTicketingConsentOneBinding -import de.rki.coronawarnapp.dccticketing.ui.dialog.DccTicketingDialogType -import de.rki.coronawarnapp.dccticketing.ui.dialog.show +import de.rki.coronawarnapp.dccticketing.ui.dialog.dccTicketingConfirmCancellationDialog +import de.rki.coronawarnapp.dccticketing.ui.dialog.dccTicketingErrorDialog import de.rki.coronawarnapp.dccticketing.ui.shared.DccTicketingSharedViewModel import de.rki.coronawarnapp.qrcode.ui.QrcodeSharedViewModel import de.rki.coronawarnapp.ui.view.onOffsetChange import de.rki.coronawarnapp.util.di.AutoInject -import de.rki.coronawarnapp.util.ui.LazyString import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.popBackStack import de.rki.coronawarnapp.util.ui.viewBinding @@ -102,25 +101,11 @@ class DccTicketingConsentOneFragment : Fragment(R.layout.fragment_dcc_ticketing_ ) NavigateToPrivacyInformation -> findNavController().navigate(R.id.informationPrivacyFragment) - ShowCancelConfirmationDialog -> showCloseDialog() - is ShowErrorDialog -> showErrorDialog(lazyErrorMessage = event.lazyErrorMessage) + ShowCancelConfirmationDialog -> dccTicketingConfirmCancellationDialog { viewModel.goBack() } + is ShowErrorDialog -> dccTicketingErrorDialog(event.lazyErrorMessage.get(requireContext())) } } - private fun showCloseDialog() { - DccTicketingDialogType.ConfirmCancellation.show( - fragment = this, - negativeButtonAction = { viewModel.goBack() } - ) - } - - private fun showErrorDialog(lazyErrorMessage: LazyString) { - val msg = lazyErrorMessage.get(requireContext()) - DccTicketingDialogType.ErrorDialog(msg = msg).show( - fragment = this - ) - } - companion object { fun uri( transactionContextIdentifier: String diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/consent/two/DccTicketingConsentTwoFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/consent/two/DccTicketingConsentTwoFragment.kt index 35c5f068af7..40e9d1ffe16 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/consent/two/DccTicketingConsentTwoFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/consent/two/DccTicketingConsentTwoFragment.kt @@ -1,22 +1,21 @@ package de.rki.coronawarnapp.dccticketing.ui.consent.two import android.os.Bundle -import androidx.fragment.app.Fragment import android.view.View import androidx.activity.addCallback +import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import androidx.navigation.navGraphViewModels import com.google.android.material.transition.MaterialSharedAxis import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentDccTicketingConsentTwoBinding -import de.rki.coronawarnapp.dccticketing.ui.dialog.DccTicketingDialogType -import de.rki.coronawarnapp.dccticketing.ui.dialog.show +import de.rki.coronawarnapp.dccticketing.ui.dialog.dccTicketingConfirmCancellationDialog +import de.rki.coronawarnapp.dccticketing.ui.dialog.dccTicketingErrorDialog import de.rki.coronawarnapp.dccticketing.ui.shared.DccTicketingSharedViewModel import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.decorations.TopBottomPaddingDecorator import de.rki.coronawarnapp.util.lists.diffutil.update -import de.rki.coronawarnapp.util.ui.LazyString import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.popBackStack import de.rki.coronawarnapp.util.ui.viewBinding @@ -101,22 +100,8 @@ class DccTicketingConsentTwoFragment : Fragment(R.layout.fragment_dcc_ticketing_ ) NavigateToPrivacyInformation -> findNavController().navigate(R.id.informationPrivacyFragment) - ShowCancelConfirmationDialog -> showCloseDialog() - is ShowErrorDialog -> showErrorDialog(lazyErrorMessage = event.lazyErrorMessage) + ShowCancelConfirmationDialog -> dccTicketingConfirmCancellationDialog { viewModel.cancel() } + is ShowErrorDialog -> dccTicketingErrorDialog(event.lazyErrorMessage.get(requireContext())) } } - - private fun showCloseDialog() { - DccTicketingDialogType.ConfirmCancellation.show( - fragment = this, - negativeButtonAction = { viewModel.cancel() } - ) - } - - private fun showErrorDialog(lazyErrorMessage: LazyString) { - val msg = lazyErrorMessage.get(requireContext()) - DccTicketingDialogType.ErrorDialog(msg = msg).show( - fragment = this - ) - } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogFragment.kt deleted file mode 100644 index 45760ffa0f6..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogFragment.kt +++ /dev/null @@ -1,79 +0,0 @@ -package de.rki.coronawarnapp.dccticketing.ui.dialog - -import android.app.Dialog -import android.content.DialogInterface -import android.os.Bundle -import android.os.Parcelable -import androidx.annotation.StringRes -import androidx.core.os.bundleOf -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.setFragmentResult -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.parcelize.Parcelize -import timber.log.Timber -import java.lang.IllegalArgumentException - -class DccTicketingDialogFragment : DialogFragment() { - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val config = requireArguments().getParcelable(PARAM_DIALOG_CONFIG) - requireNotNull(config) { "Dialog config is null" } - - return config.run { - MaterialAlertDialogBuilder(requireContext()).apply { - when { - titleRes != null -> setTitle(titleRes) - title != null -> setTitle(title) - else -> throw IllegalArgumentException("titleRes or title must be set!") - } - - when { - msgRes != null -> setMessage(msgRes) - msg != null -> setMessage(msg) - else -> throw IllegalArgumentException("msgRes or msg must be set!") - } - - setPositiveButton(positiveButtonRes) { _, _ -> setAction(Action.PositiveButtonClicked) } - - negativeButtonRes?.let { setNegativeButton(it) { _, _ -> setAction(Action.NegativeButtonClicked) } } - }.create() - } - } - - private fun setAction(action: Action) { - Timber.d("setAction(action=%s)", action) - setFragmentResult(REQUEST_KEY, bundleOf(PARAM_DIALOG_ACTION to action)) - } - - override fun onDismiss(dialog: DialogInterface) { - setAction(Action.Dismissed) - super.onDismiss(dialog) - } - - enum class Action { - PositiveButtonClicked, - NegativeButtonClicked, - Dismissed - } - - @Parcelize - data class Config( - @StringRes val titleRes: Int? = null, - val title: String? = null, - @StringRes val msgRes: Int? = null, - val msg: String? = null, - @StringRes val positiveButtonRes: Int, - @StringRes val negativeButtonRes: Int? = null, - ) : Parcelable - - companion object { - val TAG: String = DccTicketingDialogFragment::class.java.simpleName - val REQUEST_KEY = "${TAG}_REQUEST_KEY" - val PARAM_DIALOG_ACTION = "${TAG}_PARAM_DIALOG_ACTION" - private val PARAM_DIALOG_CONFIG = "${TAG}_PARAM_DIALOG_CONFIG" - - fun newInstance(dialogConfig: Config) = DccTicketingDialogFragment().apply { - arguments = bundleOf(PARAM_DIALOG_CONFIG to dialogConfig) - } - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogHelper.kt deleted file mode 100644 index 59356434969..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogHelper.kt +++ /dev/null @@ -1,37 +0,0 @@ -package de.rki.coronawarnapp.dccticketing.ui.dialog - -import androidx.fragment.app.Fragment -import de.rki.coronawarnapp.reyclebin.ui.dialog.DialogAction - -fun DccTicketingDialogType.show( - fragment: Fragment, - positiveButtonAction: DialogAction = { }, - negativeButtonAction: DialogAction = { }, - dismissAction: DialogAction = { } -) = fragment.showDccTicketingDialog(config, positiveButtonAction, negativeButtonAction, dismissAction) - -private fun Fragment.showDccTicketingDialog( - dialogConfig: DccTicketingDialogFragment.Config, - positiveButtonAction: DialogAction, - negativeButtonAction: DialogAction, - dismissAction: DialogAction -) { - val dialog = DccTicketingDialogFragment.newInstance(dialogConfig) - childFragmentManager.also { - it.setFragmentResultListener(DccTicketingDialogFragment.REQUEST_KEY, viewLifecycleOwner) { _, bundle -> - val action = bundle.getSerializable( - DccTicketingDialogFragment.PARAM_DIALOG_ACTION - ) as? DccTicketingDialogFragment.Action - - requireNotNull(action) { "Action is null" } - - when (action) { - DccTicketingDialogFragment.Action.PositiveButtonClicked -> positiveButtonAction() - DccTicketingDialogFragment.Action.NegativeButtonClicked -> negativeButtonAction() - DccTicketingDialogFragment.Action.Dismissed -> dismissAction() - } - } - - dialog.show(it, DccTicketingDialogFragment.TAG) - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogType.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogType.kt deleted file mode 100644 index 19d2da07088..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogType.kt +++ /dev/null @@ -1,38 +0,0 @@ -package de.rki.coronawarnapp.dccticketing.ui.dialog - -import de.rki.coronawarnapp.R - -sealed class DccTicketingDialogType { - abstract val config: DccTicketingDialogFragment.Config - - object ConfirmCancellation : DccTicketingDialogType() { - override val config: DccTicketingDialogFragment.Config - get() = DccTicketingDialogFragment.Config( - titleRes = R.string.dcc_ticketing_consent_one_cancel_dialog_title, - msgRes = R.string.dcc_ticketing_consent_one_cancel_dialog_body, - positiveButtonRes = R.string.dcc_ticketing_consent_one_cancel_dialog_continue_btn, - negativeButtonRes = R.string.dcc_ticketing_consent_one_cancel_dialog_cancel_btn - ) - } - - data class ErrorDialog( - private val title: String? = null, - private val negativeButtonRes: Int? = null, - private val msg: String - ) : DccTicketingDialogType() { - override val config: DccTicketingDialogFragment.Config - get() { - val config = DccTicketingDialogFragment.Config( - title = title, - msg = msg, - negativeButtonRes = negativeButtonRes, - positiveButtonRes = R.string.errors_generic_button_positive - ) - - return when (config.title == null) { - true -> config.copy(titleRes = R.string.errors_generic_headline_short) - false -> config - } - } - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogs.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogs.kt new file mode 100644 index 00000000000..15bca2b94bd --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/dccticketing/ui/dialog/DccTicketingDialogs.kt @@ -0,0 +1,18 @@ +package de.rki.coronawarnapp.dccticketing.ui.dialog + +import androidx.fragment.app.Fragment +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.ui.dialog.displayDialog + +fun Fragment.dccTicketingConfirmCancellationDialog(negativeButtonAction: () -> Unit) = displayDialog { + title(R.string.dcc_ticketing_consent_one_cancel_dialog_title) + message(R.string.dcc_ticketing_consent_one_cancel_dialog_body) + positiveButton(R.string.dcc_ticketing_consent_one_cancel_dialog_continue_btn) + negativeButton(R.string.dcc_ticketing_consent_one_cancel_dialog_cancel_btn) { negativeButtonAction() } +} + +fun Fragment.dccTicketingErrorDialog(message: String) = displayDialog { + title(R.string.errors_generic_headline_short) + message(message) + positiveButton(R.string.errors_generic_button_positive) +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/reporting/ErrorReportReceiver.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/reporting/ErrorReportReceiver.kt index 512eca4e699..eb6f6fa8301 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/reporting/ErrorReportReceiver.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/reporting/ErrorReportReceiver.kt @@ -4,10 +4,11 @@ import android.app.Activity import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import androidx.appcompat.app.AppCompatActivity import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.R import de.rki.coronawarnapp.exception.ExceptionCategory -import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.ui.dialog.displayDialog import timber.log.Timber class ErrorReportReceiver(private val activity: Activity) : BroadcastReceiver() { @@ -62,26 +63,17 @@ class ErrorReportReceiver(private val activity: Activity) : BroadcastReceiver() Timber.v("Not displaying error dialog, not in foreground.") return } - - val dialogInstance = DialogHelper.DialogInstance( - context = activity, - title = dialogTitle, - message = message, - positiveButton = confirm, - negativeButton = details, - cancelable = null, - positiveButtonFunction = {}, - negativeButtonFunction = { - val stackTraceDialog = DialogHelper.DialogInstance( - activity, - title, - "$detailsTitle:\n$stack", - confirm - ) - DialogHelper.showDialog(stackTraceDialog.copy(isTextSelectable = true)) - Unit + (activity as AppCompatActivity).displayDialog { + title(dialogTitle) + message(message) + positiveButton(confirm) + negativeButton(details) { + activity.displayDialog { + title(title) + message("$detailsTitle:\n$stack") + positiveButton(confirm) + } } - ) - DialogHelper.showDialog(dialogInstance) + } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/familytest/ui/consent/FamilyTestConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/familytest/ui/consent/FamilyTestConsentFragment.kt index 2ea0dda6bdd..ec2c0b0cfd7 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/familytest/ui/consent/FamilyTestConsentFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/familytest/ui/consent/FamilyTestConsentFragment.kt @@ -91,9 +91,7 @@ class FamilyTestConsentFragment : Fragment(R.layout.fragment_family_test_consent TestRegistrationStateProcessor.State.Idle, TestRegistrationStateProcessor.State.Working -> Unit is TestRegistrationStateProcessor.State.Error -> { - val dialog = state.getDialogBuilder(requireContext()) - dialog.setPositiveButton(android.R.string.ok) { _, _ -> popBackStack() } - dialog.show() + state.showExceptionDialog(this) { popBackStack() } } is TestRegistrationStateProcessor.State.TestRegistered -> findNavController().navigate( NavGraphDirections.actionSubmissionTestResultPendingFragment( diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/familytest/ui/testlist/FamilyTestListFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/familytest/ui/testlist/FamilyTestListFragment.kt index ea6d771f675..ba352966174 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/familytest/ui/testlist/FamilyTestListFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/familytest/ui/testlist/FamilyTestListFragment.kt @@ -7,13 +7,12 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentFamilyTestListBinding import de.rki.coronawarnapp.familytest.core.model.CoronaTest import de.rki.coronawarnapp.familytest.core.model.FamilyCoronaTest import de.rki.coronawarnapp.familytest.ui.testlist.items.FamilyTestListItem +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.list.setupSwipe import de.rki.coronawarnapp.util.lists.decorations.TopBottomPaddingDecorator @@ -40,7 +39,7 @@ class FamilyTestListFragment : Fragment(R.layout.fragment_family_test_list), Aut binding.toolbar.setNavigationOnClickListener { viewModel.onBackPressed() } viewModel.familyTests.observe2(this) { tests -> updateViews(tests) } viewModel.events.observe2(this) { it?.let { onNavigationEvent(it) } } - viewModel.error.observe2(this) { it.toErrorDialogBuilder(requireContext()).show() } + viewModel.error.observe2(this) { displayDialog { setError(it) } } viewModel.refreshComplete.observe2(this) { binding.refreshLayout.isRefreshing = false } } @@ -130,13 +129,14 @@ class FamilyTestListFragment : Fragment(R.layout.fragment_family_test_list), Aut R.string.family_tests_list_deletion_alert_delete_button ) } - MaterialAlertDialogBuilder(requireContext()) - .setTitle(title) - .setMessage(message) - .setPositiveButton(button) { _, _ -> viewModel.onRemoveTestConfirmed(familyCoronaTest) } - .setNegativeButton(R.string.family_tests_list_deletion_alert_cancel_button) { _, _ -> } - .setOnDismissListener { + displayDialog { + title(title) + message(message) + positiveButton(button) { viewModel.onRemoveTestConfirmed(familyCoronaTest) } + negativeButton(R.string.family_tests_list_deletion_alert_cancel_button) + dismissAction { position?.let { familyTestListAdapter.notifyItemChanged(position) } - }.show() + } + } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/profile/ui/qrcode/ProfileQrCodeFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/profile/ui/qrcode/ProfileQrCodeFragment.kt index 92d1435a067..d37c79d9009 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/profile/ui/qrcode/ProfileQrCodeFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/profile/ui/qrcode/ProfileQrCodeFragment.kt @@ -16,8 +16,8 @@ import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.ProfileQrCodeFragmentBinding import de.rki.coronawarnapp.profile.model.Profile import de.rki.coronawarnapp.qrcode.ui.QrCodeScannerFragmentDirections +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.ui.qrcode.fullscreen.QrCodeFullScreenFragmentArgs -import de.rki.coronawarnapp.util.DialogHelper import de.rki.coronawarnapp.util.coil.loadingView import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.joinToSpannable @@ -45,20 +45,6 @@ class ProfileQrCodeFragment : Fragment(R.layout.profile_qr_code_fragment), AutoI } ) - private val deleteRatProfileConfirmationDialog by lazy { - DialogHelper.DialogInstance( - requireActivity(), - R.string.rat_qr_code_profile_dialog_title, - R.string.rat_qr_code_profile_dialog_message, - R.string.rat_qr_code_profile_dialog_positive_button, - R.string.rat_qr_code_profile_dialog_negative_button, - positiveButtonFunction = { - viewModel.deleteProfile() - }, - isDeleteDialog = true - ) - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { setToolbarOverlay() binding.apply { @@ -122,7 +108,13 @@ class ProfileQrCodeFragment : Fragment(R.layout.profile_qr_code_fragment), AutoI } } - private fun confirmDeletionDialog() = DialogHelper.showDialog(deleteRatProfileConfirmationDialog) + private fun confirmDeletionDialog() = displayDialog { + title(R.string.rat_qr_code_profile_dialog_title) + message(R.string.rat_qr_code_profile_dialog_message) + positiveButton(R.string.rat_qr_code_profile_dialog_positive_button) { viewModel.deleteProfile() } + negativeButton(R.string.rat_qr_code_profile_dialog_negative_button) + setDeleteDialog(true) + } private fun bindPersonInfo(profile: Profile) = with(profile) { val name = buildSpannedString { bold { append("$firstName $lastName".trim()) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/qrcode/ui/QrCodeScannerFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/qrcode/ui/QrCodeScannerFragment.kt index 6dd866a69df..6edde5eb311 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/qrcode/ui/QrCodeScannerFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/qrcode/ui/QrCodeScannerFragment.kt @@ -163,29 +163,28 @@ class QrCodeScannerFragment : Fragment(R.layout.fragment_qrcode_scanner), AutoIn } private fun showCameraPermissionDeniedDialog() { - displayDialog(onDismissAction = { popBackStack() }) { - setTitle(R.string.camera_permission_dialog_title) - setMessage(R.string.camera_permission_dialog_message) - setPositiveButton(android.R.string.ok) { _, _ -> leave() } - setNegativeButton(R.string.camera_permission_dialog_settings) { _, _ -> + displayDialog { + title(R.string.camera_permission_dialog_title) + message(R.string.camera_permission_dialog_message) + positiveButton(android.R.string.ok) { leave() } + negativeButton(R.string.camera_permission_dialog_settings) { showsPermissionDialog = false requireContext().openAppDetailsSettings() } + dismissAction { popBackStack() } } showsPermissionDialog = true } private fun showCameraPermissionRationaleDialog() { displayDialog { - setTitle(R.string.camera_permission_rationale_dialog_headline) - setMessage(R.string.camera_permission_rationale_dialog_body) - setPositiveButton(R.string.camera_permission_rationale_dialog_button_positive) { _, _ -> + title(R.string.camera_permission_rationale_dialog_headline) + message(R.string.camera_permission_rationale_dialog_body) + positiveButton(R.string.camera_permission_rationale_dialog_button_positive) { showsPermissionDialog = false requestCameraPermission() } - setNegativeButton(R.string.camera_permission_rationale_dialog_button_negative) { _, _ -> - leave() - } + negativeButton(R.string.camera_permission_rationale_dialog_button_negative) { leave() } } showsPermissionDialog = true } @@ -193,33 +192,24 @@ class QrCodeScannerFragment : Fragment(R.layout.fragment_qrcode_scanner), AutoIn private fun showCheckInQrCodeError(lazyErrorText: LazyString) { val errorText = lazyErrorText.get(requireContext()) displayDialog { - setTitle(R.string.trace_location_attendee_invalid_qr_code_dialog_title) - setMessage(getString(R.string.trace_location_attendee_invalid_qr_code_dialog_message, errorText)) - setPositiveButton(R.string.trace_location_attendee_invalid_qr_code_dialog_positive_button) { _, _ -> - startDecode() - } - setNegativeButton(R.string.trace_location_attendee_invalid_qr_code_dialog_negative_button) { _, _ -> - popBackStack() - } + title(R.string.trace_location_attendee_invalid_qr_code_dialog_title) + message(getString(R.string.trace_location_attendee_invalid_qr_code_dialog_message, errorText)) + positiveButton(R.string.trace_location_attendee_invalid_qr_code_dialog_positive_button) { startDecode() } + negativeButton(R.string.trace_location_attendee_invalid_qr_code_dialog_negative_button) { popBackStack() } } } - private fun showScannerResultErrorDialog(error: Throwable) { - displayDialog( - onDismissAction = { startDecode() }, - dialog = error.toQrCodeErrorDialogBuilder(requireContext()) - ) + private fun showScannerResultErrorDialog(error: Throwable) = displayDialog { + dismissAction { startDecode() } + setError(error) } - private fun showValidationServiceMinVersionDialog(errorMsg: LazyString) { - displayDialog(onDismissAction = { startDecode() }) { - setTitle(R.string.errors_generic_headline_short) - setMessage(errorMsg.get(requireContext())) - setPositiveButton(R.string.errors_generic_button_positive) { _, _ -> startDecode() } - setNegativeButton(R.string.dcc_ticketing_error_min_version_google_play) { _, _ -> - requireContext().openGooglePlay() - } - } + private fun showValidationServiceMinVersionDialog(errorMsg: LazyString) = displayDialog { + title(R.string.errors_generic_headline_short) + message(errorMsg.get(requireContext())) + positiveButton(R.string.errors_generic_button_positive) { startDecode() } + negativeButton(R.string.dcc_ticketing_error_min_version_google_play) { requireContext().openGooglePlay() } + dismissAction { startDecode() } } private fun requestCameraPermission() = requestPermissionLauncher.launch(Manifest.permission.CAMERA) @@ -342,68 +332,68 @@ class QrCodeScannerFragment : Fragment(R.layout.fragment_qrcode_scanner), AutoIn } private fun showRestoreDgcConfirmation(containerId: CertificateContainerId) = - displayDialog(cancelable = false) { - setTitle(R.string.recycle_bin_restore_dgc_dialog_title) - setMessage(R.string.recycle_bin_restore_dgc_dialog_message) - setPositiveButton(android.R.string.ok) { _, _ -> viewModel.restoreCertificate(containerId) } + displayDialog { + title(R.string.recycle_bin_restore_dgc_dialog_title) + message(R.string.recycle_bin_restore_dgc_dialog_message) + positiveButton(android.R.string.ok) { viewModel.restoreCertificate(containerId) } + setCancelable(false) } private fun showRestoreCoronaTestConfirmation(recycledCoronaTest: BaseCoronaTest) = - displayDialog(cancelable = false) { - setTitle(R.string.recycle_bin_restore_corona_test_dialog_title) - setMessage(R.string.recycle_bin_restore_corona_test_dialog_message) - setPositiveButton(R.string.recycle_bin_restore_corona_test_dialog_title) { _, _ -> - viewModel.restoreCoronaTest( - recycledCoronaTest - ) + displayDialog { + title(R.string.recycle_bin_restore_corona_test_dialog_title) + message(R.string.recycle_bin_restore_corona_test_dialog_message) + positiveButton(R.string.recycle_bin_restore_corona_test_dialog_title) { + viewModel.restoreCoronaTest(recycledCoronaTest) } + setCancelable(false) } private fun showMaxPersonExceedsThresholdResult(max: Int, deeplink: Uri, navOptions: NavOptions) = - displayDialog( - cancelable = false, - onDismissAction = { findNavController().navigate(deeplink, navOptions) } - ) { - setTitle(R.string.qr_code_error_max_person_threshold_title) - setMessage(getString(R.string.qr_code_error_max_person_threshold_body, max)) - setPositiveButton(R.string.qr_code_error_max_person_covpasscheck_button) { _, _ -> + displayDialog { + title(R.string.qr_code_error_max_person_threshold_title) + message(getString(R.string.qr_code_error_max_person_threshold_body, max)) + positiveButton(R.string.qr_code_error_max_person_covpasscheck_button) { openUrl(R.string.qr_code_error_max_person_covpasscheck_link) } - setNegativeButton(R.string.qr_code_error_max_person_faq_button) { _, _ -> + negativeButton(R.string.qr_code_error_max_person_faq_button) { openUrl(R.string.qr_code_error_max_person_faq_link) } - setNeutralButton(android.R.string.ok) { _, _ -> } + neutralButton(android.R.string.ok) + dismissAction { findNavController().navigate(deeplink, navOptions) } + setCancelable(false) } private fun showMaxPersonExceedsMaxResult(max: Int) = - displayDialog( - cancelable = false, - onDismissAction = { popBackStack() } - ) { - setTitle(R.string.qr_code_error_max_person_max_title) - setMessage(getString(R.string.qr_code_error_max_person_max_body, max)) - setPositiveButton(R.string.qr_code_error_max_person_covpasscheck_button) { _, _ -> + displayDialog { + title(R.string.qr_code_error_max_person_max_title) + message(getString(R.string.qr_code_error_max_person_max_body, max)) + positiveButton(R.string.qr_code_error_max_person_covpasscheck_button) { openUrl(R.string.qr_code_error_max_person_covpasscheck_link) } - setNegativeButton(R.string.qr_code_error_max_person_faq_button) { _, _ -> + negativeButton(R.string.qr_code_error_max_person_faq_button) { openUrl(R.string.qr_code_error_max_person_faq_link) } - setNeutralButton(android.R.string.ok) { _, _ -> } + neutralButton(android.R.string.ok) + dismissAction { popBackStack() } + setCancelable(false) } private fun showDccTicketingErrorDialog(humanReadableError: HumanReadableError) { - displayDialog(onDismissAction = { startDecode() }) { - setTitle(humanReadableError.title) - setMessage(humanReadableError.description) - setPositiveButton(R.string.errors_generic_button_positive) { _, _ -> } + displayDialog { + if (humanReadableError.title != null) title(humanReadableError.title) + message(humanReadableError.description) + positiveButton(R.string.errors_generic_button_positive) + dismissAction { startDecode() } } } private fun showDccTicketingErrorDialog(errorMsg: LazyString) { - displayDialog(onDismissAction = { startDecode() }) { - setTitle(R.string.errors_generic_headline_short) - setMessage(errorMsg.get(requireContext())) - setPositiveButton(R.string.errors_generic_button_positive) { _, _ -> } + displayDialog { + title(R.string.errors_generic_headline_short) + message(errorMsg.get(requireContext())) + positiveButton(R.string.errors_generic_button_positive) + dismissAction { startDecode() } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/qrcode/ui/ScannerExtensions.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/qrcode/ui/ScannerExtensions.kt index d629aa7c96b..3f36ed76dce 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/qrcode/ui/ScannerExtensions.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/qrcode/ui/ScannerExtensions.kt @@ -1,11 +1,6 @@ package de.rki.coronawarnapp.qrcode.ui -import android.content.Context import android.net.Uri -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder -import de.rki.coronawarnapp.covidcertificate.common.exception.InvalidHealthCertificateException import de.rki.coronawarnapp.covidcertificate.common.repository.CertificateContainerId import de.rki.coronawarnapp.covidcertificate.common.repository.RecoveryCertificateContainerId import de.rki.coronawarnapp.covidcertificate.common.repository.TestCertificateContainerId @@ -14,35 +9,8 @@ import de.rki.coronawarnapp.covidcertificate.recovery.ui.details.RecoveryCertifi import de.rki.coronawarnapp.covidcertificate.test.ui.details.TestCertificateDetailsFragment import de.rki.coronawarnapp.covidcertificate.vaccination.ui.details.VaccinationDetailsFragment import de.rki.coronawarnapp.qrcode.handler.CheckInQrCodeHandler -import de.rki.coronawarnapp.util.ExternalActionHelper.openUrl import de.rki.coronawarnapp.util.ui.toResolvingString -fun Throwable.toQrCodeErrorDialogBuilder(context: Context): MaterialAlertDialogBuilder { - val throwable = this - return toErrorDialogBuilder(context).apply { - if (throwable is InvalidHealthCertificateException) { - when { - throwable.isCertificateInvalid -> - setNeutralButton(R.string.error_button_dcc_faq) { _, _ -> - context.openUrl(R.string.error_button_dcc_faq_link) - } - - throwable.isSignatureInvalid -> { - setTitle(R.string.dcc_signature_validation_dialog_title) - setNeutralButton(R.string.dcc_signature_validation_dialog_faq_button) { _, _ -> - context.openUrl(R.string.dcc_signature_validation_dialog_faq_link) - } - } - throwable.isAlreadyRegistered -> { - setNeutralButton(R.string.error_button_dcc_faq) { _, _ -> - context.openUrl(R.string.error_dcc_already_registered_faq_link) - } - } - } - } - } -} - fun CertificateContainerId.toDccDetails(): DccResult = DccResult.Details(uri()) fun CertificateContainerId.toMaxPersonsWarning(max: Int): DccResult = DccResult.MaxPersonsWarning(uri(), max) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/RecyclerBinOverviewFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/RecyclerBinOverviewFragment.kt index 83a91d737d1..0898315fa44 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/RecyclerBinOverviewFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/RecyclerBinOverviewFragment.kt @@ -9,8 +9,9 @@ import androidx.navigation.fragment.findNavController import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.RecyclerBinOverviewFragmentBinding import de.rki.coronawarnapp.reyclebin.ui.adapter.RecyclerBinAdapter -import de.rki.coronawarnapp.reyclebin.ui.dialog.RecycleBinDialogType -import de.rki.coronawarnapp.reyclebin.ui.dialog.show +import de.rki.coronawarnapp.reyclebin.ui.dialog.removeAllItemsDialog +import de.rki.coronawarnapp.reyclebin.ui.dialog.restoreCertificateDialog +import de.rki.coronawarnapp.reyclebin.ui.dialog.restoreTestDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.list.setupSwipe import de.rki.coronawarnapp.util.lists.diffutil.update @@ -54,22 +55,15 @@ class RecyclerBinOverviewFragment : Fragment(R.layout.recycler_bin_overview_frag } private fun handleRecyclerEvent(event: RecyclerBinEvent): Unit = when (event) { - RecyclerBinEvent.ConfirmRemoveAll -> RecycleBinDialogType.RemoveAllItemsConfirmation.show( - fragment = this, - positiveButtonAction = { viewModel.onRemoveAllItemsConfirmation() } - ) + RecyclerBinEvent.ConfirmRemoveAll -> removeAllItemsDialog { viewModel.onRemoveAllItemsConfirmation() } is RecyclerBinEvent.RemoveCertificate -> viewModel.onRemoveCertificate(event.certificate) - is RecyclerBinEvent.ConfirmRestoreCertificate -> RecycleBinDialogType.RestoreCertificateConfirmation.show( - fragment = this, - positiveButtonAction = { viewModel.onRestoreCertificateConfirmation(event.certificate) } - ) + is RecyclerBinEvent.ConfirmRestoreCertificate -> restoreCertificateDialog { + viewModel.onRestoreCertificateConfirmation(event.certificate) + } - is RecyclerBinEvent.ConfirmRestoreTest -> RecycleBinDialogType.RestoreTestConfirmation.show( - fragment = this, - positiveButtonAction = { viewModel.onRestoreTestConfirmation(event.test) } - ) + is RecyclerBinEvent.ConfirmRestoreTest -> restoreTestDialog { viewModel.onRestoreTestConfirmation(event.test) } is RecyclerBinEvent.RemoveTest -> viewModel.onRemoveTest(event.test) is RecyclerBinEvent.RestoreDuplicateTest -> findNavController().navigate( diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogFragment.kt deleted file mode 100644 index c291c862505..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogFragment.kt +++ /dev/null @@ -1,78 +0,0 @@ -package de.rki.coronawarnapp.reyclebin.ui.dialog - -import android.app.Dialog -import android.content.DialogInterface -import android.os.Bundle -import android.os.Parcelable -import androidx.annotation.StringRes -import androidx.appcompat.app.AlertDialog -import androidx.core.os.bundleOf -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.setFragmentResult -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat -import kotlinx.parcelize.Parcelize -import timber.log.Timber - -class RecycleBinDialogFragment : DialogFragment() { - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val config = requireArguments().getParcelable(PARAM_DIALOG_CONFIG) - requireNotNull(config) { "Dialog config is null" } - - return config.run { - MaterialAlertDialogBuilder(requireContext()) - .setTitle(titleRes) - .setMessage(msgRes) - .setPositiveButton(positiveButtonRes) { _, _ -> setAction(Action.PositiveButtonClicked) } - .setNegativeButton(negativeButtonRes) { _, _ -> setAction(Action.NegativeButtonClicked) } - .create() - } - } - - override fun onStart() { - super.onStart() - val config = requireArguments().getParcelable(PARAM_DIALOG_CONFIG) - if (config?.isDeleteDialog == true) { - (dialog as AlertDialog).getButton(DialogInterface.BUTTON_POSITIVE) - ?.setTextColor(requireContext().getColorCompat(R.color.colorTextDeleteButtonDialog)) - } - } - - private fun setAction(action: Action) { - Timber.d("setAction(action=%s)", action) - setFragmentResult(REQUEST_KEY, bundleOf(PARAM_DIALOG_ACTION to action)) - } - - override fun onDismiss(dialog: DialogInterface) { - setAction(Action.Dismissed) - super.onDismiss(dialog) - } - - enum class Action { - PositiveButtonClicked, - NegativeButtonClicked, - Dismissed - } - - @Parcelize - data class Config( - @StringRes val titleRes: Int, - @StringRes val msgRes: Int, - @StringRes val positiveButtonRes: Int, - @StringRes val negativeButtonRes: Int, - val isDeleteDialog: Boolean = false - ) : Parcelable - - companion object { - val TAG: String = RecycleBinDialogFragment::class.java.simpleName - val REQUEST_KEY = "${TAG}_REQUEST_KEY" - val PARAM_DIALOG_ACTION = "${TAG}_PARAM_DIALOG_ACTION" - private val PARAM_DIALOG_CONFIG = "${TAG}_PARAM_DIALOG_CONFIG" - - fun newInstance(dialogConfig: Config) = RecycleBinDialogFragment().apply { - arguments = bundleOf(PARAM_DIALOG_CONFIG to dialogConfig) - } - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogHelper.kt deleted file mode 100644 index 489bb32f8e0..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogHelper.kt +++ /dev/null @@ -1,41 +0,0 @@ -package de.rki.coronawarnapp.reyclebin.ui.dialog - -import androidx.fragment.app.Fragment - -typealias DialogAction = () -> Unit - -/** - * Display the dialog and register actions for button clicks or dismissal - */ -fun RecycleBinDialogType.show( - fragment: Fragment, - positiveButtonAction: DialogAction, - negativeButtonAction: DialogAction = { }, - dismissAction: DialogAction = { } -) = fragment.showRecyclerDialog(config, positiveButtonAction, negativeButtonAction, dismissAction) - -private fun Fragment.showRecyclerDialog( - dialogConfig: RecycleBinDialogFragment.Config, - positiveButtonAction: DialogAction, - negativeButtonAction: DialogAction, - dismissAction: DialogAction -) { - val dialog = RecycleBinDialogFragment.newInstance(dialogConfig) - childFragmentManager.also { - it.setFragmentResultListener(RecycleBinDialogFragment.REQUEST_KEY, viewLifecycleOwner) { _, bundle -> - val action = bundle.getSerializable( - RecycleBinDialogFragment.PARAM_DIALOG_ACTION - ) as? RecycleBinDialogFragment.Action - - requireNotNull(action) { "Action is null" } - - when (action) { - RecycleBinDialogFragment.Action.PositiveButtonClicked -> positiveButtonAction() - RecycleBinDialogFragment.Action.NegativeButtonClicked -> negativeButtonAction() - RecycleBinDialogFragment.Action.Dismissed -> dismissAction() - } - } - - dialog.show(it, RecycleBinDialogFragment.TAG) - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogType.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogType.kt deleted file mode 100644 index 928e7a44162..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogType.kt +++ /dev/null @@ -1,64 +0,0 @@ -package de.rki.coronawarnapp.reyclebin.ui.dialog - -import de.rki.coronawarnapp.R - -/** - * Use the extension [RecycleBinDialogType.show] to display a dialog - * e.g. RecycleBinDialogType.RemoveAllConfirmation.show(...) - */ -sealed class RecycleBinDialogType { - abstract val config: RecycleBinDialogFragment.Config - - object RemoveAllItemsConfirmation : RecycleBinDialogType() { - override val config: RecycleBinDialogFragment.Config - get() = RecycleBinDialogFragment.Config( - titleRes = R.string.recycle_bin_remove_all_dialog_title, - msgRes = R.string.recycle_bin_remove_all_dialog_message, - positiveButtonRes = R.string.recycle_bin_remove_all_dialog_positive_button, - negativeButtonRes = R.string.recycle_bin_remove_all_dialog_negative_button, - isDeleteDialog = true - ) - } - - object RecycleCertificateConfirmation : RecycleBinDialogType() { - override val config: RecycleBinDialogFragment.Config - get() = RecycleBinDialogFragment.Config( - titleRes = R.string.recycle_bin_recycle_certificate_dialog_title, - msgRes = R.string.recycle_bin_recycle_certificate_dialog_message, - positiveButtonRes = R.string.recycle_bin_recycle_certificate_dialog_positive_button, - negativeButtonRes = R.string.recycle_bin_recycle_certificate_dialog_negative_button, - isDeleteDialog = true - ) - } - - object RecycleTestConfirmation : RecycleBinDialogType() { - override val config: RecycleBinDialogFragment.Config - get() = RecycleBinDialogFragment.Config( - titleRes = R.string.submission_test_result_dialog_move_test_to_recycle_bin_title, - msgRes = R.string.submission_test_result_dialog_move_test_to_recycle_bin_body, - positiveButtonRes = R.string.submission_test_result_dialog_move_test_to_recycle_bin_button, - negativeButtonRes = R.string.recycle_bin_recycle_certificate_dialog_negative_button, - isDeleteDialog = true - ) - } - - object RestoreCertificateConfirmation : RecycleBinDialogType() { - override val config: RecycleBinDialogFragment.Config - get() = RecycleBinDialogFragment.Config( - titleRes = R.string.recycle_bin_restore_certificate_dialog_title, - msgRes = R.string.recycle_bin_restore_certificate_dialog_message, - positiveButtonRes = R.string.recycle_bin_restore_certificate_dialog_positive_button, - negativeButtonRes = R.string.recycle_bin_restore_certificate_dialog_negative_button - ) - } - - object RestoreTestConfirmation : RecycleBinDialogType() { - override val config: RecycleBinDialogFragment.Config - get() = RecycleBinDialogFragment.Config( - titleRes = R.string.recycle_bin_restore_test_dialog_title, - msgRes = R.string.recycle_bin_restore_test_dialog_message, - positiveButtonRes = R.string.recycle_bin_restore_test_dialog_positive_button, - negativeButtonRes = R.string.recycle_bin_restore_test_dialog_negative_button - ) - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogs.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogs.kt index 24b71c8b271..a418170c63f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogs.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/reyclebin/ui/dialog/RecycleBinDialogs.kt @@ -4,48 +4,42 @@ import androidx.fragment.app.Fragment import de.rki.coronawarnapp.R import de.rki.coronawarnapp.ui.dialog.displayDialog -fun Fragment.removeAllItemsDialog(positiveButtonAction: () -> Unit) = - displayDialog(isDeleteDialog = true) { - setTitle(R.string.recycle_bin_remove_all_dialog_title) - setMessage(R.string.recycle_bin_remove_all_dialog_message) - setPositiveButton(R.string.recycle_bin_remove_all_dialog_positive_button) { _, _ -> positiveButtonAction() } - setNegativeButton(R.string.recycle_bin_recycle_certificate_dialog_negative_button) { _, _ -> } - } +fun Fragment.removeAllItemsDialog(positiveButtonAction: () -> Unit) = displayDialog { + title(R.string.recycle_bin_remove_all_dialog_title) + message(R.string.recycle_bin_remove_all_dialog_message) + positiveButton(R.string.recycle_bin_remove_all_dialog_positive_button) { positiveButtonAction() } + negativeButton(R.string.recycle_bin_recycle_certificate_dialog_negative_button) + setDeleteDialog(true) +} -fun Fragment.recycleCertificateDialog(positiveButtonAction: () -> Unit) = - displayDialog(isDeleteDialog = true) { - setTitle(R.string.recycle_bin_recycle_certificate_dialog_title) - setMessage(R.string.recycle_bin_recycle_certificate_dialog_message) - setPositiveButton(R.string.recycle_bin_recycle_certificate_dialog_positive_button) { _, _ -> - positiveButtonAction() - } - setNegativeButton(R.string.recycle_bin_recycle_certificate_dialog_negative_button) { _, _ -> } - } +fun Fragment.recycleCertificateDialog(positiveButtonAction: () -> Unit) = displayDialog { + title(R.string.recycle_bin_recycle_certificate_dialog_title) + message(R.string.recycle_bin_recycle_certificate_dialog_message) + positiveButton(R.string.recycle_bin_recycle_certificate_dialog_positive_button) { positiveButtonAction() } + negativeButton(R.string.recycle_bin_recycle_certificate_dialog_negative_button) + setDeleteDialog(true) +} -fun Fragment.recycleTestDialog(positiveButtonAction: () -> Unit) = - displayDialog(isDeleteDialog = true) { - setTitle(R.string.submission_test_result_dialog_move_test_to_recycle_bin_title) - setMessage(R.string.submission_test_result_dialog_move_test_to_recycle_bin_body) - setPositiveButton(R.string.submission_test_result_dialog_move_test_to_recycle_bin_button) { _, _ -> - positiveButtonAction() - } - setNegativeButton(R.string.recycle_bin_recycle_certificate_dialog_negative_button) { _, _ -> } - } +fun Fragment.recycleTestDialog(positiveButtonAction: () -> Unit) = displayDialog { + title(R.string.submission_test_result_dialog_move_test_to_recycle_bin_title) + message(R.string.submission_test_result_dialog_move_test_to_recycle_bin_body) + positiveButton(R.string.submission_test_result_dialog_move_test_to_recycle_bin_button) { positiveButtonAction() } + negativeButton(R.string.recycle_bin_recycle_certificate_dialog_negative_button) + setDeleteDialog(true) +} -fun Fragment.restoreCertificateDialog(positiveButtonAction: () -> Unit) = - displayDialog { - setTitle(R.string.recycle_bin_restore_certificate_dialog_title) - setMessage(R.string.recycle_bin_restore_certificate_dialog_message) - setPositiveButton(R.string.recycle_bin_restore_certificate_dialog_positive_button) { _, _ -> - positiveButtonAction() - } - setNegativeButton(R.string.recycle_bin_recycle_certificate_dialog_negative_button) { _, _ -> } +fun Fragment.restoreCertificateDialog(positiveButtonAction: () -> Unit) = displayDialog { + title(R.string.recycle_bin_restore_certificate_dialog_title) + message(R.string.recycle_bin_restore_certificate_dialog_message) + positiveButton(R.string.recycle_bin_restore_certificate_dialog_positive_button) { + positiveButtonAction() } + negativeButton(R.string.recycle_bin_recycle_certificate_dialog_negative_button) +} -fun Fragment.restoreTestDialog(positiveButtonAction: () -> Unit) = - displayDialog { - setTitle(R.string.recycle_bin_restore_test_dialog_title) - setMessage(R.string.recycle_bin_restore_test_dialog_message) - setPositiveButton(R.string.recycle_bin_restore_test_dialog_positive_button) { _, _ -> positiveButtonAction() } - setNegativeButton(R.string.recycle_bin_recycle_certificate_dialog_negative_button) { _, _ -> } - } +fun Fragment.restoreTestDialog(positiveButtonAction: () -> Unit) = displayDialog { + title(R.string.recycle_bin_restore_test_dialog_title) + message(R.string.recycle_bin_restore_test_dialog_message) + positiveButton(R.string.recycle_bin_restore_test_dialog_positive_button) { positiveButtonAction() } + negativeButton(R.string.recycle_bin_recycle_certificate_dialog_negative_button) +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/TestRegistrationStateProcessor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/TestRegistrationStateProcessor.kt index a257ba86b0c..889a66812ad 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/TestRegistrationStateProcessor.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/TestRegistrationStateProcessor.kt @@ -1,10 +1,8 @@ package de.rki.coronawarnapp.submission -import android.content.Context -import com.google.android.material.dialog.MaterialAlertDialogBuilder +import androidx.fragment.app.Fragment import de.rki.coronawarnapp.R import de.rki.coronawarnapp.bugreporting.censors.submission.PcrQrCodeCensor -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.coronatest.TestRegistrationRequest import de.rki.coronawarnapp.coronatest.errors.AlreadyRedeemedException import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQRCode @@ -17,6 +15,7 @@ import de.rki.coronawarnapp.exception.http.CwaServerError import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.familytest.core.repository.FamilyTestRepository +import de.rki.coronawarnapp.ui.dialog.displayDialog import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.sync.Mutex @@ -37,51 +36,43 @@ class TestRegistrationStateProcessor @Inject constructor( data class TestRegistered(val test: BaseCoronaTest) : State() data class Error(val exception: Exception) : State() { - fun getDialogBuilder(context: Context, comingFromTan: Boolean = false): MaterialAlertDialogBuilder { - val builder = MaterialAlertDialogBuilder(context).apply { - setCancelable(true) - } - - return when (exception) { - is AlreadyRedeemedException -> builder.apply { + fun showExceptionDialog( + fragment: Fragment, + comingFromTan: Boolean = false, + positiveButtonFunction: () -> Unit = { } + ) { + when (exception) { + is AlreadyRedeemedException -> fragment.displayDialog { if (comingFromTan) { - setTitle(R.string.submission_error_dialog_web_test_paired_title_tan) - setMessage(R.string.submission_error_dialog_web_test_paired_body_tan) + title(R.string.submission_error_dialog_web_test_paired_title_tan) + message(R.string.submission_error_dialog_web_test_paired_body_tan) } else { - setTitle(R.string.submission_error_dialog_web_tan_redeemed_title) - setMessage(R.string.submission_error_dialog_web_tan_redeemed_body) - } - setPositiveButton(android.R.string.ok) { _, _ -> - /* dismiss */ + title(R.string.submission_error_dialog_web_tan_redeemed_title) + message(R.string.submission_error_dialog_web_tan_redeemed_body) } + positiveButton(android.R.string.ok) { positiveButtonFunction() } } - is BadRequestException -> builder.apply { + is BadRequestException -> fragment.displayDialog { if (comingFromTan) { - setTitle(R.string.submission_error_dialog_web_test_paired_title_tan) - setMessage(R.string.submission_error_dialog_web_test_paired_body_tan) + title(R.string.submission_error_dialog_web_test_paired_title_tan) + message(R.string.submission_error_dialog_web_test_paired_body_tan) } else { - setTitle(R.string.submission_qr_code_scan_invalid_dialog_headline) - setMessage(R.string.submission_qr_code_scan_invalid_dialog_body) - } - setPositiveButton(android.R.string.ok) { _, _ -> - /* dismiss */ + title(R.string.submission_qr_code_scan_invalid_dialog_headline) + message(R.string.submission_qr_code_scan_invalid_dialog_body) } + positiveButton(android.R.string.ok) { positiveButtonFunction() } } - is CwaClientError, is CwaServerError -> builder.apply { - setTitle(R.string.submission_error_dialog_web_generic_error_title) - setMessage(R.string.submission_error_dialog_web_generic_network_error_body) - setPositiveButton(android.R.string.ok) { _, _ -> - /* dismiss */ - } + is CwaClientError, is CwaServerError -> fragment.displayDialog { + title(R.string.submission_error_dialog_web_generic_error_title) + message(R.string.submission_error_dialog_web_generic_network_error_body) + positiveButton(android.R.string.ok) { positiveButtonFunction() } } - is CwaWebException -> builder.apply { - setTitle(R.string.submission_error_dialog_web_generic_error_title) - setMessage(R.string.submission_error_dialog_web_generic_error_body) - setPositiveButton(android.R.string.ok) { _, _ -> - /* dismiss */ - } + is CwaWebException -> fragment.displayDialog { + title(R.string.submission_error_dialog_web_generic_error_title) + message(R.string.submission_error_dialog_web_generic_error_body) + positiveButton(android.R.string.ok) { positiveButtonFunction() } } - else -> exception.toErrorDialogBuilder(context) + else -> fragment.displayDialog { setError(exception) } } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/TracingConsentDialog.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/TracingConsentDialog.kt index 3861f158d24..ad240e03953 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/TracingConsentDialog.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/TracingConsentDialog.kt @@ -8,8 +8,8 @@ fun Fragment.tracingConsentDialog( positiveButton: () -> Unit, negativeButton: () -> Unit ) = displayDialog { - setTitle(R.string.onboarding_tracing_headline_consent) - setMessage(R.string.onboarding_tracing_body_consent) - setPositiveButton(R.string.onboarding_button_enable) { _, _ -> positiveButton() } - setNegativeButton(R.string.onboarding_button_cancel) { _, _ -> negativeButton() } + title(R.string.onboarding_tracing_headline_consent) + message(R.string.onboarding_tracing_body_consent) + positiveButton(R.string.onboarding_button_enable) { positiveButton() } + negativeButton(R.string.onboarding_button_cancel) { negativeButton() } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/settings/TracingSettingsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/settings/TracingSettingsFragment.kt index 953925af58e..e683b936bbf 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/settings/TracingSettingsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/settings/TracingSettingsFragment.kt @@ -7,11 +7,10 @@ import android.view.accessibility.AccessibilityEvent import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentTracingSettingsBinding import de.rki.coronawarnapp.tracing.ui.settings.TracingSettingsFragmentViewModel.Event import de.rki.coronawarnapp.tracing.ui.tracingConsentDialog -import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.ExternalActionHelper.openDeviceSettings import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.observe2 @@ -70,9 +69,7 @@ class TracingSettingsFragment : Fragment(R.layout.fragment_tracing_settings), Au binding.switchRow.setChecked(checked) } - viewModel.ensErrorEvents.observe2(this) { error -> - error.toErrorDialogBuilder(requireContext()).show() - } + viewModel.ensErrorEvents.observe2(this) { error -> displayDialog { setError(error) } } setButtonOnClickListener() } @@ -110,19 +107,10 @@ class TracingSettingsFragment : Fragment(R.layout.fragment_tracing_settings), Au if (isChecked) turnTracingOn() else turnTracingOff() } - private fun showManualCheckingRequiredDialog() { - val dialog = DialogHelper.DialogInstance( - requireActivity(), - R.string.onboarding_manual_required_dialog_headline, - R.string.onboarding_manual_required_dialog_body, - R.string.onboarding_manual_required_dialog_button, - null, - false, - { - // close dialog - } - ) - DialogHelper.showDialog(dialog) + private fun showManualCheckingRequiredDialog() = displayDialog { + title(R.string.onboarding_manual_required_dialog_headline) + message(R.string.onboarding_manual_required_dialog_body) + positiveButton(R.string.onboarding_manual_required_dialog_button) } companion object { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/CwaDialog.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/CwaDialog.kt new file mode 100644 index 00000000000..bfa01064bbe --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/CwaDialog.kt @@ -0,0 +1,138 @@ +package de.rki.coronawarnapp.ui.dialog + +import android.os.Parcelable +import androidx.annotation.LayoutRes +import androidx.annotation.StringRes +import kotlinx.parcelize.Parcelize +import kotlinx.parcelize.RawValue + +@DslMarker +annotation class CwaDialogDsl + +typealias DialogAction = () -> Unit + +@Parcelize +data class CwaDialogTexts( + val title: @RawValue IntOrString? = null, + val message: @RawValue IntOrString? = null, + val positiveButtonText: @RawValue IntOrString? = null, + val negativeButtonText: @RawValue IntOrString? = null, + val neutralButtonText: @RawValue IntOrString? = null, +) : Parcelable + +@CwaDialogDsl +class CwaDialogBuilder { + private var title = IntOrString() + private var message = IntOrString() + private var positiveButtonText = IntOrString() + private var positiveButtonAction: DialogAction = { } + private var negativeButtonText = IntOrString() + private var negativeButtonAction: DialogAction = { } + private var neutralButtonText = IntOrString() + private var neutralButtonAction: DialogAction = { } + private var dismissAction: DialogAction = { } + private var isCancelable: Boolean = true + private var isDeleteDialog: Boolean = false + private var customView: Int? = null + private var throwableError: Throwable? = null + + fun title(@StringRes resource: Int) { + title = IntOrString.IntResource(resource) + } + + fun title(text: String) { + title = IntOrString.StringResource(text) + } + + fun message(@StringRes resource: Int) { + message = IntOrString.IntResource(resource) + } + + fun message(text: String) { + message = IntOrString.StringResource(text) + } + + fun positiveButton(@StringRes resource: Int, lambda: () -> Unit = { }) { + positiveButtonText = IntOrString.IntResource(resource) + positiveButtonAction = lambda + } + + fun positiveButton(text: String, lambda: () -> Unit = { }) { + positiveButtonText = IntOrString.StringResource(text) + positiveButtonAction = lambda + } + + fun negativeButton(@StringRes resource: Int, lambda: () -> Unit = { }) { + negativeButtonText = IntOrString.IntResource(resource) + negativeButtonAction = lambda + } + + fun negativeButton(text: String, lambda: () -> Unit = { }) { + negativeButtonText = IntOrString.StringResource(text) + negativeButtonAction = lambda + } + + fun neutralButton(@StringRes resource: Int, lambda: () -> Unit = { }) { + neutralButtonText = IntOrString.IntResource(resource) + neutralButtonAction = lambda + } + + fun neutralButton(text: String, lambda: () -> Unit = { }) { + neutralButtonText = IntOrString.StringResource(text) + neutralButtonAction = lambda + } + + fun dismissAction(lambda: () -> Unit) { + dismissAction = { lambda() } + } + + fun setCancelable(cancelable: Boolean) { + isCancelable = cancelable + } + + fun setDeleteDialog(isDelete: Boolean) { + isDeleteDialog = isDelete + } + + fun setView(@LayoutRes view: Int) { + customView = view + } + + fun setError(error: Throwable?) { + throwableError = error + } + + fun build() = Triple( + CwaDialogTexts(title, message, positiveButtonText, negativeButtonText, neutralButtonText), + CwaDialogActions(positiveButtonAction, negativeButtonAction, neutralButtonAction, dismissAction), + CwaDialogOptions(isCancelable, isDeleteDialog, customView, throwableError) + ) +} + +data class CwaDialogActions( + val positiveAction: DialogAction = { }, + val negativeAction: DialogAction = { }, + val neutralAction: DialogAction = { }, + val dismissAction: DialogAction = { } +) + +@Parcelize +data class CwaDialogOptions( + val isCancelable: Boolean = true, + val isDeleteDialog: Boolean = false, + val customView: Int? = null, + val throwableError: Throwable? = null +) : Parcelable + +@Parcelize +open class IntOrString : Parcelable { + @Parcelize + data class StringResource( + val stringResource: String + ) : Parcelable, IntOrString() + + @Parcelize + data class IntResource( + @StringRes val intResource: Int + ) : Parcelable, IntOrString() +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/CwaDialogFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/CwaDialogFragment.kt new file mode 100644 index 00000000000..7ed2fe216a6 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/CwaDialogFragment.kt @@ -0,0 +1,154 @@ +package de.rki.coronawarnapp.ui.dialog + +import android.app.Dialog +import android.content.DialogInterface +import android.os.Bundle +import android.text.SpannableString +import android.text.method.LinkMovementMethod +import android.text.util.Linkify +import android.widget.TextView +import androidx.appcompat.app.AlertDialog +import androidx.core.os.bundleOf +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.setFragmentResult +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat +import de.rki.coronawarnapp.util.ContextExtensions.getColorStateListCompat +import de.rki.coronawarnapp.util.HumanReadableError +import de.rki.coronawarnapp.util.tryHumanReadableError +import timber.log.Timber +import java.util.regex.Pattern + +class CwaDialogFragment : DialogFragment() { + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val texts = requireArguments().getParcelable(CWA_DIALOG_TEXTS) + val options = requireArguments().getParcelable(CWA_DIALOG_OPTIONS) + requireNotNull(texts) { "Could not retrieve dialog texts. Result is null" } + requireNotNull(options) { "Could not retrieve dialog options. Result is null" } + isCancelable = options.isCancelable + + val builder = MaterialAlertDialogBuilder(requireContext()) + return builder.apply { + if (options.throwableError != null) { + val humanReadableError = options.throwableError.tryHumanReadableError(requireContext()) + setErrorDialog(humanReadableError) + } + when (texts.title) { + is IntOrString.IntResource -> setTitle(texts.title.intResource) + is IntOrString.StringResource -> setTitle(texts.title.stringResource) + } + when (texts.message) { + is IntOrString.IntResource -> setMessage(texts.message.intResource) + is IntOrString.StringResource -> setMessage(texts.message.stringResource) + } + when (texts.positiveButtonText) { + is IntOrString.IntResource -> setPositiveButton(texts.positiveButtonText.intResource) { _, _ -> + setAction(Action.PositiveButtonClicked) + dismiss() + } + is IntOrString.StringResource -> setPositiveButton(texts.positiveButtonText.stringResource) { _, _ -> + setAction(Action.PositiveButtonClicked) + dismiss() + } + } + when (texts.negativeButtonText) { + is IntOrString.IntResource -> setNegativeButton(texts.negativeButtonText.intResource) { _, _ -> + setAction(Action.NegativeButtonClicked) + dismiss() + } + is IntOrString.StringResource -> setNegativeButton(texts.negativeButtonText.stringResource) { _, _ -> + setAction(Action.NegativeButtonClicked) + dismiss() + } + } + when (texts.neutralButtonText) { + is IntOrString.IntResource -> setNeutralButton(texts.neutralButtonText.intResource) { _, _ -> + setAction(Action.NeutralButtonClicked) + dismiss() + } + is IntOrString.StringResource -> setNeutralButton(texts.neutralButtonText.stringResource) { _, _ -> + setAction(Action.NeutralButtonClicked) + dismiss() + } + } + options.customView?.let { setView(it) } + }.create() + } + + private fun setAction(action: Action) { + Timber.d("setAction(action=%s)", action) + setFragmentResult(REQUEST_KEY, bundleOf(PARAM_DIALOG_ACTION to action)) + } + + override fun onStart() { + super.onStart() + val options = requireArguments().getParcelable( + CWA_DIALOG_OPTIONS + ) + if (options?.isDeleteDialog == true) { + (dialog as AlertDialog).getButton(DialogInterface.BUTTON_POSITIVE) + ?.setTextColor(requireContext().getColorCompat(R.color.colorTextDeleteButtonDialog)) + } + } + + override fun onDismiss(dialog: DialogInterface) { + setAction(Action.Dismissed) + super.onDismiss(dialog) + } + + enum class Action { + PositiveButtonClicked, + NegativeButtonClicked, + NeutralButtonClicked, + Dismissed + } + + private fun MaterialAlertDialogBuilder.setErrorDialog(humanReadableError: HumanReadableError) { + val title = context.getString(R.string.errors_generic_headline_short) + setTitle(humanReadableError.title ?: title) + setMessageView(humanReadableError.description, textHasLinks = true) + setPositiveButton(R.string.errors_generic_button_positive) { _, _ -> } + } + + private fun MaterialAlertDialogBuilder.setMessageView( + message: String, + textHasLinks: Boolean, + ) { + // create spannable and add links, removed stack trace links into nowhere + val spannable = SpannableString(message) + val httpPattern: Pattern = Pattern.compile("[a-z]+://[^ \\n]*") + Linkify.addLinks(spannable, httpPattern, "") + + val paddingStartEnd = context.resources.getDimension(R.dimen.spacing_normal).toInt() + val paddingLeftRight = context.resources.getDimension(R.dimen.spacing_small).toInt() + + val textView = TextView(context, null, R.style.TextAppearance_AppCompat_Subhead).apply { + text = spannable + linksClickable = true + movementMethod = LinkMovementMethod.getInstance() + setPadding( + paddingStartEnd, + paddingLeftRight, + paddingStartEnd, + paddingLeftRight + ) + setLinkTextColor(context.getColorStateListCompat(R.color.button_primary)) + setTextIsSelectable(!textHasLinks) + } + setView(textView) + } + + companion object { + val TAG: String = CwaDialogFragment::class.java.simpleName + val REQUEST_KEY = "${TAG}_REQUEST_KEY" + val PARAM_DIALOG_ACTION = "${TAG}_PARAM_DIALOG_ACTION" + private val CWA_DIALOG_TEXTS = "${TAG}_CWA_DIALOG_TEXTS" + private val CWA_DIALOG_OPTIONS = "${TAG}_CWA_DIALOG_OPTIONS" + + fun newInstance(texts: CwaDialogTexts, options: CwaDialogOptions) = CwaDialogFragment().apply { + arguments = bundleOf(CWA_DIALOG_TEXTS to texts, CWA_DIALOG_OPTIONS to options) + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/CwaDialogHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/CwaDialogHelper.kt new file mode 100644 index 00000000000..105899d5bd0 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/CwaDialogHelper.kt @@ -0,0 +1,106 @@ +package de.rki.coronawarnapp.ui.dialog + +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment + +/** + * Helper function that creates a CwaDialog and displays it. + * Usage: + * + * ```kotlin + * createDialog { + * title("Title example") + * message("Message example") + * positiveButton("Positive button text") { foo1() } + * negativeButton("Negative button text") { foo2() } + * neutralButton("Neutral button text") { foo3() } + * dismissAction { foo4() } + * setCancelable(false) + * setDeleteDialog(true) + * setCustomView(R.layout.dialog_view) + * } + * ``` + */ +fun Fragment.displayDialog( + lambda: CwaDialogBuilder.() -> Unit +) { + val cwaDialog = CwaDialogBuilder().apply(lambda).build() + val texts = cwaDialog.first + val actions = cwaDialog.second + val options = cwaDialog.third + val positiveButtonAction = actions.positiveAction + val negativeButtonAction = actions.negativeAction + val neutralButtonAction = actions.neutralAction + val dismissAction = actions.dismissAction + val tag = this::class.java.simpleName + CwaDialogFragment.TAG + val dialog = CwaDialogFragment.newInstance(texts, options) + childFragmentManager.also { + it.setFragmentResultListener(CwaDialogFragment.REQUEST_KEY, viewLifecycleOwner) { _, bundle -> + val action = bundle.getSerializable( + CwaDialogFragment.PARAM_DIALOG_ACTION + ) as? CwaDialogFragment.Action + + requireNotNull(action) { "Action is null" } + + when (action) { + CwaDialogFragment.Action.PositiveButtonClicked -> positiveButtonAction() + CwaDialogFragment.Action.NegativeButtonClicked -> negativeButtonAction() + CwaDialogFragment.Action.NeutralButtonClicked -> neutralButtonAction() + CwaDialogFragment.Action.Dismissed -> dismissAction() + } + } + + dialog.show(it, tag) + } +} + +/** + * Helper function that creates a CwaDialog and displays it. + * Usage: + * + * ```kotlin + * createDialog { + * title("Title example") + * message("Message example") + * positiveButton("Positive button text") { foo1() } + * negativeButton("Negative button text") { foo2() } + * neutralButton("Neutral button text") { foo3() } + * dismissAction { foo4() } + * setCancelable(false) + * setDeleteDialog(true) + * setCustomView(R.layout.dialog_view) + * } + * ``` + */ +fun AppCompatActivity.displayDialog( + lambda: CwaDialogBuilder.() -> Unit +) { + val cwaDialog = CwaDialogBuilder().apply(lambda).build() + val texts = cwaDialog.first + val actions = cwaDialog.second + val options = cwaDialog.third + val positiveButtonAction = actions.positiveAction + val negativeButtonAction = actions.negativeAction + val neutralButtonAction = actions.neutralAction + val dismissAction = actions.dismissAction + val tag = this::class.java.simpleName + CwaDialogFragment.TAG + val dialog = CwaDialogFragment.newInstance(texts, options) + supportFragmentManager.also { + it.setFragmentResultListener(CwaDialogFragment.REQUEST_KEY, this) { _, bundle -> + val action = bundle.getSerializable( + CwaDialogFragment.PARAM_DIALOG_ACTION + ) as? CwaDialogFragment.Action + + requireNotNull(action) { "Action is null" } + + when (action) { + CwaDialogFragment.Action.PositiveButtonClicked -> positiveButtonAction() + CwaDialogFragment.Action.NegativeButtonClicked -> negativeButtonAction() + CwaDialogFragment.Action.NeutralButtonClicked -> neutralButtonAction() + CwaDialogFragment.Action.Dismissed -> dismissAction() + } + } + + dialog.show(it, tag) + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/DialogFragmentTemplate.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/DialogFragmentTemplate.kt deleted file mode 100644 index 437529f144d..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/DialogFragmentTemplate.kt +++ /dev/null @@ -1,60 +0,0 @@ -package de.rki.coronawarnapp.ui.dialog - -import android.app.Dialog -import android.content.DialogInterface -import android.os.Bundle -import android.os.Parcelable -import androidx.appcompat.app.AlertDialog -import androidx.core.os.bundleOf -import androidx.fragment.app.DialogFragment -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat -import kotlinx.parcelize.Parcelize -import kotlinx.parcelize.RawValue - -class DialogFragmentTemplate : DialogFragment() { - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val dialogParams = requireArguments().getParcelable(DIALOG_TEMPLATE_PARAMS) - requireNotNull(dialogParams) { "DialogTemplateParams is null" } - isCancelable = dialogParams.cancelable == true - val builder = dialogParams.materialDialog ?: MaterialAlertDialogBuilder(requireContext()) - return builder.apply { - dialogParams.config(builder, this@DialogFragmentTemplate) - }.create() - } - - override fun onStart() { - super.onStart() - val dialogParams = requireArguments().getParcelable(DIALOG_TEMPLATE_PARAMS) - if (dialogParams?.isDeleteDialog == true) { - (dialog as AlertDialog).getButton(DialogInterface.BUTTON_POSITIVE) - ?.setTextColor(requireContext().getColorCompat(R.color.colorTextDeleteButtonDialog)) - } - } - - override fun onDismiss(dialog: DialogInterface) { - val dialogParams = requireArguments().getParcelable(DIALOG_TEMPLATE_PARAMS) - dialogParams?.dismissAction?.let { it() } - super.onDismiss(dialog) - } - - @Parcelize - data class DialogTemplateParams( - val cancelable: Boolean = true, - val isDeleteDialog: Boolean = false, - val dismissAction: () -> Unit = { }, - val materialDialog: @RawValue MaterialAlertDialogBuilder? = null, - val config: MaterialAlertDialogBuilder.(DialogFragment) -> Unit - ) : Parcelable - - companion object { - val TAG: String = DialogFragmentTemplate::class.java.simpleName - private val DIALOG_TEMPLATE_PARAMS = "${TAG}_DIALOG_TEMPLATE_PARAMS" - - fun newInstance(dialogParams: DialogTemplateParams) = DialogFragmentTemplate().apply { - arguments = bundleOf(DIALOG_TEMPLATE_PARAMS to dialogParams) - } - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/DialogFragmentTemplateHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/DialogFragmentTemplateHelper.kt deleted file mode 100644 index 01f4feb2405..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/dialog/DialogFragmentTemplateHelper.kt +++ /dev/null @@ -1,80 +0,0 @@ -package de.rki.coronawarnapp.ui.dialog - -import android.content.DialogInterface -import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.Fragment -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat - -fun Fragment.displayDialog( - cancelable: Boolean = true, - isDeleteDialog: Boolean = false, - onDismissAction: () -> Unit = { }, - dialog: MaterialAlertDialogBuilder? = null, - config: MaterialAlertDialogBuilder.() -> Unit = { } -) { - /* - TODO fix serialization by https://jira-ibs.wbs.net.sap/browse/EXPOSUREAPP-14210 - DialogFragmentTemplate.newInstance( - DialogFragmentTemplate.DialogTemplateParams( - cancelable, - isDeleteDialog, - onDismissAction, - dialog, - config - ) - ).show(childFragmentManager, DialogFragmentTemplate.TAG)*/ - - val alertDialogBuilder = dialog ?: MaterialAlertDialogBuilder(requireContext()) - val alertDialog = alertDialogBuilder.apply { - config() - setCancelable(cancelable) - setOnDismissListener { - onDismissAction() - } - }.create() - alertDialog.show() - - if (isDeleteDialog) { - alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)?.setTextColor( - requireContext().getColorCompat(R.color.colorTextDeleteButtonDialog) - ) - } -} - -fun AppCompatActivity.displayDialog( - cancelable: Boolean = true, - isDeleteDialog: Boolean = false, - onDismissAction: () -> Unit = { }, - dialog: MaterialAlertDialogBuilder? = null, - config: MaterialAlertDialogBuilder.() -> Unit = { } -) { - /* - TODO fix serialization by https://jira-ibs.wbs.net.sap/browse/EXPOSUREAPP-14210 - DialogFragmentTemplate.newInstance( - DialogFragmentTemplate.DialogTemplateParams( - cancelable, - isDeleteDialog, - onDismissAction, - dialog, - config - ) - ).show(supportFragmentManager, DialogFragmentTemplate.TAG)*/ - - val alertDialogBuilder = dialog ?: MaterialAlertDialogBuilder(this) - val alertDialog = alertDialogBuilder.apply { - config() - setCancelable(cancelable) - setOnDismissListener { - onDismissAction() - } - }.create() - alertDialog.show() - - if (isDeleteDialog) { - alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)?.setTextColor( - getColorCompat(R.color.colorTextDeleteButtonDialog) - ) - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/launcher/LauncherActivity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/launcher/LauncherActivity.kt index 648af0b7deb..8780cb55b9b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/launcher/LauncherActivity.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/launcher/LauncherActivity.kt @@ -61,13 +61,11 @@ class LauncherActivity : AppCompatActivity() { viewModel.onResult(requestCode, resultCode) } - private fun showUpdateNeededDialog() { - displayDialog(cancelable = false) { - setTitle(R.string.update_dialog_title) - setMessage(R.string.update_dialog_message) - setCancelable(false) - setPositiveButton(R.string.update_dialog_button) { _, _ -> viewModel.requestUpdate() } - } + private fun showUpdateNeededDialog() = displayDialog { + title(R.string.update_dialog_title) + message(R.string.update_dialog_message) + positiveButton(R.string.update_dialog_button) { viewModel.requestUpdate() } + setCancelable(false) } private fun checkEnvSetup() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt index 3d951e3e20a..01b5cde5370 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt @@ -20,7 +20,6 @@ import dagger.android.DispatchingAndroidInjector import dagger.android.HasAndroidInjector import de.rki.coronawarnapp.NavGraphDirections import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.contactdiary.ui.overview.ContactDiaryOverviewFragmentDirections import de.rki.coronawarnapp.coronatest.type.BaseCoronaTest import de.rki.coronawarnapp.databinding.ActivityMainBinding @@ -165,7 +164,7 @@ class MainActivity : AppCompatActivity(), HasAndroidInjector { is MainActivityEvent.GoToCheckInsFragment -> navController.navigate( CheckInsFragment.createDeepLink(event.uriString) ) - is MainActivityEvent.Error -> displayDialog(dialog = event.error.toErrorDialogBuilder(baseContext)) + is MainActivityEvent.Error -> displayDialog { setError(event.error) } is MainActivityEvent.OpenScanner -> navigateToScanner() } } @@ -189,13 +188,12 @@ class MainActivity : AppCompatActivity(), HasAndroidInjector { ) }?.let { navController.navigate(it) } - private fun showRestoreCoronaTestConfirmation(recycledCoronaTest: BaseCoronaTest) = - displayDialog(cancelable = false) { - setTitle(R.string.recycle_bin_restore_corona_test_dialog_title) - setCancelable(false) - setMessage(R.string.recycle_bin_restore_corona_test_dialog_message) - setPositiveButton(android.R.string.ok) { _, _ -> viewModel.restoreCoronaTest(recycledCoronaTest) } - } + private fun showRestoreCoronaTestConfirmation(recycledCoronaTest: BaseCoronaTest) = displayDialog { + title(R.string.recycle_bin_restore_corona_test_dialog_title) + message(R.string.recycle_bin_restore_corona_test_dialog_message) + positiveButton(android.R.string.ok) { viewModel.restoreCoronaTest(recycledCoronaTest) } + setCancelable(false) + } private fun handCoronaTestRestoreEvent(event: CoronaTestRestoreEvent) = when (event) { is CoronaTestRestoreEvent.RestoreDuplicateTest -> NavGraphDirections.actionToSubmissionDeletionWarningFragment( @@ -321,45 +319,42 @@ class MainActivity : AppCompatActivity(), HasAndroidInjector { dataDonationAnalyticsScheduler.initialize() } - private fun showEnergyOptimizedEnabledForBackground() { - displayDialog(cancelable = false) { - setTitle(R.string.onboarding_energy_optimized_dialog_headline) - setMessage(R.string.onboarding_energy_optimized_dialog_body) - setPositiveButton(R.string.onboarding_energy_optimized_dialog_button_positive) { _, _ -> - startActivitySafely( - powerManagement.toBatteryOptimizationSettingsIntent - ) - } - setNegativeButton(R.string.onboarding_energy_optimized_dialog_button_negative) { _, _ -> - showManualCheckingRequiredDialog() - } + private fun showEnergyOptimizedEnabledForBackground() = displayDialog { + title(R.string.onboarding_energy_optimized_dialog_headline) + message(R.string.onboarding_energy_optimized_dialog_body) + positiveButton(R.string.onboarding_energy_optimized_dialog_button_positive) { + startActivitySafely( + powerManagement.toBatteryOptimizationSettingsIntent + ) } + negativeButton(R.string.onboarding_energy_optimized_dialog_button_negative) { + showManualCheckingRequiredDialog() + } + setCancelable(false) } - private fun showManualCheckingRequiredDialog() { - displayDialog(cancelable = false) { - setTitle(R.string.onboarding_manual_required_dialog_headline) - setMessage(R.string.onboarding_manual_required_dialog_body) - setPositiveButton(R.string.onboarding_manual_required_dialog_button) { _, _ -> } - } + private fun showManualCheckingRequiredDialog() = displayDialog { + title(R.string.onboarding_manual_required_dialog_headline) + message(R.string.onboarding_manual_required_dialog_body) + positiveButton(R.string.onboarding_manual_required_dialog_button) + setCancelable(false) } - private fun showBackgroundJobDisabledNotification() { - displayDialog(cancelable = false) { - setTitle(R.string.onboarding_background_fetch_dialog_headline) - setMessage(R.string.onboarding_background_fetch_dialog_body) - setPositiveButton(R.string.onboarding_background_fetch_dialog_button_positive) { _, _ -> - val intent = Intent( - Settings.ACTION_APPLICATION_DETAILS_SETTINGS, - Uri.fromParts("package", packageName, null) - ) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - startActivity(intent) - // show battery optimization system dialog after background processing dialog - viewModel.onUserOpenedBackgroundPriorityOptions() - } - setNegativeButton(R.string.onboarding_background_fetch_dialog_button_negative) { _, _ -> } + private fun showBackgroundJobDisabledNotification() = displayDialog { + title(R.string.onboarding_background_fetch_dialog_headline) + message(R.string.onboarding_background_fetch_dialog_body) + positiveButton(R.string.onboarding_background_fetch_dialog_button_positive) { + val intent = Intent( + Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Uri.fromParts("package", packageName, null) + ) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + startActivity(intent) + // show battery optimization system dialog after background processing dialog + viewModel.onUserOpenedBackgroundPriorityOptions() } + negativeButton(R.string.onboarding_background_fetch_dialog_button_negative) + setCancelable(false) } private fun navigateToScanner() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt index 2b1d5c8fab5..788afeb6c6a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt @@ -16,7 +16,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.appbar.MaterialToolbar import de.rki.coronawarnapp.NavGraphDirections import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.coronatest.type.BaseCoronaTest import de.rki.coronawarnapp.databinding.HomeFragmentLayoutBinding import de.rki.coronawarnapp.reyclebin.ui.dialog.recycleTestDialog @@ -91,30 +90,27 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject { viewModel.showPopUps() viewModel.events.observe2(this) { event -> navigate(event) } viewModel.homeItems.observe2(this) { homeAdapter.update(it) } - viewModel.errorEvent.observe2(this) { - displayDialog(dialog = it.toErrorDialogBuilder(requireContext())) - } + viewModel.errorEvent.observe2(this) { displayDialog { setError(it) } } viewModel.tracingHeaderState.observe2(this) { binding.tracingHeader = it } viewModel.showIncorrectDeviceTimeDialog.observe2(this) { showDialog -> if (showDialog) displayDialog { - setTitle(R.string.device_time_incorrect_dialog_headline) - setMessage(R.string.device_time_incorrect_dialog_body) - setPositiveButton(R.string.device_time_incorrect_dialog_button_confirm) { _, _ -> + title(R.string.device_time_incorrect_dialog_headline) + message(R.string.device_time_incorrect_dialog_body) + positiveButton(R.string.device_time_incorrect_dialog_button_confirm) { viewModel.userHasAcknowledgedIncorrectDeviceTime() } } } viewModel.coronaTestErrors.observe2(this) { tests -> tests.forEach { test -> - displayDialog( - dialog = test.lastError?.toErrorDialogBuilder(requireContext())?.apply { - val testName = when (test.type) { - BaseCoronaTest.Type.PCR -> R.string.ag_homescreen_card_pcr_title - BaseCoronaTest.Type.RAPID_ANTIGEN -> R.string.ag_homescreen_card_rapidtest_title - } - setTitle(getString(testName) + " " + getString(R.string.errors_generic_headline_short)) + displayDialog { + val testName = when (test.type) { + BaseCoronaTest.Type.PCR -> R.string.ag_homescreen_card_pcr_title + BaseCoronaTest.Type.RAPID_ANTIGEN -> R.string.ag_homescreen_card_rapidtest_title } - ) + title(getString(testName) + " " + getString(R.string.errors_generic_headline_short)) + setError(test.lastError) + } } } @@ -175,37 +171,41 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject { } } - private fun showRiskLevelLoweredDialog(maxEncounterAgeInDays: Long) = displayDialog(cancelable = false) { - setTitle(R.string.risk_lowered_dialog_headline) - setMessage(getString(R.string.risk_lowered_dialog_body, maxEncounterAgeInDays)) - setPositiveButton(R.string.risk_lowered_dialog_button_confirm) { _, _ -> + private fun showRiskLevelLoweredDialog(maxEncounterAgeInDays: Long) = displayDialog { + title(R.string.risk_lowered_dialog_headline) + message(getString(R.string.risk_lowered_dialog_body, maxEncounterAgeInDays)) + positiveButton(R.string.risk_lowered_dialog_button_confirm) { viewModel.userHasAcknowledgedTheLoweredRiskLevel() } + setCancelable(false) } - private fun showAdditionalHighRiskLevelDialog(maxEncounterAgeInDays: Long) = displayDialog(cancelable = false) { - setTitle(R.string.additional_high_risk_dialog_headline) - setMessage(getString(R.string.additional_high_risk_dialog_body, maxEncounterAgeInDays)) - setPositiveButton(R.string.additional_high_risk_dialog_button_confirm) { _, _ -> + private fun showAdditionalHighRiskLevelDialog(maxEncounterAgeInDays: Long) = displayDialog { + title(R.string.additional_high_risk_dialog_headline) + message(getString(R.string.additional_high_risk_dialog_body, maxEncounterAgeInDays)) + positiveButton(R.string.additional_high_risk_dialog_button_confirm) { viewModel.userHasAcknowledgedAdditionalHighRiskLevel() } + setCancelable(false) } - private fun showErrorResetDialog() = displayDialog(cancelable = false) { - setTitle(R.string.errors_generic_headline) - setMessage(R.string.errors_generic_text_catastrophic_error_recovery_via_reset) - setPositiveButton(R.string.errors_generic_button_positive) { _, _ -> viewModel.errorResetDialogDismissed() } - setNeutralButton(R.string.errors_generic_button_negative) { _, _ -> - openUrl(context.getString(R.string.errors_generic_text_catastrophic_error_encryption_failure)) + private fun showErrorResetDialog() = displayDialog { + title(R.string.errors_generic_headline) + message(R.string.errors_generic_text_catastrophic_error_recovery_via_reset) + positiveButton(R.string.errors_generic_button_positive) { viewModel.errorResetDialogDismissed() } + neutralButton(R.string.errors_generic_button_negative) { + openUrl(getString(R.string.errors_generic_text_catastrophic_error_encryption_failure)) } + setCancelable(false) } - private fun showTracingExplanationDialog(maxEncounterAgeInDays: Long) = displayDialog(cancelable = false) { - setTitle(R.string.risk_details_explanation_dialog_title) - setMessage(getString(R.string.tracing_explanation_dialog_message, maxEncounterAgeInDays)) - setPositiveButton(R.string.errors_generic_button_positive) { _, _ -> + private fun showTracingExplanationDialog(maxEncounterAgeInDays: Long) = displayDialog { + title(R.string.risk_details_explanation_dialog_title) + message(getString(R.string.tracing_explanation_dialog_message, maxEncounterAgeInDays)) + positiveButton(R.string.errors_generic_button_positive) { viewModel.tracingExplanationWasShown() } + setCancelable(false) } private fun navigate(event: HomeFragmentEvents) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragment.kt index 504f05a56f6..3fddb12be55 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragment.kt @@ -7,7 +7,6 @@ import android.view.accessibility.AccessibilityEvent import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentOnboardingTracingBinding import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject @@ -44,13 +43,13 @@ class OnboardingTracingFragment : Fragment(R.layout.fragment_onboarding_tracing) is OnboardingNavigationEvents.NavigateToOnboardingTest -> navigateToOnboardingTestFragment() is OnboardingNavigationEvents.ShowCancelDialog -> displayDialog { - setTitle(R.string.onboarding_tracing_dialog_headline) - setMessage(R.string.onboarding_tracing_dialog_body) - setPositiveButton(R.string.onboarding_tracing_dialog_button_positive) { _, _ -> + title(R.string.onboarding_tracing_dialog_headline) + message(R.string.onboarding_tracing_dialog_body) + positiveButton(R.string.onboarding_tracing_dialog_button_positive) { vm.disableTracingIfEnabled() navigateToOnboardingTestFragment() } - setNegativeButton(R.string.onboarding_tracing_dialog_button_negative) { _, _ -> } + negativeButton(R.string.onboarding_tracing_dialog_button_negative) } is OnboardingNavigationEvents.NavigateToOnboardingPrivacy -> popBackStack() @@ -61,9 +60,7 @@ class OnboardingTracingFragment : Fragment(R.layout.fragment_onboarding_tracing) vm.permissionRequestEvent.observe2(this) { permissionRequest -> permissionRequest.invoke(requireActivity()) } - vm.ensErrorEvents.observe2(this) { error -> - error.toErrorDialogBuilder(requireContext()).show() - } + vm.ensErrorEvents.observe2(this) { error -> displayDialog { setError(error) } } } override fun onResume() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/attendee/checkins/CheckInsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/attendee/checkins/CheckInsFragment.kt index 2d79e274164..6673f24ae9d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/attendee/checkins/CheckInsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/attendee/checkins/CheckInsFragment.kt @@ -13,7 +13,6 @@ import androidx.navigation.fragment.navArgs import androidx.navigation.navGraphViewModels import androidx.recyclerview.widget.DefaultItemAnimator import com.google.android.material.appbar.MaterialToolbar -import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.transition.Hold import com.google.android.material.transition.MaterialSharedAxis import de.rki.coronawarnapp.R @@ -127,13 +126,11 @@ class CheckInsFragment : Fragment(R.layout.trace_location_attendee_checkins_frag private fun showInvalidQrCodeInformation(lazyErrorText: LazyString) { val errorText = lazyErrorText.get(requireContext()) - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.trace_location_attendee_invalid_qr_code_dialog_title) - .setMessage(getString(R.string.trace_location_attendee_invalid_qr_code_dialog_message, errorText)) - .setPositiveButton(R.string.trace_location_attendee_invalid_qr_code_dialog_positive_button) { _, _ -> - // NO-OP - } - .show() + displayDialog { + title(R.string.trace_location_attendee_invalid_qr_code_dialog_title) + message(getString(R.string.trace_location_attendee_invalid_qr_code_dialog_message, errorText)) + positiveButton(R.string.trace_location_attendee_invalid_qr_code_dialog_positive_button) + } } private fun updateViews(items: List) { @@ -163,21 +160,19 @@ class CheckInsFragment : Fragment(R.layout.trace_location_attendee_checkins_frag } } - private fun showRemovalConfirmation(checkIn: CheckIn?, position: Int?) = - displayDialog( - isDeleteDialog = true, - onDismissAction = { position?.let { checkInsAdapter.notifyItemChanged(position) } } - ) { - setTitle( - if (checkIn == null) - R.string.trace_location_checkins_remove_all_title - else - R.string.trace_location_checkins_remove_single_title - ) - setMessage(R.string.trace_location_checkins_remove_message) - setPositiveButton(R.string.generic_action_remove) { _, _ -> viewModel.onRemoveCheckInConfirmed(checkIn) } - setNegativeButton(R.string.generic_action_abort) { _, _ -> } - } + private fun showRemovalConfirmation(checkIn: CheckIn?, position: Int?) = displayDialog { + title( + if (checkIn == null) + R.string.trace_location_checkins_remove_all_title + else + R.string.trace_location_checkins_remove_single_title + ) + message(R.string.trace_location_checkins_remove_message) + positiveButton(R.string.generic_action_remove) { viewModel.onRemoveCheckInConfirmed(checkIn) } + negativeButton(R.string.generic_action_abort) + dismissAction { position?.let { checkInsAdapter.notifyItemChanged(position) } } + setDeleteDialog(true) + } private fun setupMenu(toolbar: MaterialToolbar) = toolbar.apply { toolbar.addMenuId(R.id.checkins_fragment_menu_id) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/attendee/checkins/consent/CheckInsConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/attendee/checkins/consent/CheckInsConsentFragment.kt index cde9dd610b7..0534bdd2528 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/attendee/checkins/consent/CheckInsConsentFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/attendee/checkins/consent/CheckInsConsentFragment.kt @@ -6,10 +6,9 @@ import androidx.activity.OnBackPressedCallback import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import com.google.android.material.dialog.MaterialAlertDialogBuilder import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.CheckInsConsentFragmentBinding -import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.diffutil.update import de.rki.coronawarnapp.util.ui.viewBinding @@ -86,32 +85,25 @@ class CheckInsConsentFragment : Fragment(R.layout.check_ins_consent_fragment), A viewModel.setAutoSubmission() } - private fun showSkipDialog() { - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.trace_location_attendee_consent_dialog_title) - .setMessage(R.string.trace_location_attendee_consent_dialog_message) - .setPositiveButton(R.string.trace_location_attendee_consent_dialog_positive_button) { _, _ -> - Timber.d("showSkipDialog:Stay on CheckInsConsentFragment") - } - .setNegativeButton(R.string.trace_location_attendee_consent_dialog_negative_button) { _, _ -> - viewModel.doNotShareCheckIns() - } - .show() + private fun showSkipDialog() = displayDialog { + title(R.string.trace_location_attendee_consent_dialog_title) + message(R.string.trace_location_attendee_consent_dialog_message) + positiveButton(R.string.trace_location_attendee_consent_dialog_positive_button) { + Timber.d("showSkipDialog:Stay on CheckInsConsentFragment") + } + negativeButton(R.string.trace_location_attendee_consent_dialog_negative_button) { + viewModel.doNotShareCheckIns() + } } - private fun showCloseDialog() { - val closeDialogInstance = DialogHelper.DialogInstance( - context = requireActivity(), - title = R.string.submission_test_result_available_close_dialog_title_consent_given, - message = R.string.submission_test_result_available_close_dialog_body_consent_given, - positiveButton = R.string.submission_test_result_available_close_dialog_continue_button, - negativeButton = R.string.submission_test_result_available_close_dialog_cancel_button, - cancelable = true, - positiveButtonFunction = { - Timber.d("showCloseDialog:Stay on CheckInsConsentFragment") - }, - negativeButtonFunction = { viewModel.onCancelConfirmed() } - ) - DialogHelper.showDialog(closeDialogInstance) + private fun showCloseDialog() = displayDialog { + title(R.string.submission_test_result_available_close_dialog_title_consent_given) + message(R.string.submission_test_result_available_close_dialog_body_consent_given) + positiveButton(R.string.submission_test_result_available_close_dialog_continue_button) { + Timber.d("showCloseDialog:Stay on CheckInsConsentFragment") + } + negativeButton(R.string.submission_test_result_available_close_dialog_cancel_button) { + viewModel.onCancelConfirmed() + } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/create/TraceLocationCreateFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/create/TraceLocationCreateFragment.kt index 5e1ff8fa270..ad212a38ede 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/create/TraceLocationCreateFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/create/TraceLocationCreateFragment.kt @@ -19,9 +19,9 @@ import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.util.getLocale import de.rki.coronawarnapp.contactdiary.util.hideKeyboard import de.rki.coronawarnapp.databinding.TraceLocationCreateFragmentBinding +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.ui.durationpicker.DurationPicker import de.rki.coronawarnapp.ui.durationpicker.format -import de.rki.coronawarnapp.util.DialogHelper import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.addSubtitleId import de.rki.coronawarnapp.util.ui.addTitleId @@ -68,7 +68,7 @@ class TraceLocationCreateFragment : Fragment(R.layout.trace_location_create_frag viewModel.result.observe(viewLifecycleOwner) { result -> when (result) { is TraceLocationCreateViewModel.Result.Error -> { - DialogHelper.showDialog(getErrorDialogInstance(result.exception)) + showErrorDialog(result.exception) } is TraceLocationCreateViewModel.Result.Success -> { findNavController().navigate( @@ -141,26 +141,17 @@ class TraceLocationCreateFragment : Fragment(R.layout.trace_location_create_frag } } - private fun getErrorDialogInstance(exception: Exception): DialogHelper.DialogInstance { - return DialogHelper.DialogInstance( - requireActivity(), - R.string.tracelocation_generic_error_title, - R.string.tracelocation_generic_qr_code_error_body, - R.string.errors_generic_button_positive, - R.string.errors_generic_button_negative, - negativeButtonFunction = { showExceptionDetails(exception) } - ) + private fun showErrorDialog(exception: Exception) = displayDialog { + title(R.string.tracelocation_generic_error_title) + message(R.string.tracelocation_generic_qr_code_error_body) + positiveButton(R.string.errors_generic_button_positive) + negativeButton(R.string.errors_generic_button_negative) { showExceptionDetails(exception) } } - private fun showExceptionDetails(exception: Exception) { - DialogHelper.showDialog( - DialogHelper.DialogInstance( - requireActivity(), - R.string.errors_generic_headline, - exception.toString(), - R.string.errors_generic_button_positive - ) - ) + private fun showExceptionDetails(exception: Exception) = displayDialog { + title(R.string.errors_generic_headline) + message(exception.toString()) + positiveButton(R.string.errors_generic_button_positive) } private fun showDatePicker( diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/list/TraceLocationsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/list/TraceLocationsFragment.kt index a46c8fcdbac..57595555f8b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/list/TraceLocationsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/list/TraceLocationsFragment.kt @@ -14,10 +14,10 @@ import com.google.android.material.transition.MaterialSharedAxis import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.TraceLocationOrganizerTraceLocationsListFragmentBinding import de.rki.coronawarnapp.presencetracing.checkins.qrcode.TraceLocation +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.ui.presencetracing.attendee.checkins.CheckInsFragment import de.rki.coronawarnapp.ui.presencetracing.organizer.category.adapter.category.traceLocationCategories import de.rki.coronawarnapp.ui.presencetracing.organizer.details.QrCodeDetailFragmentArgs -import de.rki.coronawarnapp.util.DialogHelper import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.list.setupSwipe import de.rki.coronawarnapp.util.lists.decorations.TopBottomPaddingDecorator @@ -179,19 +179,14 @@ class TraceLocationsFragment : Fragment(R.layout.trace_location_organizer_trace_ } } - private fun showDeleteAllDialog() { - val deleteAllDialog = DialogHelper.DialogInstance( - requireActivity(), - R.string.trace_location_organiser_list_delete_all_popup_title, - R.string.trace_location_organiser_list_delete_all_popup_message, - R.string.trace_location_organiser_list_delete_all_popup_positive_button, - R.string.trace_location_organiser_list_delete_all_popup_negative_button, - positiveButtonFunction = { - viewModel.deleteAllTraceLocations() - }, - isDeleteDialog = true - ) - DialogHelper.showDialog(deleteAllDialog) + private fun showDeleteAllDialog() = displayDialog { + title(R.string.trace_location_organiser_list_delete_all_popup_title) + message(R.string.trace_location_organiser_list_delete_all_popup_message) + positiveButton(R.string.trace_location_organiser_list_delete_all_popup_positive_button) { + viewModel.deleteAllTraceLocations() + } + negativeButton(R.string.trace_location_organiser_list_delete_all_popup_negative_button) + setDeleteDialog(true) } private fun openCreateEventFragment(traceLocation: TraceLocation) { @@ -208,20 +203,18 @@ class TraceLocationsFragment : Fragment(R.layout.trace_location_organizer_trace_ } } - private fun showDeleteSingleDialog(traceLocation: TraceLocation, position: Int?) = - DialogHelper.showDialog( - DialogHelper.DialogInstance( - requireActivity(), - R.string.trace_location_organiser_list_delete_single_popup_title, - R.string.trace_location_organiser_list_delete_single_popup_message, - R.string.trace_location_organiser_list_delete_all_popup_positive_button, - R.string.trace_location_organiser_list_delete_all_popup_negative_button, - positiveButtonFunction = { viewModel.deleteSingleTraceLocation(traceLocation) }, - negativeButtonFunction = { position?.let { traceLocationsAdapter.notifyItemChanged(position) } }, - cancelFunction = { position?.let { traceLocationsAdapter.notifyItemChanged(position) } }, - isDeleteDialog = true - ) - ) + private fun showDeleteSingleDialog(traceLocation: TraceLocation, position: Int?) = displayDialog { + title(R.string.trace_location_organiser_list_delete_single_popup_title) + message(R.string.trace_location_organiser_list_delete_single_popup_message) + positiveButton(R.string.trace_location_organiser_list_delete_all_popup_positive_button) { + viewModel.deleteSingleTraceLocation(traceLocation) + } + negativeButton(R.string.trace_location_organiser_list_delete_all_popup_negative_button) { + position?.let { traceLocationsAdapter.notifyItemChanged(it) } + } + dismissAction { position?.let { traceLocationsAdapter.notifyItemChanged(it) } } + setDeleteDialog(true) + } private fun onScrollChange(extend: Boolean) = with(binding.qrCodeFab) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/warn/qrcode/OrganizerWarnQrCodeScannerFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/warn/qrcode/OrganizerWarnQrCodeScannerFragment.kt index f2015fc5693..ec4fff0d8d4 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/warn/qrcode/OrganizerWarnQrCodeScannerFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/warn/qrcode/OrganizerWarnQrCodeScannerFragment.kt @@ -9,11 +9,10 @@ import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController -import com.google.android.material.dialog.MaterialAlertDialogBuilder import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentQrcodeScannerBinding import de.rki.coronawarnapp.tag +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.ExternalActionHelper.openAppDetailsSettings import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.permission.CameraPermissionHelper @@ -80,8 +79,7 @@ class OrganizerWarnQrCodeScannerFragment : Fragment(R.layout.fragment_qrcode_sca ) ) } - is OrganizerWarnQrCodeNavigation.Error -> - navEvent.exception.toErrorDialogBuilder(requireContext()).show() + is OrganizerWarnQrCodeNavigation.Error -> displayDialog { setError(navEvent.exception) } OrganizerWarnQrCodeNavigation.InProgress -> Unit } } @@ -109,42 +107,36 @@ class OrganizerWarnQrCodeScannerFragment : Fragment(R.layout.fragment_qrcode_sca } private fun showCameraPermissionDeniedDialog() { - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.camera_permission_dialog_title) - .setMessage(R.string.camera_permission_dialog_message) - .setNegativeButton(R.string.camera_permission_dialog_settings) { _, _ -> + displayDialog { + title(R.string.camera_permission_dialog_title) + message(R.string.camera_permission_dialog_message) + negativeButton(R.string.camera_permission_dialog_settings) { showsPermissionDialog = false requireContext().openAppDetailsSettings() } - .setPositiveButton(android.R.string.ok) { _, _ -> leave() } - .show() + positiveButton(android.R.string.ok) { leave() } + } showsPermissionDialog = true } private fun showCameraPermissionRationaleDialog() { - MaterialAlertDialogBuilder(requireContext()).apply { - setTitle(R.string.camera_permission_rationale_dialog_headline) - setMessage(R.string.camera_permission_rationale_dialog_body) - setPositiveButton(R.string.camera_permission_rationale_dialog_button_positive) { _, _ -> + displayDialog { + title(R.string.camera_permission_rationale_dialog_headline) + message(R.string.camera_permission_rationale_dialog_body) + positiveButton(R.string.camera_permission_rationale_dialog_button_positive) { showsPermissionDialog = false requestCameraPermission() } - setNegativeButton(R.string.camera_permission_rationale_dialog_button_negative) { _, _ -> - leave() - } - }.show() + negativeButton(R.string.camera_permission_rationale_dialog_button_negative) { leave() } + } showsPermissionDialog = true } - private fun showInvalidQrCodeInformation(lazyErrorText: LazyString) { - MaterialAlertDialogBuilder(requireContext()).apply { - val errorText = lazyErrorText.get(context) - setTitle(R.string.trace_location_attendee_invalid_qr_code_dialog_title) - setMessage(getString(R.string.trace_location_attendee_invalid_qr_code_dialog_message, errorText)) - setPositiveButton(R.string.trace_location_attendee_invalid_qr_code_dialog_positive_button) { _, _ -> - startDecode() - } - }.show() + private fun showInvalidQrCodeInformation(lazyErrorText: LazyString) = displayDialog { + val errorText = lazyErrorText.get(requireContext()) + title(R.string.trace_location_attendee_invalid_qr_code_dialog_title) + message(getString(R.string.trace_location_attendee_invalid_qr_code_dialog_message, errorText)) + positiveButton(R.string.trace_location_attendee_invalid_qr_code_dialog_positive_button) { startDecode() } } private fun requestCameraPermission() = requestPermissionLauncher.launch(Manifest.permission.CAMERA) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/warn/tan/TraceLocationWarnTanFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/warn/tan/TraceLocationWarnTanFragment.kt index acfd9d804f7..1116e96a8be 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/warn/tan/TraceLocationWarnTanFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/presencetracing/organizer/warn/tan/TraceLocationWarnTanFragment.kt @@ -8,9 +8,9 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.contactdiary.util.hideKeyboard import de.rki.coronawarnapp.databinding.TraceLocationOrganizerWarnTanFragmentBinding +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.addTitleId @@ -77,9 +77,7 @@ class TraceLocationWarnTanFragment : Fragment(R.layout.trace_location_organizer_ } } - viewModel.registrationError.observe2(this) { - it.toErrorDialogBuilder(requireContext()).show() - } + viewModel.registrationError.observe2(this) { displayDialog { setError(it) } } } override fun onResume() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetFragment.kt index 9f0af6fd3e3..e717b9a0d8a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetFragment.kt @@ -6,8 +6,8 @@ import android.view.accessibility.AccessibilityEvent import androidx.fragment.app.Fragment import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentSettingsResetBinding +import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.ui.onboarding.OnboardingActivity -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 @@ -35,7 +35,7 @@ class SettingsResetFragment : Fragment(R.layout.fragment_settings_reset), AutoIn } vm.clickEvent.observe2(this) { when (it) { - is SettingsEvents.ResetApp -> confirmReset() + is SettingsEvents.ResetApp -> showConfirmResetDialog() is SettingsEvents.GoBack -> popBackStack() is SettingsEvents.GoToOnboarding -> navigateToOnboarding() } @@ -52,18 +52,11 @@ class SettingsResetFragment : Fragment(R.layout.fragment_settings_reset), AutoIn activity?.finish() } - private fun confirmReset() { - val resetDialog = DialogHelper.DialogInstance( - requireActivity(), - R.string.settings_reset_dialog_headline, - R.string.settings_reset_dialog_body, - R.string.settings_reset_dialog_button_confirm, - R.string.settings_reset_dialog_button_cancel, - cancelable = true, - positiveButtonFunction = vm::deleteAllAppContent, - isDeleteDialog = true - ) - - DialogHelper.showDialog(resetDialog) + private fun showConfirmResetDialog() = displayDialog { + title(R.string.settings_reset_dialog_headline) + message(R.string.settings_reset_dialog_body) + positiveButton(R.string.settings_reset_dialog_button_confirm) { vm.deleteAllAppContent() } + negativeButton(R.string.settings_reset_dialog_button_cancel) + setDeleteDialog(true) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionCancelDialog.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionCancelDialog.kt index 60cf912bc9a..ad7bc605a56 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionCancelDialog.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionCancelDialog.kt @@ -5,10 +5,8 @@ import de.rki.coronawarnapp.R import de.rki.coronawarnapp.ui.dialog.displayDialog fun Fragment.submissionCancelDialog(cancelFunction: () -> Unit) = displayDialog { - setTitle(R.string.submission_error_dialog_confirm_cancellation_title) - setMessage(R.string.submission_error_dialog_confirm_cancellation_body) - setPositiveButton(R.string.submission_error_dialog_confirm_cancellation_button_positive) { _, _ -> - cancelFunction() - } - setNegativeButton(R.string.submission_error_dialog_confirm_cancellation_button_negative) { _, _ -> } + title(R.string.submission_error_dialog_confirm_cancellation_title) + message(R.string.submission_error_dialog_confirm_cancellation_body) + positiveButton(R.string.submission_error_dialog_confirm_cancellation_button_positive) { cancelFunction() } + negativeButton(R.string.submission_error_dialog_confirm_cancellation_button_negative) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/covidcertificate/RequestCovidCertificateFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/covidcertificate/RequestCovidCertificateFragment.kt index 63289ac9046..2a4aa5db806 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/covidcertificate/RequestCovidCertificateFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/covidcertificate/RequestCovidCertificateFragment.kt @@ -87,9 +87,7 @@ class RequestCovidCertificateFragment : Fragment(R.layout.fragment_request_covid State.Working -> { // Handled above } - is State.Error -> displayDialog(dialog = state.getDialogBuilder(requireContext())) { - setPositiveButton(android.R.string.ok) { _, _ -> popBackStack() } - } + is State.Error -> state.showExceptionDialog(this) { popBackStack() } is State.TestRegistered -> when { state.test.isPositive -> if (state.test is FamilyCoronaTest) { @@ -116,16 +114,15 @@ class RequestCovidCertificateFragment : Fragment(R.layout.fragment_request_covid } private fun showCloseDialog() = displayDialog { - setTitle(R.string.request_gc_dialog_title) - setMessage(R.string.request_gc_dialog_message) - setPositiveButton(R.string.request_gc_dialog_positive_button) { _, _ -> - if (args.comesFromDispatcherFragment) { - findNavController().navigate( - RequestCovidCertificateFragmentDirections.actionRequestCovidCertificateFragmentToHomeFragment() - ) - } else popBackStack() - } - setNegativeButton(R.string.request_gc_dialog_negative_button) { _, _ -> } + title(R.string.request_gc_dialog_title) + message(R.string.request_gc_dialog_message) + positiveButton(R.string.request_gc_dialog_positive_button) + if (args.comesFromDispatcherFragment) { + findNavController().navigate( + RequestCovidCertificateFragmentDirections.actionRequestCovidCertificateFragmentToHomeFragment() + ) + } else popBackStack() + negativeButton(R.string.request_gc_dialog_negative_button) } private fun openDatePicker() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragment.kt index 1c6309d99b8..b94173ee46a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/deletionwarning/SubmissionDeletionWarningFragment.kt @@ -14,7 +14,6 @@ import de.rki.coronawarnapp.coronatest.type.BaseCoronaTest import de.rki.coronawarnapp.coronatest.type.TestIdentifier import de.rki.coronawarnapp.databinding.FragmentSubmissionDeletionWarningBinding import de.rki.coronawarnapp.submission.TestRegistrationStateProcessor.State -import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.popBackStack @@ -79,12 +78,10 @@ class SubmissionDeletionWarningFragment : Fragment(R.layout.fragment_submission_ State.Working -> { // Handled above } - is State.Error -> displayDialog( - dialog = state.getDialogBuilder( - requireContext(), - args.testRegistrationRequest is CoronaTestTAN - ) - ) + is State.Error -> state.showExceptionDialog( + fragment = this, + comingFromTan = args.testRegistrationRequest is CoronaTestTAN + ) { popBackStack() } is State.TestRegistered -> when { state.test.isPositive -> sortNavigation(state.test.identifier) else -> findNavController().navigate( diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentFragment.kt index 0369bf1764a..2df56ccb752 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentFragment.kt @@ -110,9 +110,7 @@ class SubmissionConsentFragment : Fragment(R.layout.fragment_submission_consent) State.Working -> { // Handled above } - is State.Error -> displayDialog(dialog = state.getDialogBuilder(requireContext())) { - setPositiveButton(android.R.string.ok) { _, _ -> popBackStack() } - } + is State.Error -> state.showExceptionDialog(this) { popBackStack() } is State.TestRegistered -> when { state.test.isPositive -> NavGraphDirections.actionToSubmissionTestResultAvailableFragment( @@ -144,10 +142,10 @@ class SubmissionConsentFragment : Fragment(R.layout.fragment_submission_consent) } private fun showInvalidQrCodeDialog() = displayDialog { - setTitle(R.string.submission_qr_code_scan_invalid_dialog_headline) - setMessage(R.string.submission_qr_code_scan_invalid_dialog_body) - setPositiveButton(R.string.submission_qr_code_scan_invalid_dialog_button_positive) { _, _ -> } - setNegativeButton(R.string.submission_qr_code_scan_invalid_dialog_button_negative) { _, _ -> popBackStack() } + title(R.string.submission_qr_code_scan_invalid_dialog_headline) + message(R.string.submission_qr_code_scan_invalid_dialog_body) + positiveButton(R.string.submission_qr_code_scan_invalid_dialog_button_positive) + negativeButton(R.string.submission_qr_code_scan_invalid_dialog_button_negative) { popBackStack() } } companion object { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableFragment.kt index bfca707b1bf..b140eafdfef 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableFragment.kt @@ -105,10 +105,10 @@ class SubmissionTestResultAvailableFragment : Fragment(R.layout.fragment_submiss } private fun showCloseDialog() = displayDialog { - setTitle(R.string.submission_test_result_available_close_dialog_title_consent_given) - setMessage(R.string.submission_test_result_available_close_dialog_body_consent_given) - setPositiveButton(R.string.submission_test_result_available_close_dialog_continue_button) { _, _ -> } - setNegativeButton(R.string.submission_test_result_available_close_dialog_cancel_button) { _, _ -> + title(R.string.submission_test_result_available_close_dialog_title_consent_given) + message(R.string.submission_test_result_available_close_dialog_body_consent_given) + positiveButton(R.string.submission_test_result_available_close_dialog_continue_button) + negativeButton(R.string.submission_test_result_available_close_dialog_cancel_button) { returnToScreenWhereUQSWasOpened() } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/tan/SubmissionTanFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/tan/SubmissionTanFragment.kt index 96fb29c03af..5af0fd5517e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/tan/SubmissionTanFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/tan/SubmissionTanFragment.kt @@ -124,23 +124,19 @@ class SubmissionTanFragment : Fragment(R.layout.fragment_submission_tan), AutoIn private fun buildErrorDialog(exception: CwaWebException) { when (exception) { is BadRequestException -> displayDialog { - setTitle(R.string.submission_error_dialog_web_test_paired_title_tan) - setMessage(R.string.submission_error_dialog_web_test_paired_body_tan) - setNegativeButton(R.string.submission_error_dialog_web_test_paired_button_positive) { _, _ -> goBack() } + title(R.string.submission_error_dialog_web_test_paired_title_tan) + message(R.string.submission_error_dialog_web_test_paired_body_tan) + negativeButton(R.string.submission_error_dialog_web_test_paired_button_positive) { goBack() } } is CwaClientError, is CwaServerError -> displayDialog { - setTitle(R.string.submission_error_dialog_web_generic_error_title) - setMessage(R.string.submission_error_dialog_web_generic_network_error_body) - setNegativeButton(R.string.submission_error_dialog_web_generic_error_button_positive) { _, _ -> - goBack() - } + title(R.string.submission_error_dialog_web_generic_error_title) + message(R.string.submission_error_dialog_web_generic_network_error_body) + negativeButton(R.string.submission_error_dialog_web_generic_error_button_positive) { goBack() } } else -> displayDialog { - setTitle(R.string.submission_error_dialog_web_generic_error_title) - setMessage(R.string.submission_error_dialog_web_generic_error_body) - setNegativeButton(R.string.submission_error_dialog_web_generic_error_button_positive) { _, _ -> - goBack() - } + title(R.string.submission_error_dialog_web_generic_error_title) + message(R.string.submission_error_dialog_web_generic_error_body) + negativeButton(R.string.submission_error_dialog_web_generic_error_button_positive) { goBack() } } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt index 01ad43a5b99..57bab24b293 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/pending/SubmissionTestResultPendingFragment.kt @@ -10,7 +10,6 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.coronatest.type.BaseCoronaTest import de.rki.coronawarnapp.coronatest.type.PersonalCoronaTest import de.rki.coronawarnapp.databinding.FragmentSubmissionTestResultPendingBinding @@ -142,9 +141,9 @@ class SubmissionTestResultPendingFragment : Fragment(R.layout.fragment_submissio viewModel.showRedeemedTokenWarning.observe2(this) { displayDialog { - setTitle(R.string.submission_error_dialog_web_tan_redeemed_title) - setMessage(R.string.submission_error_dialog_web_tan_redeemed_body) - setPositiveButton(R.string.submission_error_dialog_web_tan_redeemed_button_positive) { _, _ -> } + title(R.string.submission_error_dialog_web_tan_redeemed_title) + message(R.string.submission_error_dialog_web_tan_redeemed_body) + positiveButton(R.string.submission_error_dialog_web_tan_redeemed_button_positive) } } @@ -159,9 +158,7 @@ class SubmissionTestResultPendingFragment : Fragment(R.layout.fragment_submissio findNavController().navigate(it) } ?: navigateBackToFlowStart() } - viewModel.errorEvent.observe2(this) { - displayDialog(dialog = it.toErrorDialogBuilder(requireContext())) - } + viewModel.errorEvent.observe2(this) { displayDialog { setError(it) } } } override fun onResume() { @@ -194,18 +191,14 @@ class SubmissionTestResultPendingFragment : Fragment(R.layout.fragment_submissio } private fun showNetworkErrorDialog() = displayDialog { - setTitle(R.string.submission_error_dialog_web_generic_error_title) - setMessage(R.string.submission_error_dialog_web_generic_network_error_body) - setNegativeButton(R.string.submission_error_dialog_web_generic_error_button_positive) { _, _ -> - navigateBackToFlowStart() - } + title(R.string.submission_error_dialog_web_generic_error_title) + message(R.string.submission_error_dialog_web_generic_network_error_body) + negativeButton(R.string.submission_error_dialog_web_generic_error_button_positive) { navigateBackToFlowStart() } } private fun showGenericErrorDialog() = displayDialog { - setTitle(R.string.submission_error_dialog_web_generic_error_title) - setMessage(R.string.submission_error_dialog_web_generic_error_body) - setNegativeButton(R.string.submission_error_dialog_web_generic_error_button_positive) { _, _ -> - navigateBackToFlowStart() - } + title(R.string.submission_error_dialog_web_generic_error_title) + message(R.string.submission_error_dialog_web_generic_error_body) + negativeButton(R.string.submission_error_dialog_web_generic_error_button_positive) { navigateBackToFlowStart() } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultConsentGivenFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultConsentGivenFragment.kt index 39384a93e99..8dd4885582a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultConsentGivenFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultConsentGivenFragment.kt @@ -118,11 +118,11 @@ class SubmissionTestResultConsentGivenFragment : } private fun showCancelDialog() = displayDialog { - setTitle(R.string.submission_error_dialog_confirm_cancellation_title) - setMessage(R.string.submission_error_dialog_confirm_cancellation_body) - setPositiveButton(R.string.submission_error_dialog_confirm_cancellation_button_positive) { _, _ -> + title(R.string.submission_error_dialog_confirm_cancellation_title) + message(R.string.submission_error_dialog_confirm_cancellation_body) + positiveButton(R.string.submission_error_dialog_confirm_cancellation_button_positive) { viewModel.onCancelConfirmed() } - setNegativeButton(R.string.submission_error_dialog_confirm_cancellation_button_negative) { _, _ -> } + negativeButton(R.string.submission_error_dialog_confirm_cancellation_button_negative) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt index d5db8423544..95c4ed9db9d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt @@ -82,12 +82,10 @@ class SubmissionTestResultNoConsentFragment : } private fun showCancelDialog() = displayDialog { - setTitle(R.string.submission_test_result_positive_no_consent_dialog_title) - setMessage(R.string.submission_test_result_positive_no_consent_dialog_message) - setPositiveButton(R.string.submission_test_result_positive_no_consent_dialog_negative_button) { _, _ -> - navigateToHome() - } - setNegativeButton(R.string.submission_test_result_positive_no_consent_dialog_positive_button) { _, _ -> } + title(R.string.submission_test_result_positive_no_consent_dialog_title) + message(R.string.submission_test_result_positive_no_consent_dialog_message) + positiveButton(R.string.submission_test_result_positive_no_consent_dialog_negative_button) { navigateToHome() } + negativeButton(R.string.submission_test_result_positive_no_consent_dialog_positive_button) } private fun navigateToHome() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentFragment.kt index b14f2a97459..a636c40d019 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentFragment.kt @@ -79,9 +79,9 @@ class SubmissionResultPositiveOtherWarningNoConsentFragment : viewModel.showEnableTracingEvent.observe2(this) { displayDialog { - setTitle(R.string.submission_test_result_dialog_tracing_required_title) - setMessage(R.string.submission_test_result_dialog_tracing_required_message) - setPositiveButton(R.string.submission_test_result_dialog_tracing_required_button) { _, _ -> } + title(R.string.submission_test_result_dialog_tracing_required_title) + message(R.string.submission_test_result_dialog_tracing_required_message) + positiveButton(R.string.submission_test_result_dialog_tracing_required_button) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentFragment.kt index b017e292cdc..262518e32a5 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/yourconsent/SubmissionYourConsentFragment.kt @@ -7,7 +7,6 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentSubmissionYourConsentBinding import de.rki.coronawarnapp.ui.dialog.displayDialog import de.rki.coronawarnapp.util.di.AutoInject @@ -79,7 +78,7 @@ class SubmissionYourConsentFragment : Fragment(R.layout.fragment_submission_your ) } - vm.errorEvent.observe2(this) { displayDialog(dialog = it.toErrorDialogBuilder(requireContext())) } + vm.errorEvent.observe2(this) { displayDialog { setError(it) } } } override fun onResume() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt deleted file mode 100644 index 54625dfc5fd..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt +++ /dev/null @@ -1,141 +0,0 @@ -package de.rki.coronawarnapp.util - -import android.content.Context -import android.content.DialogInterface -import android.text.SpannableString -import android.text.method.LinkMovementMethod -import android.text.util.Linkify -import android.widget.TextView -import androidx.appcompat.app.AlertDialog -import androidx.core.widget.TextViewCompat -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat -import de.rki.coronawarnapp.util.ContextExtensions.getColorStateListCompat -import java.util.regex.Pattern - -object DialogHelper { - - data class DialogInstance( - val context: Context, - val title: String, - val message: String?, - val positiveButton: String, - val negativeButton: String? = null, - val cancelable: Boolean? = true, - val isTextSelectable: Boolean = false, - val positiveButtonFunction: () -> Unit? = {}, - val negativeButtonFunction: () -> Unit? = {}, - val cancelFunction: () -> Unit? = {}, - val isDeleteDialog: Boolean = false - ) { - constructor( - context: Context, - title: Int, - message: Int, - positiveButton: Int, - negativeButton: Int? = null, - cancelable: Boolean? = true, - positiveButtonFunction: () -> Unit? = {}, - negativeButtonFunction: () -> Unit? = {}, - cancelFunction: () -> Unit? = {}, - isDeleteDialog: Boolean = false - ) : this( - context = context, - title = context.resources.getString(title), - message = context.resources.getString(message), - positiveButton = context.resources.getString(positiveButton), - negativeButton = negativeButton?.let { context.resources.getString(it) }, - cancelable = cancelable, - positiveButtonFunction = positiveButtonFunction, - negativeButtonFunction = negativeButtonFunction, - cancelFunction = cancelFunction, - isDeleteDialog = isDeleteDialog - ) - - constructor( - context: Context, - title: Int, - message: String, - positiveButton: Int, - negativeButton: Int? = null, - cancelable: Boolean? = true, - positiveButtonFunction: () -> Unit? = {}, - negativeButtonFunction: () -> Unit? = {}, - cancelFunction: () -> Unit? = {}, - isDeleteDialog: Boolean = false - ) : this( - context = context, - title = context.resources.getString(title), - message = message, - positiveButton = context.resources.getString(positiveButton), - negativeButton = negativeButton?.let { context.resources.getString(it) }, - cancelable = cancelable, - positiveButtonFunction = positiveButtonFunction, - negativeButtonFunction = negativeButtonFunction, - cancelFunction = cancelFunction, - isDeleteDialog = isDeleteDialog - ) - } - - fun showDialog( - dialogInstance: DialogInstance - ): AlertDialog { - val message = getMessage( - dialogInstance.context, - dialogInstance.message, - dialogInstance.isTextSelectable - ) - - val alertDialog = dialogInstance.context.let { - val builder = MaterialAlertDialogBuilder(it) - builder.apply { - setTitle(dialogInstance.title) - setView(message) - setCancelable(dialogInstance.cancelable ?: true) - setPositiveButton( - dialogInstance.positiveButton - ) { _, _ -> - dialogInstance.positiveButtonFunction() - } - if (dialogInstance.negativeButton != null) { - setNegativeButton( - dialogInstance.negativeButton - ) { _, _ -> - dialogInstance.negativeButtonFunction() - } - } - setOnCancelListener { dialogInstance.cancelFunction() } - } - builder.create() - } - - return alertDialog.apply { - show() - if (dialogInstance.isDeleteDialog) { - this.getButton(DialogInterface.BUTTON_POSITIVE) - ?.setTextColor(dialogInstance.context.getColorCompat(R.color.colorTextDeleteButtonDialog)) - } - } - } - - private fun getMessage(context: Context, message: String?, isTextSelectable: Boolean): TextView { - // create spannable and add links, removed stack trace links into nowhere - val spannable = SpannableString(message) - val httpPattern: Pattern = Pattern.compile("[a-z]+://[^ \\n]*") - Linkify.addLinks(spannable, httpPattern, "") - // get padding for all sides - val paddingStartEnd = context.resources.getDimension(R.dimen.spacing_normal).toInt() - val paddingLeftRight = context.resources.getDimension(R.dimen.spacing_small).toInt() - // create a textview with clickable links from the spannable - val textView = TextView(context) - textView.text = spannable - textView.linksClickable = true - textView.movementMethod = LinkMovementMethod.getInstance() - textView.setPadding(paddingStartEnd, paddingLeftRight, paddingStartEnd, paddingLeftRight) - TextViewCompat.setTextAppearance(textView, R.style.body1) - textView.setLinkTextColor(context.getColorStateListCompat(R.color.button_primary)) - if (isTextSelectable) textView.setTextIsSelectable(true) - return textView - } -}