From 53f3faf3889eb99bc1ec128d0c4882af51aeabd5 Mon Sep 17 00:00:00 2001
From: BMItter <46747780+BMItter@users.noreply.github.com>
Date: Fri, 8 Jan 2021 15:32:09 +0100
Subject: [PATCH] Contact Journal - cleanUp and code smells (EXPOSUREAPP-4503)
 (#2051)

* cleanup - Removed useless menu class

* cleanup - Sort export case sensitive

* cleanup - Added extension clearAndAddAll

* Removed useless wrapping

* Better semantic

* cleanup - Added AbstractAdapter, Use AbstractAdapter

* stabledId returns it

* Removed useless wrapping

* Use BaseAdapter and VH for contact diary overview

* Removed useless constants

* merge resolve

* detekt & ktlint
---
 .../model/DefaultContactDiaryLocation.kt      |  8 ++-
 .../model/DefaultContactDiaryPerson.kt        |  8 ++-
 .../ui/day/ContactDiaryDayFragment.kt         |  8 ++-
 .../ContactDiaryLocationListAdapter.kt        | 12 +---
 .../person/ContactDiaryPersonListAdapter.kt   | 12 +---
 .../edit/ContactDiaryEditLocationsFragment.kt | 58 ++--------------
 .../ContactDiaryEditLocationsViewModel.kt     |  4 +-
 .../edit/ContactDiaryEditPersonsFragment.kt   | 58 ++--------------
 .../edit/ContactDiaryEditPersonsViewModel.kt  |  4 +-
 .../ui/edit/adapter/LocationEditAdapter.kt    | 40 +++++++++++
 .../ui/edit/adapter/PersonEditAdapter.kt      | 40 +++++++++++
 .../overview/ContactDiaryOverviewFragment.kt  | 38 +++++++++--
 .../ui/overview/ContactDiaryOverviewMenu.kt   | 52 --------------
 .../overview/ContactDiaryOverviewViewModel.kt |  4 +-
 .../adapter/ContactDiaryOverviewAdapter.kt    | 67 ++++++++-----------
 .../ContactDiaryOverviewNestedAdapter.kt      | 40 ++++++-----
 ...DiaryLocationBottomSheetDialogViewModel.kt |  2 -
 ...ctDiaryPersonBottomSheetDialogViewModel.kt |  2 -
 .../contactdiary/util/AbstractAdapter.kt      | 15 +++++
 .../util/ContactDiaryExtensions.kt            |  5 ++
 20 files changed, 225 insertions(+), 252 deletions(-)
 create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/adapter/LocationEditAdapter.kt
 create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/adapter/PersonEditAdapter.kt
 delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewMenu.kt
 create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/util/AbstractAdapter.kt

diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryLocation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryLocation.kt
index 3e0ec3ea9..78ff94aa0 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryLocation.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryLocation.kt
@@ -2,6 +2,8 @@ package de.rki.coronawarnapp.contactdiary.model
 
 data class DefaultContactDiaryLocation(
     override val locationId: Long = 0L,
-    override var locationName: String,
-    override val stableId: Long = locationId
-) : ContactDiaryLocation
+    override var locationName: String
+) : ContactDiaryLocation {
+    override val stableId: Long
+        get() = locationId
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryPerson.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryPerson.kt
index 1d0188925..911bd939b 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryPerson.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryPerson.kt
@@ -2,6 +2,8 @@ package de.rki.coronawarnapp.contactdiary.model
 
 data class DefaultContactDiaryPerson(
     override val personId: Long = 0L,
-    override var fullName: String,
-    override val stableId: Long = personId
-) : ContactDiaryPerson
+    override var fullName: String
+) : ContactDiaryPerson {
+    override val stableId: Long
+        get() = personId
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/ContactDiaryDayFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/ContactDiaryDayFragment.kt
index ae4dd4fc0..2301d5682 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/ContactDiaryDayFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/ContactDiaryDayFragment.kt
@@ -62,9 +62,11 @@ class ContactDiaryDayFragment : Fragment(R.layout.contact_diary_day_fragment), A
             }
         }
 
