From 52b1fc2ef27d7077c6da8a10e6e3fdd55d02665e Mon Sep 17 00:00:00 2001 From: Lukas Lechner <lukas.lechner@sap.com> Date: Wed, 19 May 2021 13:41:19 +0200 Subject: [PATCH] Deletion of vaccination certificates (EXPOSUREAPP-7111) (#3209) * Add overflow menu icon to vaccination card * Show overflow menu on click * Delete vaccination certificate via overflow menu * Navigate back from VaccinationListFragment when all certificates got deleted * Lint * Add swipe to delete * Fine-tune layout * Lint * Sort vaccinations by vaccinatedAt property in vaccination list screen * Address PR feedback * Show error dialog when vaccination deletion fails Co-authored-by: Mohamed Metwalli <mohamed.metwalli@sap.com> Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com> --- .../ui/list/VaccinationListFragment.kt | 46 +++++++++++++++++-- .../ui/list/VaccinationListViewModel.kt | 41 +++++++++++++++-- ...nationListImmunityInformationCardItemVH.kt | 4 +- .../VaccinationListNameCardItemVH.kt | 4 +- .../VaccinationListQrCodeCardItemVH.kt | 4 +- .../VaccinationListVaccinationCardItemVH.kt | 23 +++++++++- .../drawable-night/ic_arrow_right_grey.xml | 10 ---- .../main/res/drawable/ic_arrow_right_grey.xml | 11 ----- .../vaccination_list_vaccination_card.xml | 35 +++++++++----- .../main/res/menu/menu_vaccination_item.xml | 5 ++ .../res/values-de/vaccination_strings.xml | 22 ++++----- .../src/main/res/values/styles.xml | 4 ++ .../main/res/values/vaccination_strings.xml | 22 ++++----- 13 files changed, 161 insertions(+), 70 deletions(-) delete mode 100644 Corona-Warn-App/src/main/res/drawable-night/ic_arrow_right_grey.xml delete mode 100644 Corona-Warn-App/src/main/res/drawable/ic_arrow_right_grey.xml create mode 100644 Corona-Warn-App/src/main/res/menu/menu_vaccination_item.xml diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/VaccinationListFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/VaccinationListFragment.kt index 58d6e8635..017f9a00c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/VaccinationListFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/VaccinationListFragment.kt @@ -10,12 +10,16 @@ import androidx.navigation.fragment.FragmentNavigatorExtras import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.google.android.material.appbar.AppBarLayout +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.imageview.ShapeableImageView import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.bugreporting.ui.toErrorDialogBuilder import de.rki.coronawarnapp.databinding.FragmentVaccinationListBinding import de.rki.coronawarnapp.ui.qrcode.fullscreen.QrCodeFullScreenFragmentArgs import de.rki.coronawarnapp.ui.view.onOffsetChange import de.rki.coronawarnapp.util.di.AutoInject +import de.rki.coronawarnapp.util.list.isSwipeable +import de.rki.coronawarnapp.util.list.onSwipeItem import de.rki.coronawarnapp.util.lists.diffutil.update import de.rki.coronawarnapp.util.ui.doNavigate import de.rki.coronawarnapp.util.ui.popBackStack @@ -23,7 +27,10 @@ import de.rki.coronawarnapp.util.ui.viewBindingLazy import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider import de.rki.coronawarnapp.util.viewmodel.cwaViewModelsAssisted import de.rki.coronawarnapp.vaccination.core.VaccinatedPerson +import de.rki.coronawarnapp.vaccination.ui.list.VaccinationListViewModel.Event.DeleteVaccinationEvent +import de.rki.coronawarnapp.vaccination.ui.list.VaccinationListViewModel.Event.NavigateBack import de.rki.coronawarnapp.vaccination.ui.list.VaccinationListViewModel.Event.NavigateToVaccinationCertificateDetails +import de.rki.coronawarnapp.vaccination.ui.list.VaccinationListViewModel.Event.NavigateToVaccinationQrCodeScanScreen import de.rki.coronawarnapp.vaccination.ui.list.adapter.VaccinationListAdapter import javax.inject.Inject @@ -43,7 +50,7 @@ class VaccinationListFragment : Fragment(R.layout.fragment_vaccination_list), Au } ) - private val adapter = VaccinationListAdapter() + private val vaccinationListAdapter = VaccinationListAdapter() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -53,7 +60,15 @@ class VaccinationListFragment : Fragment(R.layout.fragment_vaccination_list), Au popBackStack() } - recyclerViewVaccinationList.adapter = adapter + recyclerViewVaccinationList.apply { + adapter = vaccinationListAdapter + onSwipeItem(requireContext()) { position, direction -> + val vaccinationItem = vaccinationListAdapter.data[position] + if (vaccinationItem.isSwipeable()) { + vaccinationItem.onSwipe(position, direction) + } + } + } viewModel.uiState.observe(viewLifecycleOwner) { uiState -> bindViews(uiState) @@ -65,7 +80,7 @@ class VaccinationListFragment : Fragment(R.layout.fragment_vaccination_list), Au VaccinationListFragmentDirections .actionVaccinationListFragmentToVaccinationDetailsFragment(event.vaccinationCertificateId) ) - is VaccinationListViewModel.Event.NavigateToVaccinationQrCodeScanScreen -> doNavigate( + is NavigateToVaccinationQrCodeScanScreen -> doNavigate( VaccinationListFragmentDirections.actionVaccinationListFragmentToVaccinationQrCodeScanFragment() ) is VaccinationListViewModel.Event.NavigateToQrCodeFullScreen -> { @@ -82,9 +97,16 @@ class VaccinationListFragment : Fragment(R.layout.fragment_vaccination_list), Au navigatorExtras ) } + is DeleteVaccinationEvent -> + showDeleteVaccinationDialog(event.vaccinationCertificateId, event.position) + is NavigateBack -> popBackStack() } } + viewModel.errors.observe(viewLifecycleOwner) { error -> + error.toErrorDialogBuilder(requireContext()).show() + } + registerNewVaccinationButton.setOnClickListener { viewModel.onRegisterNewVaccinationClick() } @@ -97,7 +119,7 @@ class VaccinationListFragment : Fragment(R.layout.fragment_vaccination_list), Au setToolbarOverlay() - adapter.update(listItems) + vaccinationListAdapter.update(listItems) val background = if (hasImmunity) { R.drawable.vaccination_compelete_gradient @@ -131,6 +153,22 @@ class VaccinationListFragment : Fragment(R.layout.fragment_vaccination_list), Au behavior.overlayTop = (deviceWidth / divider) - 24 } + private fun showDeleteVaccinationDialog(vaccinationCertificateId: String, position: Int?) { + MaterialAlertDialogBuilder(requireContext()).apply { + setTitle(R.string.vaccination_list_deletion_dialog_title) + setMessage(R.string.vaccination_list_deletion_dialog_message) + setPositiveButton(R.string.vaccination_list_deletion_dialog_positive_button) { _, _ -> + viewModel.deleteVaccination(vaccinationCertificateId) + } + setNegativeButton(R.string.vaccination_list_deletion_dialog_negative_button) { _, _ -> + position?.let { vaccinationListAdapter.notifyItemChanged(it) } + } + setOnCancelListener { + position?.let { vaccinationListAdapter.notifyItemChanged(it) } + } + }.show() + } + companion object { fun navigationUri(personIdentifierCodeSha256: String) = "coronawarnapp://vaccination-list/$personIdentifierCodeSha256".toUri() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/VaccinationListViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/VaccinationListViewModel.kt index f1bbfe430..1a9e0d6ee 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/VaccinationListViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/VaccinationListViewModel.kt @@ -10,6 +10,7 @@ import dagger.assisted.AssistedInject import de.rki.coronawarnapp.contactdiary.util.getLocale import de.rki.coronawarnapp.presencetracing.checkins.qrcode.QrCodeGenerator import de.rki.coronawarnapp.util.TimeAndDateExtensions.toDayFormat +import de.rki.coronawarnapp.util.coroutine.AppScope import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel @@ -22,16 +23,19 @@ import de.rki.coronawarnapp.vaccination.ui.list.adapter.viewholder.VaccinationLi import de.rki.coronawarnapp.vaccination.ui.list.adapter.viewholder.VaccinationListNameCardItemVH.VaccinationListNameCardItem import de.rki.coronawarnapp.vaccination.ui.list.adapter.viewholder.VaccinationListQrCodeCardItemVH.VaccinationListQrCodeCardItem import de.rki.coronawarnapp.vaccination.ui.list.adapter.viewholder.VaccinationListVaccinationCardItemVH.VaccinationListVaccinationCardItem +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.transform +import timber.log.Timber class VaccinationListViewModel @AssistedInject constructor( - vaccinationRepository: VaccinationRepository, + private val vaccinationRepository: VaccinationRepository, valueSetsRepository: ValueSetsRepository, @AppContext context: Context, + @AppScope private val appScope: CoroutineScope, private val qrCodeGenerator: QrCodeGenerator, @Assisted private val personIdentifierCodeSha256: String ) : CWAViewModel() { @@ -41,6 +45,7 @@ class VaccinationListViewModel @AssistedInject constructor( } val events = SingleLiveEvent<Event>() + val errors = SingleLiveEvent<Throwable>() private val vaccinatedPersonFlow = vaccinationRepository.vaccinationInfos.map { vaccinatedPersonSet -> vaccinatedPersonSet.single { it.identifier.codeSHA256 == personIdentifierCodeSha256 } @@ -59,8 +64,17 @@ class VaccinationListViewModel @AssistedInject constructor( listItems = assembleItemList(vaccinatedPerson = vaccinatedPerson, qrCode), vaccinationStatus = vaccinatedPerson.getVaccinationStatus() ) - }.catch { - // TODO Error Handling in an upcoming subtask + }.catch { exception -> + when (exception) { + is NoSuchElementException -> { + Timber.d(exception, "Seems like all vaccination certificates got deleted. Navigate back ...") + events.postValue(Event.NavigateBack) + } + else -> { + Timber.e(exception, "Something unexpected went wrong... Let's navigate back...") + events.postValue(Event.NavigateBack) + } + } }.asLiveData() private fun assembleItemList(vaccinatedPerson: VaccinatedPerson, qrCode: Bitmap?) = @@ -102,7 +116,7 @@ class VaccinationListViewModel @AssistedInject constructor( } } - vaccinatedPerson.vaccinationCertificates.forEach { vaccinationCertificate -> + vaccinatedPerson.vaccinationCertificates.sortedBy { it.vaccinatedAt }.forEach { vaccinationCertificate -> with(vaccinationCertificate) { add( VaccinationListVaccinationCardItem( @@ -114,6 +128,12 @@ class VaccinationListViewModel @AssistedInject constructor( isFinalVaccination = doseNumber == totalSeriesOfDoses, onCardClick = { certificateId -> events.postValue(Event.NavigateToVaccinationCertificateDetails(certificateId)) + }, + onDeleteClick = { certificateId -> + events.postValue(Event.DeleteVaccinationEvent(certificateId)) + }, + onSwipeToDelete = { certificateId, position -> + events.postValue(Event.DeleteVaccinationEvent(certificateId, position)) } ) ) @@ -125,6 +145,17 @@ class VaccinationListViewModel @AssistedInject constructor( events.postValue(Event.NavigateToVaccinationQrCodeScanScreen) } + fun deleteVaccination(vaccinationCertificateId: String) { + launch(scope = appScope) { + try { + vaccinationRepository.deleteVaccinationCertificate(vaccinationCertificateId) + } catch (exception: Exception) { + errors.postValue(exception) + Timber.e(exception, "Something went wrong when trying to delete a vaccination certificate.") + } + } + } + data class UiState( val listItems: List<VaccinationListItem>, val vaccinationStatus: VaccinatedPerson.Status @@ -134,6 +165,8 @@ class VaccinationListViewModel @AssistedInject constructor( data class NavigateToVaccinationCertificateDetails(val vaccinationCertificateId: String) : Event() object NavigateToVaccinationQrCodeScanScreen : Event() data class NavigateToQrCodeFullScreen(val qrCode: String, val positionInList: Int) : Event() + data class DeleteVaccinationEvent(val vaccinationCertificateId: String, val position: Int? = null) : Event() + object NavigateBack : Event() } @AssistedFactory diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListImmunityInformationCardItemVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListImmunityInformationCardItemVH.kt index f6824b79b..d347b79da 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListImmunityInformationCardItemVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListImmunityInformationCardItemVH.kt @@ -3,6 +3,7 @@ package de.rki.coronawarnapp.vaccination.ui.list.adapter.viewholder import android.view.ViewGroup import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.VaccinationListImmunityCardBinding +import de.rki.coronawarnapp.util.list.Movable import de.rki.coronawarnapp.vaccination.ui.list.adapter.VaccinationListAdapter import de.rki.coronawarnapp.vaccination.ui.list.adapter.VaccinationListItem import de.rki.coronawarnapp.vaccination.ui.list.adapter.viewholder.VaccinationListImmunityInformationCardItemVH.VaccinationListImmunityInformationCardItem @@ -12,7 +13,8 @@ class VaccinationListImmunityInformationCardItemVH(parent: ViewGroup) : VaccinationListAdapter.ItemVH<VaccinationListImmunityInformationCardItem, VaccinationListImmunityCardBinding>( layoutRes = R.layout.vaccination_list_immunity_card, parent = parent - ) { + ), + Movable { override val viewBinding: Lazy<VaccinationListImmunityCardBinding> = lazy { VaccinationListImmunityCardBinding.bind(itemView) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListNameCardItemVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListNameCardItemVH.kt index 5cd1501ca..392007562 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListNameCardItemVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListNameCardItemVH.kt @@ -3,6 +3,7 @@ package de.rki.coronawarnapp.vaccination.ui.list.adapter.viewholder import android.view.ViewGroup import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.VaccinationListNameCardBinding +import de.rki.coronawarnapp.util.list.Movable import de.rki.coronawarnapp.vaccination.ui.list.adapter.VaccinationListAdapter import de.rki.coronawarnapp.vaccination.ui.list.adapter.VaccinationListItem import de.rki.coronawarnapp.vaccination.ui.list.adapter.viewholder.VaccinationListNameCardItemVH.VaccinationListNameCardItem @@ -11,7 +12,8 @@ class VaccinationListNameCardItemVH(parent: ViewGroup) : VaccinationListAdapter.ItemVH<VaccinationListNameCardItem, VaccinationListNameCardBinding>( layoutRes = R.layout.vaccination_list_name_card, parent = parent - ) { + ), + Movable { override val viewBinding: Lazy<VaccinationListNameCardBinding> = lazy { VaccinationListNameCardBinding.bind(itemView) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListQrCodeCardItemVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListQrCodeCardItemVH.kt index 9510850ad..cf5b3b331 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListQrCodeCardItemVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListQrCodeCardItemVH.kt @@ -6,6 +6,7 @@ import androidx.core.view.isVisible import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.VaccinationListQrcodeCardBinding import de.rki.coronawarnapp.util.TimeAndDateExtensions.toShortDayFormat +import de.rki.coronawarnapp.util.list.Movable import de.rki.coronawarnapp.vaccination.ui.list.adapter.VaccinationListAdapter import de.rki.coronawarnapp.vaccination.ui.list.adapter.VaccinationListItem import de.rki.coronawarnapp.vaccination.ui.list.adapter.viewholder.VaccinationListQrCodeCardItemVH.VaccinationListQrCodeCardItem @@ -16,7 +17,8 @@ class VaccinationListQrCodeCardItemVH(parent: ViewGroup) : VaccinationListAdapter.ItemVH<VaccinationListQrCodeCardItem, VaccinationListQrcodeCardBinding>( layoutRes = R.layout.vaccination_list_qrcode_card, parent = parent - ) { + ), + Movable { override val viewBinding: Lazy<VaccinationListQrcodeCardBinding> = lazy { VaccinationListQrcodeCardBinding.bind(itemView) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListVaccinationCardItemVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListVaccinationCardItemVH.kt index 80b9dc19f..f38f54c83 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListVaccinationCardItemVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListVaccinationCardItemVH.kt @@ -1,8 +1,11 @@ package de.rki.coronawarnapp.vaccination.ui.list.adapter.viewholder +import android.view.Gravity import android.view.ViewGroup +import androidx.appcompat.widget.PopupMenu import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.VaccinationListVaccinationCardBinding +import de.rki.coronawarnapp.util.list.SwipeConsumer import de.rki.coronawarnapp.vaccination.core.VaccinatedPerson import de.rki.coronawarnapp.vaccination.core.VaccinatedPerson.Status.COMPLETE import de.rki.coronawarnapp.vaccination.core.VaccinatedPerson.Status.IMMUNITY @@ -54,6 +57,18 @@ class VaccinationListVaccinationCardItemVH( } } vaccinationIcon.setImageResource(iconRes) + + val menu = PopupMenu(context, overflowMenu, Gravity.TOP or Gravity.END).apply { + inflate(R.menu.menu_vaccination_item) + setOnMenuItemClickListener { + when (it.itemId) { + R.id.menu_delete -> item.onDeleteClick(item.vaccinationCertificateId).let { true } + else -> false + } + } + } + + overflowMenu.setOnClickListener { menu.show() } } } @@ -64,8 +79,10 @@ class VaccinationListVaccinationCardItemVH( val vaccinatedAt: String, val vaccinationStatus: VaccinatedPerson.Status, val isFinalVaccination: Boolean, - val onCardClick: (String) -> Unit - ) : VaccinationListItem { + val onCardClick: (String) -> Unit, + val onDeleteClick: (String) -> Unit, + val onSwipeToDelete: (String, Int) -> Unit + ) : VaccinationListItem, SwipeConsumer { override val stableId: Long = Objects.hash( vaccinationCertificateId, @@ -76,6 +93,8 @@ class VaccinationListVaccinationCardItemVH( isFinalVaccination ).toLong() + override fun onSwipe(position: Int, direction: Int) = onSwipeToDelete(vaccinationCertificateId, position) + // Ignore onCardClick Listener in equals() to avoid re-drawing when only the click listener is updated override fun equals(other: Any?): Boolean { if (this === other) return true diff --git a/Corona-Warn-App/src/main/res/drawable-night/ic_arrow_right_grey.xml b/Corona-Warn-App/src/main/res/drawable-night/ic_arrow_right_grey.xml deleted file mode 100644 index 40001f61b..000000000 --- a/Corona-Warn-App/src/main/res/drawable-night/ic_arrow_right_grey.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="19dp" - android:height="16dp" - android:viewportWidth="19" - android:viewportHeight="16"> - <path - android:pathData="M11.9186,0.7474L10.4286,2.3179L14.9685,7.103H0.9918V9.197H14.9685L10.4286,13.9821L11.9186,15.5525L18.9419,8.15L11.9186,0.7474Z" - android:fillColor="#A7A7A7" - android:fillType="evenOdd"/> -</vector> diff --git a/Corona-Warn-App/src/main/res/drawable/ic_arrow_right_grey.xml b/Corona-Warn-App/src/main/res/drawable/ic_arrow_right_grey.xml deleted file mode 100644 index fea245299..000000000 --- a/Corona-Warn-App/src/main/res/drawable/ic_arrow_right_grey.xml +++ /dev/null @@ -1,11 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="19dp" - android:height="16dp" - android:viewportWidth="19" - android:viewportHeight="16"> - <path - android:pathData="M11.9186,0.7475L10.4286,2.318L14.9685,7.1031H0.9918V9.197H14.9685L10.4286,13.9821L11.9186,15.5526L18.9419,8.15L11.9186,0.7475Z" - android:fillColor="#17191A" - android:fillAlpha="0.6" - android:fillType="evenOdd"/> -</vector> diff --git a/Corona-Warn-App/src/main/res/layout/vaccination_list_vaccination_card.xml b/Corona-Warn-App/src/main/res/layout/vaccination_list_vaccination_card.xml index 2078b26bd..20d3f5f2d 100644 --- a/Corona-Warn-App/src/main/res/layout/vaccination_list_vaccination_card.xml +++ b/Corona-Warn-App/src/main/res/layout/vaccination_list_vaccination_card.xml @@ -2,17 +2,18 @@ <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/vaccination_card" - style="@style/Card.Vaccination.Ripple" + style="@style/Card.Vaccination.Ripple.NoPadding" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="24dp" - android:layout_marginTop="8dp" - android:padding="16dp"> + android:layout_marginTop="8dp"> <ImageView android:id="@+id/vaccination_icon" android:layout_width="88dp" android:layout_height="95dp" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" android:importantForAccessibility="no" app:srcCompat="@drawable/ic_vaccination_incomplete" app:layout_constraintStart_toStartOf="parent" @@ -27,9 +28,9 @@ android:text="@string/vaccination_list_vaccination_card_title" android:textSize="18sp" android:textStyle="bold" - app:layout_constraintEnd_toStartOf="@id/arrow_right" + app:layout_constraintEnd_toStartOf="@id/overflow_menu" app:layout_constraintStart_toEndOf="@id/vaccination_icon" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="@id/vaccination_icon" /> <TextView android:id="@+id/vaccination_card_subtitle" @@ -39,17 +40,27 @@ android:layout_marginStart="16dp" android:layout_marginTop="4dp" android:text="@string/vaccination_list_vaccination_card_subtitle" - app:layout_constraintEnd_toStartOf="@id/arrow_right" + app:layout_constraintEnd_toStartOf="@id/overflow_menu" app:layout_constraintStart_toEndOf="@id/vaccination_icon" app:layout_constraintTop_toBottomOf="@id/vaccination_card_title" /> - <ImageView - android:id="@+id/arrow_right" + <ImageButton + android:id="@+id/overflow_menu" + style="@style/CardOverFlowButton" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent"/> + + <androidx.constraintlayout.widget.Barrier + android:id="@+id/bottom_barrier" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:importantForAccessibility="no" - app:srcCompat="@drawable/ic_arrow_right_grey" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + app:barrierDirection="bottom" + app:constraint_referenced_ids="vaccination_icon,vaccination_card_subtitle" /> + + <Space + android:layout_width="match_parent" + android:layout_height="16dp" + app:layout_constraintTop_toBottomOf="@id/bottom_barrier" + app:layout_constraintStart_toStartOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/menu/menu_vaccination_item.xml b/Corona-Warn-App/src/main/res/menu/menu_vaccination_item.xml new file mode 100644 index 000000000..7e750fd6e --- /dev/null +++ b/Corona-Warn-App/src/main/res/menu/menu_vaccination_item.xml @@ -0,0 +1,5 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/menu_delete" + android:title="@string/vaccination_list_delete_button" /> +</menu> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/values-de/vaccination_strings.xml b/Corona-Warn-App/src/main/res/values-de/vaccination_strings.xml index 9529309ba..31cbf05d3 100644 --- a/Corona-Warn-App/src/main/res/values-de/vaccination_strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/vaccination_strings.xml @@ -16,8 +16,6 @@ <string name="vaccination_details_certificate_country">Land</string> <!-- XTXT: Vaccination Details certificate id --> <string name="vaccination_details_certificate_id">Zertifikationsnummer</string> - <!-- XBUT: Vaccination Details delete button --> - <string name="vaccination_details_delete_button">Impfzertifikat entfernen</string> <!-- XTXT: Vaccination Details subtitle--> <string name="vaccination_details_subtitle">Impfzertifikat</string> <!-- XTXT: Vaccination Details title--> @@ -26,14 +24,6 @@ <string name="vaccination_qrcode_card_title">Impfzertifikat %1$d von %2$d</string> <!-- XTXT: Vaccination Qr Code card subtitle--> <string name="vaccination_qrcode_card_subtitle">Geimpft %1$s - gültig bis %2$s</string> - <!-- XTXT: Vaccination Details deletion dialog title--> - <string name="vaccination_details_deletion_dialog_title">Wollen Sie das Impfzertifikat wirklich entfernen?</string> - <!-- XTXT: Vaccination Details deletion dialog message--> - <string name="vaccination_details_deletion_dialog_message">Wenn Sie das Impfzertifikat entfernen, kann die App die Impfung nicht mehr für die Prüfung Ihres Impfstatus berücksichtigen.</string> - <!-- XBUT: Vaccination Details deletion dialog positive button--> - <string name="vaccination_details_deletion_dialog_positive_button">Entfernen</string> - <!-- XBUT: Vaccination Details deletion dialog negative button--> - <string name="vaccination_details_deletion_dialog_negative_button">Abbrechen</string> <!-- XTXT: Vaccination List title--> <string name="vaccination_list_title">Digitaler Impfnachweis</string> @@ -54,8 +44,16 @@ </plurals> <!-- XBUT: Vaccination List register additional vaccination button --> <string name="vaccination_list_register_new_vaccination_button">Weitere Impfung registrieren</string> - <!-- XBUT: Vaccination List refresh button --> - <string name="vaccination_list_refresh_button">Aktualisieren</string> + <!-- XBUT: Vaccination List delete button --> + <string name="vaccination_list_delete_button">Entfernen</string> + <!-- XTXT: Vaccination List deletion dialog title--> + <string name="vaccination_list_deletion_dialog_title">Wollen Sie das Impfzertifikat wirklich entfernen?</string> + <!-- XTXT: Vaccination List deletion dialog message--> + <string name="vaccination_list_deletion_dialog_message">Wenn Sie das Impfzertifikat entfernen, kann die App die Impfung nicht mehr für die Prüfung Ihres Impfstatus berücksichtigen.</string> + <!-- XBUT: Vaccination List deletion dialog positive button--> + <string name="vaccination_list_deletion_dialog_positive_button">Entfernen</string> + <!-- XBUT: Vaccination List deletion dialog negative button--> + <string name="vaccination_list_deletion_dialog_negative_button">Abbrechen</string> <!-- XACT: Vaccination List Qr-Code for screen readers --> <string name="vaccination_list_qr_code_accessibility">Qr-Code</string> diff --git a/Corona-Warn-App/src/main/res/values/styles.xml b/Corona-Warn-App/src/main/res/values/styles.xml index e24c21b57..9057e165e 100644 --- a/Corona-Warn-App/src/main/res/values/styles.xml +++ b/Corona-Warn-App/src/main/res/values/styles.xml @@ -243,6 +243,10 @@ <item name="android:background">@drawable/grey_card_ripple</item> </style> + <style name="Card.Vaccination.Ripple.NoPadding"> + <item name="android:padding">@dimen/no_padding</item> + </style> + <style name="Card.NoPadding"> <item name="android:padding">@dimen/no_padding</item> </style> diff --git a/Corona-Warn-App/src/main/res/values/vaccination_strings.xml b/Corona-Warn-App/src/main/res/values/vaccination_strings.xml index 62730ced6..80ce5d67e 100644 --- a/Corona-Warn-App/src/main/res/values/vaccination_strings.xml +++ b/Corona-Warn-App/src/main/res/values/vaccination_strings.xml @@ -16,8 +16,6 @@ <string name="vaccination_details_certificate_country">Land</string> <!-- XTXT: Vaccination Details certificate id --> <string name="vaccination_details_certificate_id">Zertifikationsnummer</string> - <!-- XBUT: Vaccination Details delete button --> - <string name="vaccination_details_delete_button">Impfzertifikat entfernen</string> <!-- XTXT: Vaccination Details subtitle--> <string name="vaccination_details_subtitle">Impfzertifikat</string> <!-- XTXT: Vaccination Details title--> @@ -26,14 +24,6 @@ <string name="vaccination_qrcode_card_title">Impfzertifikat %1$d von %2$d</string> <!-- XTXT: Vaccination Qr Code card subtitle--> <string name="vaccination_qrcode_card_subtitle">Geimpft %1$s - gültig bis %2$s</string> - <!-- XTXT: Vaccination Details deletion dialog title--> - <string name="vaccination_details_deletion_dialog_title">Wollen Sie das Impfzertifikat wirklich entfernen?</string> - <!-- XTXT: Vaccination Details deletion dialog message--> - <string name="vaccination_details_deletion_dialog_message">Wenn Sie das Impfzertifikat entfernen, kann die App die Impfung nicht mehr für die Prüfung Ihres Impfstatus berücksichtigen.</string> - <!-- XBUT: Vaccination Details deletion dialog positive button--> - <string name="vaccination_details_deletion_dialog_positive_button">Entfernen</string> - <!-- XBUT: Vaccination Details deletion dialog negative button--> - <string name="vaccination_details_deletion_dialog_negative_button">Abbrechen</string> <!-- XTXT: Vaccination List title--> <string name="vaccination_list_title">Digitaler Impfnachweis</string> @@ -60,8 +50,16 @@ </plurals> <!-- XBUT: Vaccination List register additional vaccination button --> <string name="vaccination_list_register_new_vaccination_button">Weitere Impfung registrieren</string> - <!-- XBUT: Vaccination List refresh button --> - <string name="vaccination_list_refresh_button">Aktualisieren</string> + <!-- XBUT: Vaccination List delete button --> + <string name="vaccination_list_delete_button">Entfernen</string> + <!-- XTXT: Vaccination List deletion dialog title--> + <string name="vaccination_list_deletion_dialog_title">Wollen Sie das Impfzertifikat wirklich entfernen?</string> + <!-- XTXT: Vaccination List deletion dialog message--> + <string name="vaccination_list_deletion_dialog_message">Wenn Sie das Impfzertifikat entfernen, kann die App die Impfung nicht mehr für die Prüfung Ihres Impfstatus berücksichtigen.</string> + <!-- XBUT: Vaccination List deletion dialog positive button--> + <string name="vaccination_list_deletion_dialog_positive_button">Entfernen</string> + <!-- XBUT: Vaccination List deletion dialog negative button--> + <string name="vaccination_list_deletion_dialog_negative_button">Abbrechen</string> <!-- XACT: Vaccination List Qr-Code for screen readers --> <string name="vaccination_list_qr_code_accessibility">Qr-Code</string> -- GitLab