-        viewModel.uiState.observe2(this) {
-            binding.contactDiaryDayHeader.title = it.dayText(requireContext())
-            binding.contactDiaryDayHeader.contentDescription = it.dayTextContentDescription(requireContext())
+        viewModel.uiState.observe2(this) { uiState ->
+            binding.contactDiaryDayHeader.apply {
+                title = uiState.dayText(context)
+                contentDescription = uiState.dayTextContentDescription(context)
+            }
         }
 
         viewModel.routeToScreen.observe2(this) {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/ContactDiaryLocationListAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/ContactDiaryLocationListAdapter.kt
index 53ad1fa2d..0e1dbfd1a 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/ContactDiaryLocationListAdapter.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/ContactDiaryLocationListAdapter.kt
@@ -4,25 +4,19 @@ import android.view.ViewGroup
 import android.view.accessibility.AccessibilityEvent
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.contactdiary.model.ContactDiaryLocation
+import de.rki.coronawarnapp.contactdiary.util.AbstractAdapter
 import de.rki.coronawarnapp.contactdiary.util.SelectableItem
 import de.rki.coronawarnapp.contactdiary.util.setClickLabel
 import de.rki.coronawarnapp.databinding.ContactDiaryLocationListItemBinding
 import de.rki.coronawarnapp.ui.lists.BaseAdapter
 import de.rki.coronawarnapp.util.lists.BindableVH
 import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter
-import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer
 
-class ContactDiaryLocationListAdapter(
+internal class ContactDiaryLocationListAdapter(
     private val onTappedCallback: (item: SelectableItem<ContactDiaryLocation>) -> Unit
-) : BaseAdapter<ContactDiaryLocationListAdapter.CachedLocationViewHolder>(),
+) : AbstractAdapter<SelectableItem<ContactDiaryLocation>, ContactDiaryLocationListAdapter.CachedLocationViewHolder>(),
     AsyncDiffUtilAdapter<SelectableItem<ContactDiaryLocation>> {
 
-    override val asyncDiffer: AsyncDiffer<SelectableItem<ContactDiaryLocation>> = AsyncDiffer(this)
-
-    override fun getItemCount(): Int = data.size
-
-    override fun getItemId(position: Int): Long = data[position].stableId
-
     override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): CachedLocationViewHolder =
         CachedLocationViewHolder(parent)
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/person/ContactDiaryPersonListAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/person/ContactDiaryPersonListAdapter.kt
index f8142cb31..d45e61947 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/person/ContactDiaryPersonListAdapter.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/person/ContactDiaryPersonListAdapter.kt
@@ -4,25 +4,19 @@ import android.view.ViewGroup
 import android.view.accessibility.AccessibilityEvent
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.contactdiary.model.ContactDiaryPerson
+import de.rki.coronawarnapp.contactdiary.util.AbstractAdapter
 import de.rki.coronawarnapp.contactdiary.util.SelectableItem
 import de.rki.coronawarnapp.contactdiary.util.setClickLabel
 import de.rki.coronawarnapp.databinding.ContactDiaryPersonListItemBinding
 import de.rki.coronawarnapp.ui.lists.BaseAdapter
 import de.rki.coronawarnapp.util.lists.BindableVH
 import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter
-import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer
 
-class ContactDiaryPersonListAdapter(
+internal class ContactDiaryPersonListAdapter(
     private val onTappedCallback: (item: SelectableItem<ContactDiaryPerson>) -> Unit
-) : BaseAdapter<ContactDiaryPersonListAdapter.CachedPersonViewHolder>(),
+) : AbstractAdapter<SelectableItem<ContactDiaryPerson>, ContactDiaryPersonListAdapter.CachedPersonViewHolder>(),
     AsyncDiffUtilAdapter<SelectableItem<ContactDiaryPerson>> {
 
-    override val asyncDiffer: AsyncDiffer<SelectableItem<ContactDiaryPerson>> = AsyncDiffer(this)
-
-    override fun getItemCount(): Int = data.size
-
-    override fun getItemId(position: Int): Long = data[position].stableId
-
     override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): CachedPersonViewHolder =
         CachedPersonViewHolder(parent)
 
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 e9c77914f..5a226c113 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
@@ -1,24 +1,17 @@
 package de.rki.coronawarnapp.contactdiary.ui.edit
 
 import android.os.Bundle
-import android.view.LayoutInflater
 import android.view.View
-import android.view.ViewGroup
 import android.view.accessibility.AccessibilityEvent
-import android.widget.TextView
 import androidx.core.view.isGone
 import androidx.fragment.app.Fragment
-import androidx.recyclerview.widget.RecyclerView
 import de.rki.coronawarnapp.R
-import de.rki.coronawarnapp.contactdiary.model.ContactDiaryLocation
 import de.rki.coronawarnapp.contactdiary.ui.edit.ContactDiaryEditLocationsViewModel.NavigationEvent.ShowDeletionConfirmationDialog
 import de.rki.coronawarnapp.contactdiary.ui.edit.ContactDiaryEditLocationsViewModel.NavigationEvent.ShowLocationDetailSheet
-import de.rki.coronawarnapp.contactdiary.util.setClickLabel
+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.util.di.AutoInject
-import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter
-import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer
 import de.rki.coronawarnapp.util.lists.diffutil.update
 import de.rki.coronawarnapp.util.ui.doNavigate
 import de.rki.coronawarnapp.util.ui.observe2
@@ -34,7 +27,7 @@ class ContactDiaryEditLocationsFragment : Fragment(R.layout.contact_diary_edit_l
     private val viewModel: ContactDiaryEditLocationsViewModel by cwaViewModels { viewModelFactory }
     private val binding: ContactDiaryEditLocationsFragmentBinding by viewBindingLazy()
 
-    private lateinit var listAdapter: ListAdapter
+    private lateinit var listAdapter: LocationEditAdapter
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
@@ -81,9 +74,11 @@ class ContactDiaryEditLocationsFragment : Fragment(R.layout.contact_diary_edit_l
     }
 
     private fun setupRecyclerView() {
-        listAdapter = ListAdapter(getString(R.string.accessibility_edit)) {
-            getString(R.string.accessibility_location, it.locationName)
-        }
+        listAdapter = LocationEditAdapter(
+            clickLabelString = getString(R.string.accessibility_edit),
+            getContentDescriptionString = { getString(R.string.accessibility_location, it.locationName) },
+            onItemClicked = { viewModel.onEditLocationClick(it) }
+        )
         binding.locationsRecyclerView.adapter = listAdapter
     }
 
@@ -99,43 +94,4 @@ class ContactDiaryEditLocationsFragment : Fragment(R.layout.contact_diary_edit_l
             }
         )
     }
-
-    inner class ListAdapter(
-        private val clickLabelString: String,
-        private val getContentDescriptionString: (ContactDiaryLocation) -> String
-    ) : RecyclerView.Adapter<ListAdapter.ViewHolder>(),
-        AsyncDiffUtilAdapter<ContactDiaryLocation> {
-
-        override val asyncDiffer: AsyncDiffer<ContactDiaryLocation> = AsyncDiffer(this)
-
-        inner class ViewHolder(listItemView: View) : RecyclerView.ViewHolder(listItemView) {
-            val nameTextView = itemView.findViewById<TextView>(R.id.name)
-            val itemContainerView = itemView.findViewById<View>(R.id.item_container)
-        }
-
-        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListAdapter.ViewHolder {
-            val view = LayoutInflater.from(parent.context).inflate(R.layout.contact_diary_edit_list_item, parent, false)
-            return ViewHolder(view)
-        }
-
-        override fun onBindViewHolder(viewHolder: ListAdapter.ViewHolder, position: Int) {
-            val location = data[position]
-            with(viewHolder) {
-                nameTextView.text = location.locationName
-                itemContainerView.setOnClickListener {
-                    viewModel.onEditLocationClick(location)
-                }
-                itemContainerView.contentDescription = getContentDescriptionString(location)
-                itemContainerView.setClickLabel(clickLabelString)
-            }
-        }
-
-        override fun getItemCount(): Int {
-            return data.size
-        }
-
-        override fun getItemId(position: Int): Long {
-            return data[position].locationId
-        }
-    }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModel.kt
index 3ef030e2c..c4a5dd4e1 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModel.kt
@@ -28,10 +28,10 @@ class ContactDiaryEditLocationsViewModel @AssistedInject constructor(
 
     val navigationEvent = SingleLiveEvent<NavigationEvent>()
 
-    val isButtonEnabled = contactDiaryRepository.locations.map { !it.isNullOrEmpty() }
+    val isButtonEnabled = contactDiaryRepository.locations.map { it.isNotEmpty() }
         .asLiveData(dispatcherProvider.IO)
 
-    val isListVisible = contactDiaryRepository.locations.map { !it.isNullOrEmpty() }
+    val isListVisible = contactDiaryRepository.locations.map { it.isNotEmpty() }
         .asLiveData(dispatcherProvider.IO)
 
     fun onDeleteAllLocationsClick() {
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 eaeace7dd..bd46ac797 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
@@ -1,24 +1,17 @@
 package de.rki.coronawarnapp.contactdiary.ui.edit
 
 import android.os.Bundle
-import android.view.LayoutInflater
 import android.view.View
-import android.view.ViewGroup
 import android.view.accessibility.AccessibilityEvent
-import android.widget.TextView
 import androidx.core.view.isGone
 import androidx.fragment.app.Fragment
-import androidx.recyclerview.widget.RecyclerView
 import de.rki.coronawarnapp.R
-import de.rki.coronawarnapp.contactdiary.model.ContactDiaryPerson
 import de.rki.coronawarnapp.contactdiary.ui.edit.ContactDiaryEditPersonsViewModel.NavigationEvent.ShowDeletionConfirmationDialog
 import de.rki.coronawarnapp.contactdiary.ui.edit.ContactDiaryEditPersonsViewModel.NavigationEvent.ShowPersonDetailSheet
-import de.rki.coronawarnapp.contactdiary.util.setClickLabel
+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.util.di.AutoInject
-import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter
-import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer
 import de.rki.coronawarnapp.util.lists.diffutil.update
 import de.rki.coronawarnapp.util.ui.doNavigate
 import de.rki.coronawarnapp.util.ui.observe2
@@ -34,7 +27,7 @@ class ContactDiaryEditPersonsFragment : Fragment(R.layout.contact_diary_edit_per
     private val viewModel: ContactDiaryEditPersonsViewModel by cwaViewModels { viewModelFactory }
     private val binding: ContactDiaryEditPersonsFragmentBinding by viewBindingLazy()
 
-    private lateinit var listAdapter: ListAdapter
+    private lateinit var listAdapter: PersonEditAdapter
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
@@ -83,9 +76,11 @@ class ContactDiaryEditPersonsFragment : Fragment(R.layout.contact_diary_edit_per
     }
 
     private fun setupRecyclerView() {
-        listAdapter = ListAdapter(getString(R.string.accessibility_edit)) {
-            getString(R.string.accessibility_person, it.fullName)
-        }
+        listAdapter = PersonEditAdapter(
+            clickLabelString = getString(R.string.accessibility_edit),
+            getContentDescriptionString = { getString(R.string.accessibility_person, it.fullName) },
+            onItemClicked = { viewModel.onEditPersonClick(it) }
+        )
         binding.personsRecyclerView.adapter = listAdapter
     }
 
@@ -101,43 +96,4 @@ class ContactDiaryEditPersonsFragment : Fragment(R.layout.contact_diary_edit_per
             }
         )
     }
-
-    inner class ListAdapter(
-        private val clickLabelString: String,
-        private val getContentDescriptionString: (ContactDiaryPerson) -> String
-    ) : RecyclerView.Adapter<ListAdapter.ViewHolder>(),
-        AsyncDiffUtilAdapter<ContactDiaryPerson> {
-
-        override val asyncDiffer: AsyncDiffer<ContactDiaryPerson> = AsyncDiffer(this)
-
-        inner class ViewHolder(listItemView: View) : RecyclerView.ViewHolder(listItemView) {
-            val nameTextView = itemView.findViewById<TextView>(R.id.name)
-            val itemContainerView = itemView.findViewById<View>(R.id.item_container)
-        }
-
-        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListAdapter.ViewHolder {
-            val view = LayoutInflater.from(parent.context).inflate(R.layout.contact_diary_edit_list_item, parent, false)
-            return ViewHolder(view)
-        }
-
-        override fun onBindViewHolder(viewHolder: ListAdapter.ViewHolder, position: Int) {
-            val person = data[position]
-            with(viewHolder) {
-                nameTextView.text = person.fullName
-                itemContainerView.setOnClickListener {
-                    viewModel.onEditPersonClick(person)
-                }
-                itemContainerView.contentDescription = getContentDescriptionString(person)
-                itemContainerView.setClickLabel(clickLabelString)
-            }
-        }
-
-        override fun getItemCount(): Int {
-            return data.size
-        }
-
-        override fun getItemId(position: Int): Long {
-            return data[position].personId
-        }
-    }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditPersonsViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditPersonsViewModel.kt
index 2fa6a23e7..d418c003a 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditPersonsViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditPersonsViewModel.kt
@@ -25,10 +25,10 @@ class ContactDiaryEditPersonsViewModel @AssistedInject constructor(
     val personsLiveData = contactDiaryRepository.people
         .asLiveData()
 
-    val isButtonEnabled = contactDiaryRepository.people.map { !it.isNullOrEmpty() }
+    val isButtonEnabled = contactDiaryRepository.people.map { it.isNotEmpty() }
         .asLiveData(dispatcherProvider.IO)
 
-    val isListVisible = contactDiaryRepository.people.map { !it.isNullOrEmpty() }
+    val isListVisible = contactDiaryRepository.people.map { it.isNotEmpty() }
         .asLiveData(dispatcherProvider.IO)
 
     private val coroutineExceptionHandler = CoroutineExceptionHandler { coroutineContext, ex ->
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/adapter/LocationEditAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/adapter/LocationEditAdapter.kt
new file mode 100644
index 000000000..54b560ab3
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/adapter/LocationEditAdapter.kt
@@ -0,0 +1,40 @@
+package de.rki.coronawarnapp.contactdiary.ui.edit.adapter
+
+import android.view.ViewGroup
+import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.contactdiary.model.ContactDiaryLocation
+import de.rki.coronawarnapp.contactdiary.util.AbstractAdapter
+import de.rki.coronawarnapp.contactdiary.util.setClickLabel
+import de.rki.coronawarnapp.databinding.ContactDiaryEditListItemBinding
+import de.rki.coronawarnapp.ui.lists.BaseAdapter
+import de.rki.coronawarnapp.util.lists.BindableVH
+
+internal class LocationEditAdapter(
+    private val clickLabelString: String,
+    private val getContentDescriptionString: (ContactDiaryLocation) -> String,
+    private val onItemClicked: (item: ContactDiaryLocation) -> Unit
+) : AbstractAdapter<ContactDiaryLocation, LocationEditAdapter.ViewHolder>() {
+
+    override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(parent)
+
+    override fun onBindBaseVH(holder: ViewHolder, position: Int, payloads: MutableList<Any>) =
+        holder.bind(data[position], payloads)
+
+    inner class ViewHolder(parent: ViewGroup) : BaseAdapter.VH(R.layout.contact_diary_edit_list_item, parent),
+        BindableVH<ContactDiaryLocation, ContactDiaryEditListItemBinding> {
+        override val viewBinding:
+            Lazy<ContactDiaryEditListItemBinding> =
+            lazy { ContactDiaryEditListItemBinding.bind(itemView) }
+
+        override val onBindData:
+            ContactDiaryEditListItemBinding.(item: ContactDiaryLocation, payloads: List<Any>) -> Unit =
+            { location, _ ->
+                name.text = location.locationName
+                itemContainer.apply {
+                    setOnClickListener { onItemClicked(location) }
+                    contentDescription = getContentDescriptionString(location)
+                    setClickLabel(clickLabelString)
+                }
+            }
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/adapter/PersonEditAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/adapter/PersonEditAdapter.kt
new file mode 100644
index 000000000..c241ecef2
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/edit/adapter/PersonEditAdapter.kt
@@ -0,0 +1,40 @@
+package de.rki.coronawarnapp.contactdiary.ui.edit.adapter
+
+import android.view.ViewGroup
+import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.contactdiary.model.ContactDiaryPerson
+import de.rki.coronawarnapp.contactdiary.util.AbstractAdapter
+import de.rki.coronawarnapp.contactdiary.util.setClickLabel
+import de.rki.coronawarnapp.databinding.ContactDiaryEditListItemBinding
+import de.rki.coronawarnapp.ui.lists.BaseAdapter
+import de.rki.coronawarnapp.util.lists.BindableVH
+
+internal class PersonEditAdapter(
+    private val clickLabelString: String,
+    private val getContentDescriptionString: (ContactDiaryPerson) -> String,
+    private val onItemClicked: (item: ContactDiaryPerson) -> Unit
+) : AbstractAdapter<ContactDiaryPerson, PersonEditAdapter.ViewHolder>() {
+
+    override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(parent)
+
+    override fun onBindBaseVH(holder: ViewHolder, position: Int, payloads: MutableList<Any>) =
+        holder.bind(data[position], payloads)
+
+    inner class ViewHolder(parent: ViewGroup) : BaseAdapter.VH(R.layout.contact_diary_edit_list_item, parent),
+        BindableVH<ContactDiaryPerson, ContactDiaryEditListItemBinding> {
+        override val viewBinding:
+            Lazy<ContactDiaryEditListItemBinding> =
+            lazy { ContactDiaryEditListItemBinding.bind(itemView) }
+
+        override val onBindData:
+            ContactDiaryEditListItemBinding.(item: ContactDiaryPerson, payloads: List<Any>) -> Unit =
+            { person, _ ->
+                name.text = person.fullName
+                itemContainer.apply {
+                    setOnClickListener { onItemClicked(person) }
+                    contentDescription = getContentDescriptionString(person)
+                    setClickLabel(clickLabelString)
+                }
+            }
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt
index dc4624cda..4cef4c67c 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt
@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.contactdiary.ui.overview
 import android.os.Bundle
 import android.view.View
 import android.view.accessibility.AccessibilityEvent
+import androidx.appcompat.widget.Toolbar
 import androidx.core.app.ShareCompat
 import androidx.fragment.app.Fragment
 import de.rki.coronawarnapp.R
@@ -23,7 +24,6 @@ import javax.inject.Inject
 class ContactDiaryOverviewFragment : Fragment(R.layout.contact_diary_overview_fragment), AutoInject {
 
     @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
-    @Inject lateinit var contactDiaryOverviewMenu: ContactDiaryOverviewMenu
     private val vm: ContactDiaryOverviewViewModel by cwaViewModels { viewModelFactory }
     private val binding: ContactDiaryOverviewFragmentBinding by viewBindingLazy()
 
@@ -35,7 +35,7 @@ class ContactDiaryOverviewFragment : Fragment(R.layout.contact_diary_overview_fr
             { vm.onItemPress(it) }
         )
 
-        setupToolbar()
+        setupMenu(binding.toolbar)
 
         binding.apply {
             contactDiaryOverviewRecyclerview.adapter = adapter
@@ -89,7 +89,37 @@ class ContactDiaryOverviewFragment : Fragment(R.layout.contact_diary_overview_fr
         }
     }
 
-    private fun setupToolbar() {
-        contactDiaryOverviewMenu.setupMenu(binding.toolbar)
+    private fun setupMenu(toolbar: Toolbar) = toolbar.apply {
+        inflateMenu(R.menu.menu_contact_diary_overview)
+        setOnMenuItemClickListener {
+            when (it.itemId) {
+                R.id.menu_contact_diary_information -> {
+                    doNavigate(
+                        ContactDiaryOverviewFragmentDirections
+                            .actionContactDiaryOverviewFragmentToContactDiaryOnboardingFragment()
+                    )
+                    true
+                }
+                R.id.menu_contact_diary_export_entries -> {
+                    vm.onExportPress(context)
+                    true
+                }
+                R.id.menu_contact_diary_edit_persons -> {
+                    doNavigate(
+                        ContactDiaryOverviewFragmentDirections
+                            .actionContactDiaryOverviewFragmentToContactDiaryEditPersonsFragment()
+                    )
+                    true
+                }
+                R.id.menu_contact_diary_edit_locations -> {
+                    doNavigate(
+                        ContactDiaryOverviewFragmentDirections
+                            .actionContactDiaryOverviewFragmentToContactDiaryEditLocationsFragment()
+                    )
+                    true
+                }
+                else -> onOptionsItemSelected(it)
+            }
+        }
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewMenu.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewMenu.kt
deleted file mode 100644
index 048c25a9f..000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewMenu.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-package de.rki.coronawarnapp.contactdiary.ui.overview
-
-import androidx.appcompat.widget.Toolbar
-import androidx.navigation.NavController
-import androidx.navigation.fragment.findNavController
-import de.rki.coronawarnapp.R
-import de.rki.coronawarnapp.ui.doNavigate
-import de.rki.coronawarnapp.util.viewmodel.cwaViewModels
-import javax.inject.Inject
-
-// TODO(Remove this useless class)
-class ContactDiaryOverviewMenu @Inject constructor(
-    private val contactDiaryOverviewFragment: ContactDiaryOverviewFragment
-) {
-
-    private val navController: NavController
-        get() = contactDiaryOverviewFragment.findNavController()
-    private val vm: ContactDiaryOverviewViewModel by contactDiaryOverviewFragment.cwaViewModels {
-        contactDiaryOverviewFragment.viewModelFactory
-    }
-
-    fun setupMenu(toolbar: Toolbar) = toolbar.apply {
-        inflateMenu(R.menu.menu_contact_diary_overview)
-        setOnMenuItemClickListener {
-            when (it.itemId) {
-                R.id.menu_contact_diary_information -> {
-                    navController.doNavigate(
-                        ContactDiaryOverviewFragmentDirections
-                            .actionContactDiaryOverviewFragmentToContactDiaryOnboardingFragment()
-                    )
-                    true
-                }
-                R.id.menu_contact_diary_export_entries -> {
-                    vm.onExportPress(context)
-                    true }
-                R.id.menu_contact_diary_edit_persons -> {
-                    navController.doNavigate(
-                        ContactDiaryOverviewFragmentDirections
-                            .actionContactDiaryOverviewFragmentToContactDiaryEditPersonsFragment())
-                    true
-                }
-                R.id.menu_contact_diary_edit_locations -> {
-                    navController.doNavigate(
-                        ContactDiaryOverviewFragmentDirections
-                            .actionContactDiaryOverviewFragmentToContactDiaryEditLocationsFragment())
-                    true
-                }
-                else -> contactDiaryOverviewFragment.onOptionsItemSelected(it)
-            }
-        }
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt
index 554bf6d88..a0dbcbfae 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt
@@ -139,7 +139,9 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(
         }
     }
 
-    private fun List<String>.addToStringBuilder(sb: StringBuilder, dateString: String) = sorted()
+    private fun List<String>.addToStringBuilder(sb: StringBuilder, dateString: String) = sortedBy {
+        it.toLowerCase(Locale.ROOT)
+    }
         .forEach { sb.appendLine("$dateString $it") }
 
     // According to tech spec german locale only
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt
index 05a3a950d..3e3c3a730 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt
@@ -1,67 +1,54 @@
 package de.rki.coronawarnapp.contactdiary.ui.overview.adapter
 
-import android.view.LayoutInflater
 import android.view.ViewGroup
 import androidx.core.view.isGone
-import androidx.recyclerview.widget.RecyclerView
+import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.contactdiary.util.clearAndAddAll
 import de.rki.coronawarnapp.databinding.ContactDiaryOverviewListItemBinding
+import de.rki.coronawarnapp.ui.lists.BaseAdapter
+import de.rki.coronawarnapp.util.lists.BindableVH
 import org.joda.time.LocalDate
 
 class ContactDiaryOverviewAdapter(
     private val dateFormatter: (LocalDate) -> String,
     private val dateFormatterForAccessibility: (LocalDate) -> String,
     private val onItemSelectionListener: (ListItem) -> Unit
-) :
-    RecyclerView.Adapter<ContactDiaryOverviewAdapter.OverviewElementHolder>() {
+) : BaseAdapter<ContactDiaryOverviewAdapter.OverviewElementHolder>() {
+
     private val elements: MutableList<ListItem> = mutableListOf()
 
     fun setItems(elements: List<ListItem>) {
-        this.elements.clear()
-        this.elements += elements
+        this.elements.clearAndAddAll(elements)
         notifyDataSetChanged()
     }
 
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OverviewElementHolder {
-        val inflater = LayoutInflater.from(parent.context)
-        return OverviewElementHolder(
-            ContactDiaryOverviewListItemBinding.inflate(
-                inflater,
-                parent,
-                false
-            )
-        )
-    }
-
     override fun getItemCount() = elements.size
 
-    override fun onBindViewHolder(holder: OverviewElementHolder, position: Int) {
-        holder.bind(elements[position], dateFormatter, dateFormatterForAccessibility, onItemSelectionListener)
-    }
-
-    class OverviewElementHolder(private val viewDataBinding: ContactDiaryOverviewListItemBinding) :
-        RecyclerView.ViewHolder(viewDataBinding.root) {
-        private val nestedItemAdapter = ContactDiaryOverviewNestedAdapter()
-
-        init {
-            viewDataBinding.contactDiaryOverviewNestedRecyclerView.adapter = nestedItemAdapter
-        }
+    override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): OverviewElementHolder = OverviewElementHolder(parent)
 
-        fun bind(
-            item: ListItem,
-            dateFormatter: (LocalDate) -> String,
-            dateFormatterForAccessibility: (LocalDate) -> String,
-            onElementSelectionListener: (ListItem) -> Unit
-        ) {
-            viewDataBinding.contactDiaryOverviewElementName.text = dateFormatter(item.date)
+    override fun onBindBaseVH(holder: OverviewElementHolder, position: Int, payloads: MutableList<Any>) =
+        holder.bind(elements[position], payloads)
 
-            viewDataBinding.contactDiaryOverviewElementName.contentDescription =
-                dateFormatterForAccessibility(item.date)
+    inner class OverviewElementHolder(parent: ViewGroup) :
+        BaseAdapter.VH(R.layout.contact_diary_overview_list_item, parent),
+        BindableVH<ListItem, ContactDiaryOverviewListItemBinding> {
 
-            viewDataBinding.contactDiaryOverviewElementBody.setOnClickListener { onElementSelectionListener(item) }
+        override val viewBinding: Lazy<ContactDiaryOverviewListItemBinding> =
+            lazy { ContactDiaryOverviewListItemBinding.bind(itemView) }
 
-            viewDataBinding.contactDiaryOverviewNestedElementGroup.isGone = item.data.isEmpty()
+        private val nestedItemAdapter = ContactDiaryOverviewNestedAdapter()
 
-            nestedItemAdapter.setItems(item.data)
+        init {
+            viewBinding.value.contactDiaryOverviewNestedRecyclerView.adapter = nestedItemAdapter
         }
+
+        override val onBindData: ContactDiaryOverviewListItemBinding.(item: ListItem, payloads: List<Any>) -> Unit =
+            { item, _ ->
+                contactDiaryOverviewElementName.text = dateFormatter(item.date)
+                contactDiaryOverviewElementName.contentDescription = dateFormatterForAccessibility(item.date)
+                contactDiaryOverviewElementBody.setOnClickListener { onItemSelectionListener(item) }
+                contactDiaryOverviewNestedElementGroup.isGone = item.data.isEmpty()
+                nestedItemAdapter.setItems(item.data)
+            }
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt
index b8cd8b56d..e7835cb12 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt
@@ -1,37 +1,41 @@
 package de.rki.coronawarnapp.contactdiary.ui.overview.adapter
 
-import android.view.LayoutInflater
 import android.view.ViewGroup
-import androidx.recyclerview.widget.RecyclerView
+import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.contactdiary.util.clearAndAddAll
 import de.rki.coronawarnapp.databinding.ContactDiaryOverviewNestedListItemBinding
+import de.rki.coronawarnapp.ui.lists.BaseAdapter
+import de.rki.coronawarnapp.util.lists.BindableVH
 
 class ContactDiaryOverviewNestedAdapter :
-    RecyclerView.Adapter<ContactDiaryOverviewNestedAdapter.NestedItemViewHolder>() {
+    BaseAdapter<ContactDiaryOverviewNestedAdapter.NestedItemViewHolder>() {
 
     private val dataList: MutableList<ListItem.Data> = mutableListOf()
 
     fun setItems(dataList: List<ListItem.Data>) {
-        this.dataList.clear()
-        this.dataList += dataList
+        this.dataList.clearAndAddAll(dataList)
         notifyDataSetChanged()
     }
 
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NestedItemViewHolder {
-        val inflater = LayoutInflater.from(parent.context)
-        return NestedItemViewHolder(ContactDiaryOverviewNestedListItemBinding.inflate(inflater, parent, false))
-    }
+    override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): NestedItemViewHolder = NestedItemViewHolder(parent)
 
-    override fun onBindViewHolder(holder: NestedItemViewHolder, position: Int) {
-        holder.bind(dataList[position])
-    }
+    override fun onBindBaseVH(holder: NestedItemViewHolder, position: Int, payloads: MutableList<Any>) =
+        holder.bind(dataList[position], payloads)
 
     override fun getItemCount(): Int = dataList.size
 
-    class NestedItemViewHolder(private val viewBinding: ContactDiaryOverviewNestedListItemBinding) :
-        RecyclerView.ViewHolder(viewBinding.root) {
-        fun bind(data: ListItem.Data) {
-            viewBinding.contactDiaryOverviewElementImage.setImageResource(data.drawableId)
-            viewBinding.contactDiaryOverviewElementName.text = data.text
-        }
+    class NestedItemViewHolder(parent: ViewGroup) :
+        BaseAdapter.VH(R.layout.contact_diary_overview_nested_list_item, parent),
+        BindableVH<ListItem.Data, ContactDiaryOverviewNestedListItemBinding> {
+        override val viewBinding:
+            Lazy<ContactDiaryOverviewNestedListItemBinding> =
+            lazy { ContactDiaryOverviewNestedListItemBinding.bind(itemView) }
+
+        override val onBindData:
+            ContactDiaryOverviewNestedListItemBinding.(item: ListItem.Data, payloads: List<Any>) -> Unit =
+            { key, _ ->
+                contactDiaryOverviewElementImage.setImageResource(key.drawableId)
+                contactDiaryOverviewElementName.text = key.text
+            }
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/sheets/location/ContactDiaryLocationBottomSheetDialogViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/sheets/location/ContactDiaryLocationBottomSheetDialogViewModel.kt
index c59fb7368..7e639168a 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/sheets/location/ContactDiaryLocationBottomSheetDialogViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/sheets/location/ContactDiaryLocationBottomSheetDialogViewModel.kt
@@ -97,5 +97,3 @@ class ContactDiaryLocationBottomSheetDialogViewModel @AssistedInject constructor
         fun create(addedAt: String?): ContactDiaryLocationBottomSheetDialogViewModel
     }
 }
-
-private const val MAX_LOCATION_NAME_LENGTH = 250
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/sheets/person/ContactDiaryPersonBottomSheetDialogViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/sheets/person/ContactDiaryPersonBottomSheetDialogViewModel.kt
index 82c42dd13..eff32df76 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/sheets/person/ContactDiaryPersonBottomSheetDialogViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/sheets/person/ContactDiaryPersonBottomSheetDialogViewModel.kt
@@ -97,5 +97,3 @@ class ContactDiaryPersonBottomSheetDialogViewModel @AssistedInject constructor(
         fun create(addedAt: String?): ContactDiaryPersonBottomSheetDialogViewModel
     }
 }
-
-private const val MAX_PERSON_NAME_LENGTH = 250
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/util/AbstractAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/util/AbstractAdapter.kt
new file mode 100644
index 000000000..567c2c549
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/util/AbstractAdapter.kt
@@ -0,0 +1,15 @@
+package de.rki.coronawarnapp.contactdiary.util
+
+import de.rki.coronawarnapp.ui.lists.BaseAdapter
+import de.rki.coronawarnapp.util.lists.HasStableId
+import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter
+import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer
+
+internal abstract class AbstractAdapter<T : HasStableId, U : BaseAdapter.VH> : BaseAdapter<U>(),
+    AsyncDiffUtilAdapter<T> {
+    override val asyncDiffer: AsyncDiffer<T> = AsyncDiffer(this)
+
+    override fun getItemCount(): Int = data.size
+
+    override fun getItemId(position: Int): Long = data[position].stableId
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/util/ContactDiaryExtensions.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/util/ContactDiaryExtensions.kt
index 8149e4cf9..6348145c6 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/util/ContactDiaryExtensions.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/util/ContactDiaryExtensions.kt
@@ -97,3 +97,8 @@ fun View.setClickLabel(label: String) {
         }
     })
 }
+
+fun <T> MutableList<T>.clearAndAddAll(newItems: List<T>) {
+    clear()
+    addAll(newItems)
+}
-- 
GitLab