From d37456e4c5a504e544b1367411e6bba0a14ed255 Mon Sep 17 00:00:00 2001 From: BMItter Date: Mon, 15 Mar 2021 15:27:16 +0100 Subject: [PATCH 01/30] string preparation --- .../src/main/res/values-de/contact_diary_strings.xml | 2 ++ Corona-Warn-App/src/main/res/values/contact_diary_strings.xml | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml index 14b896c15e6..0927bb914c8 100644 --- a/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml @@ -77,6 +77,8 @@ "aufgrund von mehreren Begegnungen mit niedrigem Risiko." "Diese müssen nicht in Zusammenhang mit den von Ihnen erfassten Personen und Orten stehen." + + "aufgrund ihrer Anwesenheit bei:" diff --git a/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml index 83bd6e59559..9e19375dc66 100644 --- a/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml +++ b/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml @@ -77,7 +77,8 @@ "based on multiple exposures with low risk." "They are not necessarily related to the people and places you have recorded." - + + "" "A closed book with a bookmark" From ba7846b9c33b7eaade81e5f177edb925538331d2 Mon Sep 17 00:00:00 2001 From: BMItter Date: Tue, 16 Mar 2021 17:22:07 +0100 Subject: [PATCH 02/30] Use modular recycler view for dairy days, adapter, items, layouts --- .../ui/overview/adapter/day/DayDataAdapter.kt | 44 +++++++++++++ .../ui/overview/adapter/day/DayDataItem.kt | 5 ++ .../adapter/day/contact/ContactAdapter.kt | 64 +++++++++++++++++++ .../adapter/day/contact/ContactItem.kt | 25 ++++++++ .../overview/adapter/day/contact/ContactVH.kt | 23 +++++++ .../overview/adapter/day/header/HeaderItem.kt | 10 +++ .../overview/adapter/day/header/HeaderVH.kt | 23 +++++++ .../day/riskcalculated/RiskCalculatedItem.kt | 15 +++++ .../day/riskcalculated/RiskCalculatedVH.kt | 31 +++++++++ ...t_diary_overview_day_list_item_contact.xml | 19 ++++++ ...ct_diary_overview_day_list_item_header.xml | 34 ++++++++++ ...overview_day_list_item_risk_calculated.xml | 49 ++++++++++++++ 12 files changed, 342 insertions(+) create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataItem.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactAdapter.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactItem.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedItem.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedVH.kt create mode 100644 Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_contact.xml create mode 100644 Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml create mode 100644 Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_calculated.xml diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt new file mode 100644 index 00000000000..a24eeef110b --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt @@ -0,0 +1,44 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day + +import android.view.ViewGroup +import androidx.annotation.LayoutRes +import androidx.viewbinding.ViewBinding +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactVH +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderVH +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated.RiskCalculatedItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated.RiskCalculatedVH +import de.rki.coronawarnapp.util.lists.BindableVH +import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter +import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer +import de.rki.coronawarnapp.util.lists.modular.ModularAdapter +import de.rki.coronawarnapp.util.lists.modular.mods.DataBinderMod +import de.rki.coronawarnapp.util.lists.modular.mods.StableIdMod +import de.rki.coronawarnapp.util.lists.modular.mods.TypedVHCreatorMod + +class DayDataAdapter : + ModularAdapter>(), + AsyncDiffUtilAdapter { + + override val asyncDiffer: AsyncDiffer = AsyncDiffer(adapter = this) + + init { + modules.addAll( + listOf( + StableIdMod(data), + DataBinderMod>(data), + TypedVHCreatorMod({ data[it] is HeaderItem }) { HeaderVH(it) }, + TypedVHCreatorMod({ data[it] is RiskCalculatedItem }) { RiskCalculatedVH(it) }, + TypedVHCreatorMod({ data[it] is ContactItem }) { ContactVH(it) } + ) + ) + } + + override fun getItemCount(): Int = data.size + + abstract class ItemVH( + @LayoutRes layoutRes: Int, + parent: ViewGroup + ) : ModularAdapter.VH(layoutRes, parent), BindableVH +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataItem.kt new file mode 100644 index 00000000000..b508a2b31c4 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataItem.kt @@ -0,0 +1,5 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day + +import de.rki.coronawarnapp.util.lists.HasStableId + +interface DayDataItem : HasStableId diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactAdapter.kt new file mode 100644 index 00000000000..a785fd872b1 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactAdapter.kt @@ -0,0 +1,64 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact + +import android.view.View +import android.view.ViewGroup +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.contactdiary.util.clearAndAddAll +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewNestedListItemBinding +import de.rki.coronawarnapp.ui.durationpicker.toReadableDuration +import de.rki.coronawarnapp.ui.lists.BaseAdapter +import de.rki.coronawarnapp.util.lists.BindableVH +import org.joda.time.Duration + +class ContactAdapter : BaseAdapter() { + + private val dataList: MutableList = mutableListOf() + + fun setItems(dataList: List) { + this.dataList.clearAndAddAll(dataList) + notifyDataSetChanged() + } + + override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): ContactItemViewHolder = ContactItemViewHolder(parent) + + override fun onBindBaseVH(holder: ContactItemViewHolder, position: Int, payloads: MutableList) { + holder.bind(dataList[position], payloads) + } + + override fun getItemCount(): Int = dataList.size + + inner class ContactItemViewHolder(parent: ViewGroup) : + BaseAdapter.VH(R.layout.contact_diary_overview_nested_list_item, parent), + BindableVH { + override val viewBinding: Lazy = + lazy { ContactDiaryOverviewNestedListItemBinding.bind(itemView) } + + override val onBindData: ContactDiaryOverviewNestedListItemBinding.( + item: ContactItem.Data, + payloads: List + ) -> Unit = { key, _ -> + contactDiaryOverviewElementImage.setImageResource(key.drawableId) + contactDiaryOverviewElementName.text = key.name + contactDiaryOverviewElementName.contentDescription = when (key.type) { + ContactItem.Type.LOCATION -> context.getString(R.string.accessibility_location, key.name) + ContactItem.Type.PERSON -> context.getString(R.string.accessibility_person, key.name) + } + val attributes = getAttributes(key.duration, key.attributes, key.circumstances) + if (attributes.isNotEmpty()) { + contactDiaryOverviewElementAttributes.text = attributes + } else contactDiaryOverviewElementAttributes.visibility = View.GONE + } + + private fun getAttributes(duration: Duration?, resources: List?, circumstances: String?): String = + mutableListOf().apply { + duration?.run { + if (duration != Duration.ZERO) { + val durationSuffix = context.getString(R.string.contact_diary_overview_location_duration_suffix) + add(toReadableDuration(suffix = durationSuffix)) + } + } + resources?.run { forEach { add(context.getString(it)) } } + circumstances?.run { add(this) } + }.filter { it.isNotEmpty() }.joinToString() + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactItem.kt new file mode 100644 index 00000000000..b8bb5f01f95 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactItem.kt @@ -0,0 +1,25 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact + +import androidx.annotation.DrawableRes +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataItem +import org.joda.time.Duration + +data class ContactItem( + val data: List +) : DayDataItem { + + override val stableId: Long = data.hashCode().toLong() + + data class Data( + @DrawableRes val drawableId: Int, + val name: String, + val duration: Duration?, + val attributes: List?, + val circumstances: String?, + val type: Type + ) + + enum class Type { + LOCATION, PERSON + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt new file mode 100644 index 00000000000..9839f0a354f --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt @@ -0,0 +1,23 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact + +import android.view.ViewGroup +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataAdapter +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemContactBinding + +class ContactVH(parent: ViewGroup) : + DayDataAdapter.ItemVH( + layoutRes = R.layout.contact_diary_overview_day_list_item_contact, + parent = parent + ) { + + private val contactAdapter by lazy { ContactAdapter() } + + override val viewBinding: Lazy = + lazy { ContactDiaryOverviewDayListItemContactBinding.bind(itemView) } + + override val onBindData: ContactDiaryOverviewDayListItemContactBinding.(item: ContactItem, payloads: List) -> Unit = + { item, _ -> + recyclerView.adapter = contactAdapter.apply { setItems(item.data) } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt new file mode 100644 index 00000000000..1848cb0160f --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt @@ -0,0 +1,10 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header + +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataItem +import org.joda.time.LocalDate + +data class HeaderItem( + val date: LocalDate +) : DayDataItem { + override val stableId: Long = date.hashCode().toLong() +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt new file mode 100644 index 00000000000..8dc26829a9c --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt @@ -0,0 +1,23 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header + +import android.view.ViewGroup +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataAdapter +import de.rki.coronawarnapp.contactdiary.util.getLocale +import de.rki.coronawarnapp.contactdiary.util.toFormattedDay +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemHeaderBinding + +class HeaderVH(parent: ViewGroup) : + DayDataAdapter.ItemVH( + layoutRes = R.layout.contact_diary_overview_day_list_item_header, + parent = parent + ) { + + override val viewBinding: Lazy = + lazy { ContactDiaryOverviewDayListItemHeaderBinding.bind(itemView) } + + override val onBindData: ContactDiaryOverviewDayListItemHeaderBinding.(item: HeaderItem, payloads: List) -> Unit = + { item, _ -> + name.text = item.date.toFormattedDay(context.getLocale()) + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedItem.kt new file mode 100644 index 00000000000..bfed27ee6f2 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedItem.kt @@ -0,0 +1,15 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated + +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataItem +import java.util.Objects + +data class RiskCalculatedItem( + @StringRes val title: Int, + @StringRes val body: Int, + @StringRes val bodyExtended: Int? = null, + @DrawableRes val drawableId: Int +) : DayDataItem { + override val stableId: Long = Objects.hash(title, body, bodyExtended, drawableId).toLong() +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedVH.kt new file mode 100644 index 00000000000..9c4d56d49ca --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedVH.kt @@ -0,0 +1,31 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated + +import android.view.ViewGroup +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataAdapter +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskCalculatedBinding + +class RiskCalculatedVH(parent: ViewGroup) : + DayDataAdapter.ItemVH( + layoutRes = R.layout.contact_diary_overview_day_list_item_risk_calculated, + parent = parent + ) { + + override val viewBinding: Lazy = + lazy { ContactDiaryOverviewDayListItemRiskCalculatedBinding.bind(itemView) } + + override val onBindData: ContactDiaryOverviewDayListItemRiskCalculatedBinding.(item: RiskCalculatedItem, payloads: List) -> Unit = + { item, _ -> + + contactDiaryOverviewItemRiskTitle.text = context.getString(item.title) + this.contactDiaryOverviewRiskItemImage.setImageResource(item.drawableId) + + val sb = StringBuilder().append(context.getString(item.body)) + + item.bodyExtended?.let { extend -> + sb.appendLine().append(context.getString(extend)) + } + + this.contactDiaryOverviewItemRiskBody.text = sb + } +} diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_contact.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_contact.xml new file mode 100644 index 00000000000..6cb0515742d --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_contact.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml new file mode 100644 index 00000000000..5bdfd478ee6 --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml @@ -0,0 +1,34 @@ + + + + + + + + \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_calculated.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_calculated.xml new file mode 100644 index 00000000000..5f32e1d3806 --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_calculated.xml @@ -0,0 +1,49 @@ + + + + + + + + + \ No newline at end of file From 8557e96696e14df92ffbfba69d45e9b0b9c41a9a Mon Sep 17 00:00:00 2001 From: BMItter Date: Wed, 17 Mar 2021 23:34:38 +0100 Subject: [PATCH 03/30] Use modular recycler view for dairy days - next --- .../overview/ContactDiaryOverviewViewModel.kt | 30 ++++++-- .../adapter/day/DayDataNestedAdapter.kt | 64 ---------------- .../overview/adapter/day/DayOverviewItem.kt | 27 +------ .../ui/overview/adapter/day/DayOverviewVH.kt | 38 +++------- .../contact_diary_overview_list_item.xml | 73 +------------------ 5 files changed, 35 insertions(+), 197 deletions(-) delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt 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 d1f5c152ec7..6877697495e 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 @@ -14,7 +14,11 @@ import de.rki.coronawarnapp.contactdiary.retention.ContactDiaryCleanTask import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository import de.rki.coronawarnapp.contactdiary.ui.exporter.ContactDiaryExporter import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated.RiskCalculatedItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem import de.rki.coronawarnapp.risk.result.AggregatedRiskPerDateResult import de.rki.coronawarnapp.risk.storage.RiskLevelStorage @@ -87,15 +91,25 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( riskLevelPerDateList ) return dateList.map { date -> + val items: MutableList = mutableListOf() + + items.add(HeaderItem(date)) + val dayData = getEncountersForDate(encounters, date) + getVisitsForDate(visits, date) - val risk = riskLevelPerDateList + riskLevelPerDateList .firstOrNull { riskLevelPerDate -> riskLevelPerDate.day == date } ?.toRisk(dayData.isNotEmpty()) - DayOverviewItem(date = date, data = dayData, risk = risk) { onItemPress(it) } + ?.also { items.add(it) } + + if (dayData.isNotEmpty()) { + items.add(ContactItem(dayData)) + } + + DayOverviewItem(date = date, dayData = items) { onItemPress(it) } } } - private fun AggregatedRiskPerDateResult.toRisk(locationOrPerson: Boolean): DayOverviewItem.Risk { + private fun AggregatedRiskPerDateResult.toRisk(locationOrPerson: Boolean): RiskCalculatedItem { @StringRes val title: Int @StringRes var body: Int = R.string.contact_diary_risk_body @DrawableRes val drawableId: Int @@ -116,7 +130,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( drawableId = R.drawable.ic_low_risk_alert } - return DayOverviewItem.Risk(title, body, bodyExtend, drawableId) + return RiskCalculatedItem(title, body, bodyExtend, drawableId) } private fun getEncountersForDate( @@ -125,13 +139,13 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( ) = personEncounterList .filter { personEncounter -> personEncounter.date == date } .map { personEncounter -> - DayOverviewItem.Data( + ContactItem.Data( R.drawable.ic_contact_diary_person_item, name = personEncounter.contactDiaryPerson.fullName, duration = null, attributes = getPersonAttributes(personEncounter), circumstances = personEncounter.circumstances, - DayOverviewItem.Type.PERSON + ContactItem.Type.PERSON ) } @@ -141,13 +155,13 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( ) = locationVisitList .filter { locationVisit -> locationVisit.date == date } .map { locationVisit -> - DayOverviewItem.Data( + ContactItem.Data( R.drawable.ic_contact_diary_location_item, locationVisit.contactDiaryLocation.locationName, duration = locationVisit.duration, attributes = null, circumstances = locationVisit.circumstances, - DayOverviewItem.Type.LOCATION + ContactItem.Type.LOCATION ) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt deleted file mode 100644 index b0cc6fb871c..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt +++ /dev/null @@ -1,64 +0,0 @@ -package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day - -import android.view.View -import android.view.ViewGroup -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.ui.durationpicker.toReadableDuration -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 -import org.joda.time.Duration - -class DayDataNestedAdapter : BaseAdapter() { - - private val dataList: MutableList = mutableListOf() - - fun setItems(dataList: List) { - this.dataList.clearAndAddAll(dataList) - notifyDataSetChanged() - } - - override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): NestedItemViewHolder = NestedItemViewHolder(parent) - - override fun onBindBaseVH(holder: NestedItemViewHolder, position: Int, payloads: MutableList) { - holder.bind(dataList[position], payloads) - } - - override fun getItemCount(): Int = dataList.size - - inner class NestedItemViewHolder(parent: ViewGroup) : - BaseAdapter.VH(R.layout.contact_diary_overview_nested_list_item, parent), - BindableVH { - override val viewBinding: Lazy = - lazy { ContactDiaryOverviewNestedListItemBinding.bind(itemView) } - - override val onBindData: ContactDiaryOverviewNestedListItemBinding.( - item: DayOverviewItem.Data, - payloads: List - ) -> Unit = { key, _ -> - contactDiaryOverviewElementImage.setImageResource(key.drawableId) - contactDiaryOverviewElementName.text = key.name - contactDiaryOverviewElementName.contentDescription = when (key.type) { - DayOverviewItem.Type.LOCATION -> context.getString(R.string.accessibility_location, key.name) - DayOverviewItem.Type.PERSON -> context.getString(R.string.accessibility_person, key.name) - } - val attributes = getAttributes(key.duration, key.attributes, key.circumstances) - if (attributes.isNotEmpty()) { - contactDiaryOverviewElementAttributes.text = attributes - } else contactDiaryOverviewElementAttributes.visibility = View.GONE - } - - private fun getAttributes(duration: Duration?, resources: List?, circumstances: String?): String = - mutableListOf().apply { - duration?.run { - if (duration != Duration.ZERO) { - val durationSuffix = context.getString(R.string.contact_diary_overview_location_duration_suffix) - add(toReadableDuration(suffix = durationSuffix)) - } - } - resources?.run { forEach { add(context.getString(it)) } } - circumstances?.run { add(this) } - }.filter { it.isNotEmpty() }.joinToString() - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt index 983df3ff329..4e5aaf6e430 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt @@ -1,37 +1,12 @@ package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day -import androidx.annotation.DrawableRes -import androidx.annotation.StringRes import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewItem -import org.joda.time.Duration import org.joda.time.LocalDate data class DayOverviewItem( val date: LocalDate, - val data: List, - val risk: Risk?, + val dayData: List, val onItemSelectionListener: (DayOverviewItem) -> Unit ) : DiaryOverviewItem { - override val stableId: Long = date.hashCode().toLong() - - data class Data( - @DrawableRes val drawableId: Int, - val name: String, - val duration: Duration?, - val attributes: List?, - val circumstances: String?, - val type: Type - ) - - data class Risk( - @StringRes val title: Int, - @StringRes val body: Int, - @StringRes val bodyExtended: Int? = null, - @DrawableRes val drawableId: Int - ) - - enum class Type { - LOCATION, PERSON - } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt index c52682b1c41..c33e7556eb5 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt @@ -1,13 +1,12 @@ package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day import android.view.ViewGroup -import androidx.core.view.isGone import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewAdapter import de.rki.coronawarnapp.contactdiary.util.getLocale -import de.rki.coronawarnapp.contactdiary.util.toFormattedDay import de.rki.coronawarnapp.contactdiary.util.toFormattedDayForAccessibility import de.rki.coronawarnapp.databinding.ContactDiaryOverviewListItemBinding +import de.rki.coronawarnapp.util.lists.diffutil.update class DayOverviewVH(parent: ViewGroup) : DiaryOverviewAdapter.ItemVH( @@ -15,41 +14,22 @@ class DayOverviewVH(parent: ViewGroup) : parent = parent ) { - private val nestedItemAdapter by lazy { DayDataNestedAdapter() } + private val dayDataAdapter by lazy { DayDataAdapter() } override val viewBinding: Lazy = lazy { ContactDiaryOverviewListItemBinding.bind(itemView) } override val onBindData: ContactDiaryOverviewListItemBinding.(item: DayOverviewItem, payloads: List) -> Unit = { item, _ -> - contactDiaryOverviewNestedRecyclerView.adapter = nestedItemAdapter - contactDiaryOverviewNestedRecyclerView.suppressLayout(true) - contactDiaryOverviewElementBody.setOnClickListener { item.onItemSelectionListener(item) } - - contactDiaryOverviewElementBody.contentDescription = - item.date.toFormattedDayForAccessibility(context.getLocale()) - - contactDiaryOverviewElementName.apply { - text = item.date.toFormattedDay(context.getLocale()) + dayRecyclerView.apply { + adapter = dayDataAdapter.apply { update(item.dayData) } + itemAnimator = null } - contactDiaryOverviewNestedElementGroup.isGone = item.data.isEmpty() - nestedItemAdapter.setItems(item.data) - - contactDiaryOverviewNestedListItemRisk.apply { - item.risk?.let { - this.contactDiaryOverviewRiskItem.isGone = false - this.contactDiaryOverviewItemRiskTitle.text = context.getString(it.title) - this.contactDiaryOverviewRiskItemImage.setImageResource(it.drawableId) - - val sb = StringBuilder().append(context.getString(it.body)) - - it.bodyExtended?.let { extend -> - sb.appendLine().append(context.getString(extend)) - } - - this.contactDiaryOverviewItemRiskBody.text = sb - } ?: run { this.contactDiaryOverviewRiskItem.isGone = true } + dayElementBody.apply { + contentDescription = item.date.toFormattedDayForAccessibility(context.getLocale()) + setOnClickListener { item.onItemSelectionListener(item) } } } } + diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml index 6082e367f53..c6a73f7e4a3 100644 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml @@ -2,7 +2,7 @@ - - - - - - - - - - - - - - + app:layout_constraintTop_toTopOf="parent" /> From 0e35f8480261cd69e390da0167cd76dbf4b29f2e Mon Sep 17 00:00:00 2001 From: BMItter Date: Fri, 19 Mar 2021 15:25:35 +0100 Subject: [PATCH 04/30] improved item handling --- .../ui/overview/adapter/day/DayDataAdapter.kt | 13 ++++++++----- .../ui/overview/adapter/day/DayOverviewVH.kt | 4 ++-- .../ui/overview/adapter/day/contact/ContactVH.kt | 5 ++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt index a24eeef110b..e8a9872c9f7 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt @@ -9,19 +9,17 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderIt import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderVH import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated.RiskCalculatedItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated.RiskCalculatedVH +import de.rki.coronawarnapp.contactdiary.util.clearAndAddAll import de.rki.coronawarnapp.util.lists.BindableVH -import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter -import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer import de.rki.coronawarnapp.util.lists.modular.ModularAdapter import de.rki.coronawarnapp.util.lists.modular.mods.DataBinderMod import de.rki.coronawarnapp.util.lists.modular.mods.StableIdMod import de.rki.coronawarnapp.util.lists.modular.mods.TypedVHCreatorMod class DayDataAdapter : - ModularAdapter>(), - AsyncDiffUtilAdapter { + ModularAdapter>() { - override val asyncDiffer: AsyncDiffer = AsyncDiffer(adapter = this) + private val data: MutableList = mutableListOf() init { modules.addAll( @@ -37,6 +35,11 @@ class DayDataAdapter : override fun getItemCount(): Int = data.size + fun setItems(dayDataList: List) { + data.clearAndAddAll(dayDataList) + notifyDataSetChanged() + } + abstract class ItemVH( @LayoutRes layoutRes: Int, parent: ViewGroup diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt index c33e7556eb5..0390fc56072 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt @@ -22,8 +22,8 @@ class DayOverviewVH(parent: ViewGroup) : override val onBindData: ContactDiaryOverviewListItemBinding.(item: DayOverviewItem, payloads: List) -> Unit = { item, _ -> dayRecyclerView.apply { - adapter = dayDataAdapter.apply { update(item.dayData) } - itemAnimator = null + adapter = dayDataAdapter.apply { setItems(item.dayData) } + suppressLayout(true) } dayElementBody.apply { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt index 9839f0a354f..dc8d44d7100 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt @@ -18,6 +18,9 @@ class ContactVH(parent: ViewGroup) : override val onBindData: ContactDiaryOverviewDayListItemContactBinding.(item: ContactItem, payloads: List) -> Unit = { item, _ -> - recyclerView.adapter = contactAdapter.apply { setItems(item.data) } + recyclerView.apply{ + adapter = contactAdapter.apply { setItems(item.data) } + suppressLayout(true) + } } } From 4d636ce8ee7a7070eeea07147f89a8cc64b24eb7 Mon Sep 17 00:00:00 2001 From: BMItter Date: Fri, 19 Mar 2021 15:30:08 +0100 Subject: [PATCH 05/30] Added dividers, diff util --- .../ui/overview/adapter/day/DayDataAdapter.kt | 14 ++++---- .../ui/overview/adapter/day/DayOverviewVH.kt | 11 ++++-- ...erticalDividerItemDecorationExcludeLast.kt | 35 +++++++++++++++++++ 3 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/lists/decorations/VerticalDividerItemDecorationExcludeLast.kt diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt index e8a9872c9f7..8a9c10b541a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt @@ -9,17 +9,20 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderIt import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderVH import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated.RiskCalculatedItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated.RiskCalculatedVH -import de.rki.coronawarnapp.contactdiary.util.clearAndAddAll import de.rki.coronawarnapp.util.lists.BindableVH +import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter +import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer import de.rki.coronawarnapp.util.lists.modular.ModularAdapter import de.rki.coronawarnapp.util.lists.modular.mods.DataBinderMod import de.rki.coronawarnapp.util.lists.modular.mods.StableIdMod import de.rki.coronawarnapp.util.lists.modular.mods.TypedVHCreatorMod class DayDataAdapter : - ModularAdapter>() { + ModularAdapter>(), + AsyncDiffUtilAdapter +{ - private val data: MutableList = mutableListOf() + override val asyncDiffer: AsyncDiffer = AsyncDiffer(adapter = this) init { modules.addAll( @@ -35,11 +38,6 @@ class DayDataAdapter : override fun getItemCount(): Int = data.size - fun setItems(dayDataList: List) { - data.clearAndAddAll(dayDataList) - notifyDataSetChanged() - } - abstract class ItemVH( @LayoutRes layoutRes: Int, parent: ViewGroup diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt index 0390fc56072..581163a8bc5 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt @@ -6,6 +6,7 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewAdapte import de.rki.coronawarnapp.contactdiary.util.getLocale import de.rki.coronawarnapp.contactdiary.util.toFormattedDayForAccessibility import de.rki.coronawarnapp.databinding.ContactDiaryOverviewListItemBinding +import de.rki.coronawarnapp.util.lists.decorations.VerticalDividerItemDecorationExcludeLast import de.rki.coronawarnapp.util.lists.diffutil.update class DayOverviewVH(parent: ViewGroup) : @@ -22,8 +23,14 @@ class DayOverviewVH(parent: ViewGroup) : override val onBindData: ContactDiaryOverviewListItemBinding.(item: DayOverviewItem, payloads: List) -> Unit = { item, _ -> dayRecyclerView.apply { - adapter = dayDataAdapter.apply { setItems(item.dayData) } - suppressLayout(true) + if (adapter == null) { + adapter = dayDataAdapter + addItemDecoration(VerticalDividerItemDecorationExcludeLast(context)) + // To avoid flickering + itemAnimator = null + } + dayDataAdapter.update(item.dayData) + //suppressLayout(true) } dayElementBody.apply { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/lists/decorations/VerticalDividerItemDecorationExcludeLast.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/lists/decorations/VerticalDividerItemDecorationExcludeLast.kt new file mode 100644 index 00000000000..829b0dd0b09 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/lists/decorations/VerticalDividerItemDecorationExcludeLast.kt @@ -0,0 +1,35 @@ +package de.rki.coronawarnapp.util.lists.decorations + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Rect +import androidx.core.view.children +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView + +class VerticalDividerItemDecorationExcludeLast( + context: Context +) : DividerItemDecoration(context, VERTICAL) { + + override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) { + val left = parent.paddingLeft + val right = parent.width - parent.paddingRight + parent.adapter?.let { adapter -> + parent.children // Displayed children on screen + .forEach { view -> + val childAdapterPosition = parent.getChildAdapterPosition(view) + .let { if (it == RecyclerView.NO_POSITION) return else it } + if (childAdapterPosition != adapter.itemCount - 1) { + drawable?.let { + val dividerDrawable = it + val params = view.layoutParams as RecyclerView.LayoutParams + val top = view.bottom + params.bottomMargin + val bottom = top + dividerDrawable.intrinsicHeight + dividerDrawable.bounds = Rect(left, top, right, bottom) + dividerDrawable.draw(canvas) + } + } + } + } + } +} From aa2511f45e00b2262c51fdff11fd79efd2e0220e Mon Sep 17 00:00:00 2001 From: BMItter Date: Mon, 22 Mar 2021 15:29:41 +0100 Subject: [PATCH 06/30] adjusted header logic --- .../ui/overview/ContactDiaryOverviewViewModel.kt | 9 +++++++-- .../ui/overview/adapter/day/header/HeaderItem.kt | 3 ++- .../ui/overview/adapter/day/header/HeaderVH.kt | 1 + .../contact_diary_overview_day_list_item_header.xml | 1 + 4 files changed, 11 insertions(+), 3 deletions(-) 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 6877697495e..6542a797c60 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 @@ -93,7 +93,8 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( return dateList.map { date -> val items: MutableList = mutableListOf() - items.add(HeaderItem(date)) + val headerItem = HeaderItem(date) { openDayFragment(it.date)} + items.add(headerItem) val dayData = getEncountersForDate(encounters, date) + getVisitsForDate(visits, date) riskLevelPerDateList @@ -170,7 +171,11 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( } fun onItemPress(listItem: DayOverviewItem) { - routeToScreen.postValue(ContactDiaryOverviewNavigationEvents.NavigateToContactDiaryDayFragment(listItem.date)) + openDayFragment(listItem.date) + } + + private fun openDayFragment(date: LocalDate) { + routeToScreen.postValue(ContactDiaryOverviewNavigationEvents.NavigateToContactDiaryDayFragment(date)) } private fun getPersonAttributes(personEncounter: ContactDiaryPersonEncounter): List = diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt index 1848cb0160f..10f37e25ef4 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt @@ -4,7 +4,8 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataItem import org.joda.time.LocalDate data class HeaderItem( - val date: LocalDate + val date: LocalDate, + val onclickListener: (HeaderItem) -> Unit = { } ) : DayDataItem { override val stableId: Long = date.hashCode().toLong() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt index 8dc26829a9c..b7aea443044 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt @@ -19,5 +19,6 @@ class HeaderVH(parent: ViewGroup) : override val onBindData: ContactDiaryOverviewDayListItemHeaderBinding.(item: HeaderItem, payloads: List) -> Unit = { item, _ -> name.text = item.date.toFormattedDay(context.getLocale()) + headerBody.setOnClickListener { item.onclickListener(item) } } } diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml index 5bdfd478ee6..eb7c905c470 100644 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml @@ -2,6 +2,7 @@ From 9ed86cc0e2cef6e6254b0e378fc74c5857e6fd26 Mon Sep 17 00:00:00 2001 From: BMItter Date: Tue, 23 Mar 2021 14:30:28 +0100 Subject: [PATCH 07/30] Added final risk event for diary, refactored ENFitem and ENFvh, cleanup --- .../overview/ContactDiaryOverviewViewModel.kt | 6 +- .../ui/overview/adapter/day/DayDataAdapter.kt | 6 +- .../RiskEnfItem.kt} | 4 +- .../RiskEnfVH.kt} | 16 ++--- ...diary_overview_day_list_item_risk_enf.xml} | 0 ...iary_overview_day_list_item_risk_event.xml | 59 +++++++++++++++++++ ...iew_day_list_item_risk_event_list_item.xml | 30 ++++++++++ 7 files changed, 105 insertions(+), 16 deletions(-) rename Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/{riskcalculated/RiskCalculatedItem.kt => riskenf/RiskEnfItem.kt} (91%) rename Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/{riskcalculated/RiskCalculatedVH.kt => riskenf/RiskEnfVH.kt} (70%) rename Corona-Warn-App/src/main/res/layout/{contact_diary_overview_day_list_item_risk_calculated.xml => contact_diary_overview_day_list_item_risk_enf.xml} (100%) create mode 100644 Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event.xml create mode 100644 Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml 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 6542a797c60..4128302668c 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 @@ -18,7 +18,7 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderItem -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated.RiskCalculatedItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem import de.rki.coronawarnapp.risk.result.AggregatedRiskPerDateResult import de.rki.coronawarnapp.risk.storage.RiskLevelStorage @@ -110,7 +110,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( } } - private fun AggregatedRiskPerDateResult.toRisk(locationOrPerson: Boolean): RiskCalculatedItem { + private fun AggregatedRiskPerDateResult.toRisk(locationOrPerson: Boolean): RiskEnfItem { @StringRes val title: Int @StringRes var body: Int = R.string.contact_diary_risk_body @DrawableRes val drawableId: Int @@ -131,7 +131,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( drawableId = R.drawable.ic_low_risk_alert } - return RiskCalculatedItem(title, body, bodyExtend, drawableId) + return RiskEnfItem(title, body, bodyExtend, drawableId) } private fun getEncountersForDate( diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt index 8a9c10b541a..69c4b5fa1fa 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt @@ -7,8 +7,8 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.Contact import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactVH import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderVH -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated.RiskCalculatedItem -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated.RiskCalculatedVH +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfVH import de.rki.coronawarnapp.util.lists.BindableVH import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer @@ -30,7 +30,7 @@ class DayDataAdapter : StableIdMod(data), DataBinderMod>(data), TypedVHCreatorMod({ data[it] is HeaderItem }) { HeaderVH(it) }, - TypedVHCreatorMod({ data[it] is RiskCalculatedItem }) { RiskCalculatedVH(it) }, + TypedVHCreatorMod({ data[it] is RiskEnfItem }) { RiskEnfVH(it) }, TypedVHCreatorMod({ data[it] is ContactItem }) { ContactVH(it) } ) ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfItem.kt similarity index 91% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedItem.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfItem.kt index bfed27ee6f2..264a40b7fd7 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedItem.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfItem.kt @@ -1,11 +1,11 @@ -package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf import androidx.annotation.DrawableRes import androidx.annotation.StringRes import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataItem import java.util.Objects -data class RiskCalculatedItem( +data class RiskEnfItem( @StringRes val title: Int, @StringRes val body: Int, @StringRes val bodyExtended: Int? = null, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt similarity index 70% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedVH.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt index 9c4d56d49ca..a893dd012b6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskcalculated/RiskCalculatedVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt @@ -1,20 +1,20 @@ -package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskcalculated +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf import android.view.ViewGroup import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataAdapter -import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskCalculatedBinding +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEnfBinding -class RiskCalculatedVH(parent: ViewGroup) : - DayDataAdapter.ItemVH( - layoutRes = R.layout.contact_diary_overview_day_list_item_risk_calculated, +class RiskEnfVH(parent: ViewGroup) : + DayDataAdapter.ItemVH( + layoutRes = R.layout.contact_diary_overview_day_list_item_risk_enf, parent = parent ) { - override val viewBinding: Lazy = - lazy { ContactDiaryOverviewDayListItemRiskCalculatedBinding.bind(itemView) } + override val viewBinding: Lazy = + lazy { ContactDiaryOverviewDayListItemRiskEnfBinding.bind(itemView) } - override val onBindData: ContactDiaryOverviewDayListItemRiskCalculatedBinding.(item: RiskCalculatedItem, payloads: List) -> Unit = + override val onBindData: ContactDiaryOverviewDayListItemRiskEnfBinding.(item: RiskEnfItem, payloads: List) -> Unit = { item, _ -> contactDiaryOverviewItemRiskTitle.text = context.getString(item.title) diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_calculated.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_enf.xml similarity index 100% rename from Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_calculated.xml rename to Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_enf.xml diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event.xml new file mode 100644 index 00000000000..88584805429 --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml new file mode 100644 index 00000000000..5c881789ca2 --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file From f395e60bb362cd76fddb6f05e7957d4df4b1c557 Mon Sep 17 00:00:00 2001 From: BMItter Date: Wed, 24 Mar 2021 13:30:14 +0100 Subject: [PATCH 08/30] final logic for risk event diary --- .../model/ContactDiaryLocationVisit.kt | 1 + .../model/DefaultContactDiaryLocationVisit.kt | 6 +- .../overview/ContactDiaryOverviewViewModel.kt | 178 +++++++++++++----- .../ui/overview/adapter/day/DayDataAdapter.kt | 6 +- .../adapter/day/riskevent/RiskEventAdapter.kt | 48 +++++ .../adapter/day/riskevent/RiskEventItem.kt | 23 +++ .../adapter/day/riskevent/RiskEventVH.kt | 36 ++++ .../risk/storage/BaseRiskLevelStorage.kt | 6 +- .../risk/storage/RiskLevelStorage.kt | 3 + ...iary_overview_day_list_item_risk_event.xml | 2 + ...iew_day_list_item_risk_event_list_item.xml | 13 +- .../res/values-de/contact_diary_strings.xml | 5 + .../src/main/res/values/colors.xml | 2 + .../main/res/values/contact_diary_strings.xml | 4 + .../src/main/res/values/dimens.xml | 3 + 15 files changed, 282 insertions(+), 54 deletions(-) create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventAdapter.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventItem.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocationVisit.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocationVisit.kt index d5eb4b2852a..e0073525378 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocationVisit.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocationVisit.kt @@ -14,6 +14,7 @@ interface ContactDiaryLocationVisit { */ val duration: Duration? val circumstances: String? + val checkInID: Long? } fun List.sortByNameAndIdASC(): List = diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryLocationVisit.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryLocationVisit.kt index e9c16848e2c..427767d5da1 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryLocationVisit.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/DefaultContactDiaryLocationVisit.kt @@ -8,7 +8,8 @@ data class DefaultContactDiaryLocationVisit( override val date: LocalDate, override val contactDiaryLocation: ContactDiaryLocation, override val duration: Duration? = null, - override val circumstances: String? = null + override val circumstances: String? = null, + override val checkInID: Long? = null ) : ContactDiaryLocationVisit fun ContactDiaryLocationVisit.toEditableVariant(): DefaultContactDiaryLocationVisit { @@ -18,6 +19,7 @@ fun ContactDiaryLocationVisit.toEditableVariant(): DefaultContactDiaryLocationVi date = date, contactDiaryLocation = contactDiaryLocation, duration = duration, - circumstances = circumstances + circumstances = circumstances, + checkInID = checkInID ) } 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 4128302668c..4f4df1918b1 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 @@ -19,10 +19,14 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem +import de.rki.coronawarnapp.risk.RiskState +import de.rki.coronawarnapp.risk.TraceLocationCheckInRisk import de.rki.coronawarnapp.risk.result.AggregatedRiskPerDateResult import de.rki.coronawarnapp.risk.storage.RiskLevelStorage import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass +import de.rki.coronawarnapp.storage.TracingSettings import de.rki.coronawarnapp.task.TaskController import de.rki.coronawarnapp.task.common.DefaultTaskRequest import de.rki.coronawarnapp.util.TimeAndDateExtensions.toLocalDate @@ -55,16 +59,18 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( private val personEncountersFlow = contactDiaryRepository.personEncounters private val riskLevelPerDateFlow = riskLevelStorage.aggregatedRiskPerDateResults + private val traceLocationCheckInRiskFlow = riskLevelStorage.allTraceLocationCheckInRisk val listItems = combine( flowOf(dates), locationVisitsFlow, personEncountersFlow, - riskLevelPerDateFlow - ) { dateList, locationVisists, personEncounters, riskLevelPerDateList -> + riskLevelPerDateFlow, + traceLocationCheckInRiskFlow + ) { dateList, locationVisists, personEncounters, riskLevelPerDateList, traceLocationCheckInRiskList -> mutableListOf().apply { add(OverviewSubHeaderItem) - addAll(createListItemList(dateList, locationVisists, personEncounters, riskLevelPerDateList)) + addAll(createListItemList(dateList, locationVisists, personEncounters, riskLevelPerDateList, traceLocationCheckInRiskList)) }.toList() }.asLiveData(dispatcherProvider.Default) @@ -81,31 +87,50 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( dateList: List, visits: List, encounters: List, - riskLevelPerDateList: List + riskLevelPerDateList: List, + traceLocationCheckInRiskList: List ): List { Timber.v( - "createListItemList(dateList=%s, visits=%s, encounters=%s, riskLevelPerDateList=%s", + "createListItemList(dateList=%s, visits=%s, encounters=%s, riskLevelPerDateList=%s, traceLocationCheckInRiskList=%s", dateList, visits, encounters, - riskLevelPerDateList + riskLevelPerDateList, + traceLocationCheckInRiskList ) return dateList.map { date -> - val items: MutableList = mutableListOf() - val headerItem = HeaderItem(date) { openDayFragment(it.date)} - items.add(headerItem) + val visitsForDate = visits.filter { it.date == date } + val encountersForDate = encounters.filter { it.date == date } + val traceLocationCheckInRisksForDate = traceLocationCheckInRiskList.filter { it.localDate == date } - val dayData = getEncountersForDate(encounters, date) + getVisitsForDate(visits, date) - riskLevelPerDateList - .firstOrNull { riskLevelPerDate -> riskLevelPerDate.day == date } - ?.toRisk(dayData.isNotEmpty()) - ?.also { items.add(it) } + val headerItem = HeaderItem(date) { openDayFragment(it.date) } - if (dayData.isNotEmpty()) { - items.add(ContactItem(dayData)) + val coreItemData = + encountersForDate.map { it.toContactItemData() } + visitsForDate.map { it.toContactItemData() } + val contactItem = when (coreItemData.isNotEmpty()) { + true -> ContactItem(data = coreItemData) + false -> null } + val riskEnf = riskLevelPerDateList + .firstOrNull { riskLevelPerDate -> riskLevelPerDate.day == date } + ?.toRisk(coreItemData.isNotEmpty()) + + val riskeventItem = visitsForDate + .map { it to traceLocationCheckInRisksForDate.find { checkInRisk -> checkInRisk.checkInId == it.checkInID } } + .toMap() + .filter { it.value != null } + .toRiskEventItem() + + // Items will be shown in order they are added to list + val items: List = listOf( + headerItem, + riskEnf, + riskeventItem, + contactItem + ).mapNotNull { it } + DayOverviewItem(date = date, dayData = items) { onItemPress(it) } } } @@ -134,38 +159,105 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( return RiskEnfItem(title, body, bodyExtend, drawableId) } - private fun getEncountersForDate( - personEncounterList: List, - date: LocalDate - ) = personEncounterList - .filter { personEncounter -> personEncounter.date == date } - .map { personEncounter -> - ContactItem.Data( - R.drawable.ic_contact_diary_person_item, - name = personEncounter.contactDiaryPerson.fullName, - duration = null, - attributes = getPersonAttributes(personEncounter), - circumstances = personEncounter.circumstances, - ContactItem.Type.PERSON - ) + private fun ContactDiaryPersonEncounter.toContactItemData(): ContactItem.Data = ContactItem.Data( + drawableId = R.drawable.ic_contact_diary_person_item, + name = contactDiaryPerson.fullName, + duration = null, + attributes = getPersonAttributes(this), + circumstances = circumstances, + type = ContactItem.Type.PERSON + ) + + private fun ContactDiaryLocationVisit.toContactItemData(): ContactItem.Data = ContactItem.Data( + drawableId = R.drawable.ic_contact_diary_location_item, + name = contactDiaryLocation.locationName, + duration = duration, + attributes = null, + circumstances = circumstances, + type = ContactItem.Type.LOCATION + ) + + private fun Map.toRiskEventItem(): RiskEventItem? { + + + TODO("Use Bulletspan...") + + val highRiskEvent = RiskEventItem.Event( + name = "Test high risk", + bulledPointColor = R.color.colorBulletPointHighRisk, + riskInfoAddition = R.string.contact_diary_event_risk_high + ) + + val lowRiskEvent = RiskEventItem.Event( + name = "Test low risk", + bulledPointColor = R.color.colorBulletPointLowRisk + ) + + return RiskEventItem( + title = R.string.contact_diary_high_risk_title, + body = R.string.contact_diary_event_risk_body, + drawableId = R.drawable.ic_high_risk_alert, + events = listOf(highRiskEvent, lowRiskEvent) + ) + + + if (isEmpty()) return null + + val isHighRisk = values.any { it?.riskState == RiskState.INCREASED_RISK } + + val body: Int = R.string.contact_diary_event_risk_body + val drawableID: Int + val title: Int + + when(isHighRisk) { + true -> { + drawableID = R.drawable.ic_high_risk_alert + title = R.string.contact_diary_high_risk_title + } + false -> { + drawableID = R.drawable.ic_low_risk_alert + title = R.string.contact_diary_low_risk_title + } } - private fun getVisitsForDate( - locationVisitList: List, - date: LocalDate - ) = locationVisitList - .filter { locationVisit -> locationVisit.date == date } - .map { locationVisit -> - ContactItem.Data( - R.drawable.ic_contact_diary_location_item, - locationVisit.contactDiaryLocation.locationName, - duration = locationVisit.duration, - attributes = null, - circumstances = locationVisit.circumstances, - ContactItem.Type.LOCATION + val events = mapNotNull { entry -> + if (entry.value == null) return null + + val name = entry.key.contactDiaryLocation.locationName + + val bulletPointColor: Int + var riskInfoAddition: Int? + + when(entry.value?.riskState == RiskState.INCREASED_RISK) { + true -> { + bulletPointColor = R.color.colorBulletPointHighRisk + riskInfoAddition = R.string.contact_diary_event_risk_high + } + false -> { + bulletPointColor = R.color.colorBulletPointLowRisk + riskInfoAddition = R.string.contact_diary_event_risk_low + } + } + + if (size < 2) riskInfoAddition = null + + RiskEventItem.Event( + name = name, + bulledPointColor = bulletPointColor, + riskInfoAddition = riskInfoAddition ) } + if (events.isEmpty()) return null + + return RiskEventItem( + title = title, + body = body, + drawableId = drawableID, + events = events + ) + } + fun onBackButtonPress() { routeToScreen.postValue(ContactDiaryOverviewNavigationEvents.NavigateToMainActivity) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt index 69c4b5fa1fa..0171e5172c6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt @@ -9,6 +9,8 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderIt import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderVH import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfVH +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventVH import de.rki.coronawarnapp.util.lists.BindableVH import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer @@ -19,8 +21,7 @@ import de.rki.coronawarnapp.util.lists.modular.mods.TypedVHCreatorMod class DayDataAdapter : ModularAdapter>(), - AsyncDiffUtilAdapter -{ + AsyncDiffUtilAdapter { override val asyncDiffer: AsyncDiffer = AsyncDiffer(adapter = this) @@ -31,6 +32,7 @@ class DayDataAdapter : DataBinderMod>(data), TypedVHCreatorMod({ data[it] is HeaderItem }) { HeaderVH(it) }, TypedVHCreatorMod({ data[it] is RiskEnfItem }) { RiskEnfVH(it) }, + TypedVHCreatorMod({ data[it] is RiskEventItem }) { RiskEventVH(it) }, TypedVHCreatorMod({ data[it] is ContactItem }) { ContactVH(it) } ) ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventAdapter.kt new file mode 100644 index 00000000000..96be4752692 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventAdapter.kt @@ -0,0 +1,48 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent + +import android.view.ViewGroup +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.contactdiary.util.clearAndAddAll +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEventListItemBinding +import de.rki.coronawarnapp.ui.lists.BaseAdapter +import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat +import de.rki.coronawarnapp.util.lists.BindableVH + +class RiskEventAdapter : BaseAdapter() { + + private val events: MutableList = mutableListOf() + + override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): RiskEventListItemVH = RiskEventListItemVH(parent) + + override fun onBindBaseVH(holder: RiskEventListItemVH, position: Int, payloads: MutableList) = + holder.bind(events[position], payloads) + + override fun getItemCount(): Int = events.size + + fun setItems(events: List) { + this.events.clearAndAddAll(events) + notifyDataSetChanged() + } + + inner class RiskEventListItemVH(parent: ViewGroup) : + BaseAdapter.VH(R.layout.contact_diary_overview_day_list_item_risk_event_list_item, parent), + BindableVH { + + override val viewBinding: Lazy = + lazy { ContactDiaryOverviewDayListItemRiskEventListItemBinding.bind(itemView) } + + override val onBindData: ContactDiaryOverviewDayListItemRiskEventListItemBinding.(item: RiskEventItem.Event, payloads: List) -> Unit = + { item, _ -> + + bulletPointImage.drawable?.setTint(context.getColorCompat(item.bulledPointColor)) + + var name = item.name + + item.riskInfoAddition?.let { + name += " (${context.getString(it)})" + } + + eventName.text = name + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventItem.kt new file mode 100644 index 00000000000..faa1f95d67b --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventItem.kt @@ -0,0 +1,23 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent + +import androidx.annotation.ColorRes +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataItem +import java.util.Objects + +data class RiskEventItem( + @StringRes val title: Int, + @StringRes val body: Int, + @DrawableRes val drawableId: Int, + val events: List +) : DayDataItem { + + override val stableId: Long = Objects.hash(title, body, drawableId, events).toLong() + + data class Event( + val name: String, + @ColorRes val bulledPointColor: Int, + @StringRes val riskInfoAddition: Int? = null + ) +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt new file mode 100644 index 00000000000..30f7bba16e2 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt @@ -0,0 +1,36 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent + +import android.view.ViewGroup +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataAdapter +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEventBinding + +class RiskEventVH(parent: ViewGroup) : + DayDataAdapter.ItemVH( + layoutRes = R.layout.contact_diary_overview_day_list_item_risk_event, + parent = parent + ) { + + private val riskEventAdapter: RiskEventAdapter by lazy { RiskEventAdapter() } + + override val viewBinding: Lazy = + lazy { ContactDiaryOverviewDayListItemRiskEventBinding.bind(itemView) } + + override val onBindData: ContactDiaryOverviewDayListItemRiskEventBinding.(item: RiskEventItem, payloads: List) -> Unit = + { item, _ -> + + with(context) { + contactDiaryOverviewItemRiskTitle.text = getString(item.title) + contactDiaryOverviewItemRiskBody.text = getString(item.body) + } + + contactDiaryOverviewRiskItemImage.setImageResource(item.drawableId) + + with(contactDiaryOverviewItemRiskEventList) { + if (adapter == null) { + adapter = riskEventAdapter + } + riskEventAdapter.setItems(item.events) + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorage.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorage.kt index 8b84f939545..c0e05402fa3 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorage.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorage.kt @@ -2,6 +2,7 @@ package de.rki.coronawarnapp.risk.storage import de.rki.coronawarnapp.risk.RiskLevelResult import de.rki.coronawarnapp.risk.RiskLevelTaskResult +import de.rki.coronawarnapp.risk.TraceLocationCheckInRisk import de.rki.coronawarnapp.risk.result.AggregatedRiskPerDateResult import de.rki.coronawarnapp.risk.storage.internal.RiskResultDatabase import de.rki.coronawarnapp.risk.storage.internal.riskresults.PersistedRiskLevelResultDao @@ -13,6 +14,7 @@ import de.rki.coronawarnapp.util.flow.shareLatest import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import timber.log.Timber @@ -127,7 +129,7 @@ abstract class BaseRiskLevelStorage constructor( aggregatedRiskPerDateResultTables.allEntries() .map { it.map { - persistedAggregatedRiskPerDateResult -> + persistedAggregatedRiskPerDateResult -> persistedAggregatedRiskPerDateResult.toAggregatedRiskPerDateResult() } } @@ -158,6 +160,8 @@ abstract class BaseRiskLevelStorage constructor( } } + override val allTraceLocationCheckInRisk: Flow> = flowOf(emptyList()) + internal abstract suspend fun storeExposureWindows(storedResultId: String, result: RiskLevelResult) internal abstract suspend fun deletedOrphanedExposureWindows() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/RiskLevelStorage.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/RiskLevelStorage.kt index 5a7ce88567b..521afd696e0 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/RiskLevelStorage.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/RiskLevelStorage.kt @@ -1,6 +1,7 @@ package de.rki.coronawarnapp.risk.storage import de.rki.coronawarnapp.risk.RiskLevelResult +import de.rki.coronawarnapp.risk.TraceLocationCheckInRisk import de.rki.coronawarnapp.risk.result.AggregatedRiskPerDateResult import kotlinx.coroutines.flow.Flow @@ -36,6 +37,8 @@ interface RiskLevelStorage { */ val aggregatedRiskPerDateResults: Flow> + val allTraceLocationCheckInRisk: Flow> + suspend fun deleteAggregatedRiskPerDateResults(results: List) suspend fun storeResult(result: RiskLevelResult) diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event.xml index 88584805429..b9586154d2e 100644 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event.xml +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event.xml @@ -47,10 +47,12 @@ tools:text="aufgrund Ihrer Anwesenheit bei:" /> + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> "Diese müssen nicht in Zusammenhang mit den von Ihnen erfassten Personen und Orten stehen." "aufgrund ihrer Anwesenheit bei:" + + "erhöhtes Risiko" + + "niedriges Risiko" + diff --git a/Corona-Warn-App/src/main/res/values/colors.xml b/Corona-Warn-App/src/main/res/values/colors.xml index a459e542b50..9fa3d6f5f41 100644 --- a/Corona-Warn-App/src/main/res/values/colors.xml +++ b/Corona-Warn-App/src/main/res/values/colors.xml @@ -77,6 +77,8 @@ #F5F5F5 #D7D7D7 #FFFFFF + #BF0F2D + #5D6E80 #747576 diff --git a/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml index 9e19375dc66..4eeff365812 100644 --- a/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml +++ b/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml @@ -79,6 +79,10 @@ "They are not necessarily related to the people and places you have recorded." "" + + "" + + "" "A closed book with a bookmark" diff --git a/Corona-Warn-App/src/main/res/values/dimens.xml b/Corona-Warn-App/src/main/res/values/dimens.xml index 833899f8978..76bfcb52370 100644 --- a/Corona-Warn-App/src/main/res/values/dimens.xml +++ b/Corona-Warn-App/src/main/res/values/dimens.xml @@ -131,6 +131,9 @@ @dimen/spacing_tiny @dimen/spacing_normal + 8dp + 10dp + 0dp From a3fd243d5590c9eeb2185999c17c87805a06861d Mon Sep 17 00:00:00 2001 From: BMItter Date: Thu, 25 Mar 2021 13:20:49 +0100 Subject: [PATCH 09/30] Adjusted baselne - diary extension --- ...ontact_diary_overview_day_list_item_risk_event_list_item.xml | 2 +- Corona-Warn-App/src/main/res/values/dimens.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml index 34d9132e009..8717b3d9602 100644 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml @@ -9,7 +9,7 @@ android:id="@+id/bullet_point_image" android:layout_width="@dimen/bullet_point_size_contact_diary" android:layout_height="@dimen/bullet_point_size_contact_diary" - android:baseline="@dimen/bullet_point_baseline_offset" + android:baseline="@dimen/bullet_point_baseline_offset_contact_diary" android:importantForAccessibility="no" android:src="@drawable/bullet_point" app:layout_constraintBaseline_toBaselineOf="@id/event_name" diff --git a/Corona-Warn-App/src/main/res/values/dimens.xml b/Corona-Warn-App/src/main/res/values/dimens.xml index 76bfcb52370..e2aebedecca 100644 --- a/Corona-Warn-App/src/main/res/values/dimens.xml +++ b/Corona-Warn-App/src/main/res/values/dimens.xml @@ -133,6 +133,7 @@ 8dp 10dp + 9dp 0dp From 802eb7d8d8c26e65184b616529a0b668b0134117 Mon Sep 17 00:00:00 2001 From: BMItter Date: Thu, 25 Mar 2021 19:39:04 +0100 Subject: [PATCH 10/30] diary db migration and new attributes for event extension --- .../3.json | 244 ++++++++++++++++++ .../model/ContactDiaryLocation.kt | 1 + .../model/DefaultContactDiaryLocation.kt | 3 +- .../storage/ContactDiaryDatabase.kt | 5 +- .../entity/ContactDiaryLocationEntity.kt | 6 +- .../entity/ContactDiaryLocationVisitEntity.kt | 6 +- .../ContactDiaryLocationVisitWrapper.kt | 3 +- .../ContactDiaryDatabaseMigration2To3.kt | 45 ++++ .../overview/ContactDiaryOverviewFragment.kt | 12 +- .../overview/ContactDiaryOverviewViewModel.kt | 5 +- 10 files changed, 308 insertions(+), 22 deletions(-) create mode 100644 Corona-Warn-App/schemas/de.rki.coronawarnapp.contactdiary.storage.ContactDiaryDatabase/3.json create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/internal/migrations/ContactDiaryDatabaseMigration2To3.kt diff --git a/Corona-Warn-App/schemas/de.rki.coronawarnapp.contactdiary.storage.ContactDiaryDatabase/3.json b/Corona-Warn-App/schemas/de.rki.coronawarnapp.contactdiary.storage.ContactDiaryDatabase/3.json new file mode 100644 index 00000000000..e0a59f046ba --- /dev/null +++ b/Corona-Warn-App/schemas/de.rki.coronawarnapp.contactdiary.storage.ContactDiaryDatabase/3.json @@ -0,0 +1,244 @@ +{ + "formatVersion": 1, + "database": { + "version": 3, + "identityHash": "f962ae2729d9b71eb3ed3fc51a110b95", + "entities": [ + { + "tableName": "locations", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationName` TEXT NOT NULL, `phoneNumber` TEXT, `emailAddress` TEXT, `traceLocationGUID` TEXT)", + "fields": [ + { + "fieldPath": "locationId", + "columnName": "locationId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "locationName", + "columnName": "locationName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "phoneNumber", + "columnName": "phoneNumber", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "emailAddress", + "columnName": "emailAddress", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "traceLocationGUID", + "columnName": "traceLocationGUID", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "locationId" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "locationvisits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `date` TEXT NOT NULL, `fkLocationId` INTEGER NOT NULL, `duration` INTEGER, `circumstances` TEXT, `checkInID` INTEGER, FOREIGN KEY(`fkLocationId`) REFERENCES `locations`(`locationId`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fkLocationId", + "columnName": "fkLocationId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "circumstances", + "columnName": "circumstances", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "checkInID", + "columnName": "checkInID", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_locationvisits_fkLocationId", + "unique": false, + "columnNames": [ + "fkLocationId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_locationvisits_fkLocationId` ON `${TABLE_NAME}` (`fkLocationId`)" + } + ], + "foreignKeys": [ + { + "table": "locations", + "onDelete": "CASCADE", + "onUpdate": "CASCADE", + "columns": [ + "fkLocationId" + ], + "referencedColumns": [ + "locationId" + ] + } + ] + }, + { + "tableName": "persons", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`personId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `fullName` TEXT NOT NULL, `phoneNumber` TEXT, `emailAddress` TEXT)", + "fields": [ + { + "fieldPath": "personId", + "columnName": "personId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "fullName", + "columnName": "fullName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "phoneNumber", + "columnName": "phoneNumber", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "emailAddress", + "columnName": "emailAddress", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "personId" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "personencounters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `date` TEXT NOT NULL, `fkPersonId` INTEGER NOT NULL, `durationClassification` TEXT, `withMask` INTEGER, `wasOutside` INTEGER, `circumstances` TEXT, FOREIGN KEY(`fkPersonId`) REFERENCES `persons`(`personId`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fkPersonId", + "columnName": "fkPersonId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "durationClassification", + "columnName": "durationClassification", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "withMask", + "columnName": "withMask", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "wasOutside", + "columnName": "wasOutside", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "circumstances", + "columnName": "circumstances", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_personencounters_fkPersonId", + "unique": false, + "columnNames": [ + "fkPersonId" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_personencounters_fkPersonId` ON `${TABLE_NAME}` (`fkPersonId`)" + } + ], + "foreignKeys": [ + { + "table": "persons", + "onDelete": "CASCADE", + "onUpdate": "CASCADE", + "columns": [ + "fkPersonId" + ], + "referencedColumns": [ + "personId" + ] + } + ] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f962ae2729d9b71eb3ed3fc51a110b95')" + ] + } +} \ No newline at end of file diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocation.kt index 1221b89bb7b..c0116d8026f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocation.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocation.kt @@ -8,6 +8,7 @@ interface ContactDiaryLocation : HasStableId { var locationName: String val phoneNumber: String? val emailAddress: String? + val traceLocationGUID: String? } fun List.sortByNameAndIdASC(): List = 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 3c20aa3cbdc..a9ef1b4bfcf 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 @@ -4,7 +4,8 @@ data class DefaultContactDiaryLocation( override val locationId: Long = 0L, override var locationName: String, override val phoneNumber: String? = null, - override val emailAddress: String? = null + override val emailAddress: String? = null, + override val traceLocationGUID: String? = null ) : ContactDiaryLocation { override val stableId: Long get() = locationId diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabase.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabase.kt index bb7eb9c19a6..e7081eac5ac 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabase.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabase.kt @@ -15,6 +15,7 @@ import de.rki.coronawarnapp.contactdiary.storage.entity.ContactDiaryPersonEncoun import de.rki.coronawarnapp.contactdiary.storage.entity.ContactDiaryPersonEntity import de.rki.coronawarnapp.contactdiary.storage.internal.converters.ContactDiaryRoomConverters import de.rki.coronawarnapp.contactdiary.storage.internal.migrations.ContactDiaryDatabaseMigration1To2 +import de.rki.coronawarnapp.contactdiary.storage.internal.migrations.ContactDiaryDatabaseMigration2To3 import de.rki.coronawarnapp.util.database.CommonConverters import de.rki.coronawarnapp.util.di.AppContext import javax.inject.Inject @@ -26,7 +27,7 @@ import javax.inject.Inject ContactDiaryPersonEntity::class, ContactDiaryPersonEncounterEntity::class ], - version = 2, + version = 3, exportSchema = true ) @TypeConverters(CommonConverters::class, ContactDiaryRoomConverters::class) @@ -40,7 +41,7 @@ abstract class ContactDiaryDatabase : RoomDatabase() { class Factory @Inject constructor(@AppContext private val ctx: Context) { fun create(databaseName: String = CONTACT_DIARY_DATABASE_NAME): ContactDiaryDatabase = Room .databaseBuilder(ctx, ContactDiaryDatabase::class.java, databaseName) - .addMigrations(ContactDiaryDatabaseMigration1To2) + .addMigrations(ContactDiaryDatabaseMigration1To2, ContactDiaryDatabaseMigration2To3) .build() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt index 31529a2382e..c552279d64c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt @@ -14,7 +14,8 @@ data class ContactDiaryLocationEntity( @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "locationId") override val locationId: Long = 0L, @ColumnInfo(name = "locationName") override var locationName: String, override val phoneNumber: String?, - override val emailAddress: String? + override val emailAddress: String?, + @ColumnInfo(name = "traceLocationGUID") override val traceLocationGUID: String? ) : ContactDiaryLocation, Parcelable { override val stableId: Long get() = locationId @@ -28,5 +29,6 @@ fun ContactDiaryLocation.toContactDiaryLocationEntity(): ContactDiaryLocationEnt locationId = this.locationId, locationName = this.locationName.trimMaxCharacters(), phoneNumber = this.phoneNumber?.trimMaxCharacters(), - emailAddress = this.emailAddress?.trimMaxCharacters() + emailAddress = this.emailAddress?.trimMaxCharacters(), + traceLocationGUID = this.traceLocationGUID ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationVisitEntity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationVisitEntity.kt index 4dfe111b24f..88c5d3b4cb7 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationVisitEntity.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationVisitEntity.kt @@ -29,7 +29,8 @@ data class ContactDiaryLocationVisitEntity( @ColumnInfo(name = "date") val date: LocalDate, @ColumnInfo(name = "fkLocationId") val fkLocationId: Long, @ColumnInfo(name = "duration") val duration: Duration?, - @ColumnInfo(name = "circumstances") val circumstances: String? + @ColumnInfo(name = "circumstances") val circumstances: String?, + @ColumnInfo(name = "checkInID") val checkInID: Long? ) fun ContactDiaryLocationVisit.toContactDiaryLocationVisitEntity(): ContactDiaryLocationVisitEntity = @@ -38,5 +39,6 @@ fun ContactDiaryLocationVisit.toContactDiaryLocationVisitEntity(): ContactDiaryL date = this.date, fkLocationId = this.contactDiaryLocation.locationId, duration = this.duration, - circumstances = this.circumstances?.trimToLength(250) + circumstances = this.circumstances?.trimToLength(250), + checkInID = this.checkInID ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationVisitWrapper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationVisitWrapper.kt index 040de1b5c26..734e0fdf4d1 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationVisitWrapper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationVisitWrapper.kt @@ -18,7 +18,8 @@ fun ContactDiaryLocationVisitWrapper.toContactDiaryLocationVisit(): ContactDiary date = this.contactDiaryLocationVisitEntity.date, contactDiaryLocation = this.contactDiaryLocationEntity, duration = contactDiaryLocationVisitEntity.duration, - circumstances = contactDiaryLocationVisitEntity.circumstances + circumstances = contactDiaryLocationVisitEntity.circumstances, + checkInID = this.contactDiaryLocationVisitEntity.checkInID ) fun List.toContactDiaryLocationVisitSortedList(): List = diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/internal/migrations/ContactDiaryDatabaseMigration2To3.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/internal/migrations/ContactDiaryDatabaseMigration2To3.kt new file mode 100644 index 00000000000..76706e36555 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/internal/migrations/ContactDiaryDatabaseMigration2To3.kt @@ -0,0 +1,45 @@ +package de.rki.coronawarnapp.contactdiary.storage.internal.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase +import de.rki.coronawarnapp.exception.ExceptionCategory +import de.rki.coronawarnapp.exception.reporting.report +import timber.log.Timber + +/** + * Migrates the contact diary database from schema version 2 to schema version 3. + * We are adding additional columns for new optional attributes + * Location: TraceLocationGUID + * LocationVisit: CheckInID + */ +object ContactDiaryDatabaseMigration2To3 : Migration(2, 3) { + + override fun migrate(database: SupportSQLiteDatabase) { + try { + Timber.i("Attempting migration 2->3...") + performMigration(database) + Timber.i("Migration 2->3 successful.") + } catch (e: Exception) { + Timber.e(e, "Migration 2->3 failed") + e.report(ExceptionCategory.INTERNAL, "ContactDiary database migration failed.") + throw e + } + } + + private fun performMigration(database: SupportSQLiteDatabase) = with(database) { + Timber.d("Running MIGRATION_2_3") + + migrateLocationsTable() + migrateLocationVisitTable() + } + + private val migrateLocationsTable: SupportSQLiteDatabase.() -> Unit = { + Timber.d("Table 'locations': Add column 'traceLocationGUID'") + execSQL("ALTER TABLE `locations` ADD COLUMN `traceLocationGUID` TEXT") + } + + private val migrateLocationVisitTable: SupportSQLiteDatabase.() -> Unit = { + Timber.d("Table 'locationvisits': Add column 'checkInID'") + execSQL("ALTER TABLE `locationvisits` ADD COLUMN `checkInID` INTEGER") + } +} 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 74c6aa6b9ef..db541a96cec 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 @@ -8,7 +8,6 @@ import androidx.core.app.ShareCompat import androidx.fragment.app.Fragment import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewAdapter -import de.rki.coronawarnapp.contactdiary.util.MarginRecyclerViewDecoration import de.rki.coronawarnapp.databinding.ContactDiaryOverviewFragmentBinding import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.diffutil.update @@ -31,16 +30,9 @@ class ContactDiaryOverviewFragment : Fragment(R.layout.contact_diary_overview_fr val adapter = DiaryOverviewAdapter() - binding.contactDiaryOverviewRecyclerview.apply { - this.adapter = adapter - addItemDecoration( - MarginRecyclerViewDecoration( - resources.getDimensionPixelSize(R.dimen.list_item_decoration_card_margins) - ) - ) - } - binding.apply { + contactDiaryOverviewRecyclerview.adapter = adapter + setupMenu(toolbar) toolbar.setNavigationOnClickListener { vm.onBackButtonPress() 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 4f4df1918b1..505094349e5 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 @@ -59,7 +59,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( private val personEncountersFlow = contactDiaryRepository.personEncounters private val riskLevelPerDateFlow = riskLevelStorage.aggregatedRiskPerDateResults - private val traceLocationCheckInRiskFlow = riskLevelStorage.allTraceLocationCheckInRisk + private val traceLocationCheckInRiskFlow = riskLevelStorage.traceLocationCheckInRiskStates val listItems = combine( flowOf(dates), @@ -179,9 +179,6 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( private fun Map.toRiskEventItem(): RiskEventItem? { - - TODO("Use Bulletspan...") - val highRiskEvent = RiskEventItem.Event( name = "Test high risk", bulledPointColor = R.color.colorBulletPointHighRisk, From 3edc16d1585a0de5f23378bb681703977acbbbd7 Mon Sep 17 00:00:00 2001 From: BMItter Date: Fri, 26 Mar 2021 12:29:11 +0100 Subject: [PATCH 11/30] cleanup, sourceCheck --- .../ui/overview/ContactDiaryOverviewViewModel.kt | 8 +++----- .../contactdiary/ui/overview/adapter/day/DayOverviewVH.kt | 3 +-- .../ui/overview/adapter/day/contact/ContactVH.kt | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) 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 505094349e5..114d55efa83 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 @@ -26,7 +26,6 @@ import de.rki.coronawarnapp.risk.TraceLocationCheckInRisk import de.rki.coronawarnapp.risk.result.AggregatedRiskPerDateResult import de.rki.coronawarnapp.risk.storage.RiskLevelStorage import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass -import de.rki.coronawarnapp.storage.TracingSettings import de.rki.coronawarnapp.task.TaskController import de.rki.coronawarnapp.task.common.DefaultTaskRequest import de.rki.coronawarnapp.util.TimeAndDateExtensions.toLocalDate @@ -185,7 +184,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( riskInfoAddition = R.string.contact_diary_event_risk_high ) - val lowRiskEvent = RiskEventItem.Event( + val lowRiskEvent = RiskEventItem.Event( name = "Test low risk", bulledPointColor = R.color.colorBulletPointLowRisk ) @@ -197,7 +196,6 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( events = listOf(highRiskEvent, lowRiskEvent) ) - if (isEmpty()) return null val isHighRisk = values.any { it?.riskState == RiskState.INCREASED_RISK } @@ -206,7 +204,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( val drawableID: Int val title: Int - when(isHighRisk) { + when (isHighRisk) { true -> { drawableID = R.drawable.ic_high_risk_alert title = R.string.contact_diary_high_risk_title @@ -225,7 +223,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( val bulletPointColor: Int var riskInfoAddition: Int? - when(entry.value?.riskState == RiskState.INCREASED_RISK) { + when (entry.value?.riskState == RiskState.INCREASED_RISK) { true -> { bulletPointColor = R.color.colorBulletPointHighRisk riskInfoAddition = R.string.contact_diary_event_risk_high diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt index 581163a8bc5..f349a15178d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt @@ -30,7 +30,7 @@ class DayOverviewVH(parent: ViewGroup) : itemAnimator = null } dayDataAdapter.update(item.dayData) - //suppressLayout(true) + // suppressLayout(true) } dayElementBody.apply { @@ -39,4 +39,3 @@ class DayOverviewVH(parent: ViewGroup) : } } } - diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt index dc8d44d7100..d73d9e89785 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt @@ -18,7 +18,7 @@ class ContactVH(parent: ViewGroup) : override val onBindData: ContactDiaryOverviewDayListItemContactBinding.(item: ContactItem, payloads: List) -> Unit = { item, _ -> - recyclerView.apply{ + recyclerView.apply { adapter = contactAdapter.apply { setItems(item.data) } suppressLayout(true) } From 6043ed826fa67e626315b36d559f2e6683b62111 Mon Sep 17 00:00:00 2001 From: BMItter Date: Fri, 26 Mar 2021 13:07:10 +0100 Subject: [PATCH 12/30] clean code --- .../overview/ContactDiaryOverviewViewModel.kt | 23 +++++++++++++--- .../overview/adapter/day/contact/ContactVH.kt | 18 +++++++------ .../overview/adapter/day/header/HeaderVH.kt | 16 +++++++----- .../overview/adapter/day/riskenf/RiskEnfVH.kt | 26 ++++++++++--------- .../adapter/day/riskevent/RiskEventAdapter.kt | 25 ++++++++++-------- .../adapter/day/riskevent/RiskEventVH.kt | 3 ++- ...erticalDividerItemDecorationExcludeLast.kt | 1 + 7 files changed, 70 insertions(+), 42 deletions(-) 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 114d55efa83..bdad3431f2d 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 @@ -69,7 +69,15 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( ) { dateList, locationVisists, personEncounters, riskLevelPerDateList, traceLocationCheckInRiskList -> mutableListOf().apply { add(OverviewSubHeaderItem) - addAll(createListItemList(dateList, locationVisists, personEncounters, riskLevelPerDateList, traceLocationCheckInRiskList)) + addAll( + createListItemList( + dateList, + locationVisists, + personEncounters, + riskLevelPerDateList, + traceLocationCheckInRiskList + ) + ) }.toList() }.asLiveData(dispatcherProvider.Default) @@ -90,7 +98,11 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( traceLocationCheckInRiskList: List ): List { Timber.v( - "createListItemList(dateList=%s, visits=%s, encounters=%s, riskLevelPerDateList=%s, traceLocationCheckInRiskList=%s", + "createListItemList(dateList=%s, " + + "visits=%s, " + + "encounters=%s, " + + "riskLevelPerDateList=%s, " + + "traceLocationCheckInRiskList=%s", dateList, visits, encounters, @@ -117,7 +129,12 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( ?.toRisk(coreItemData.isNotEmpty()) val riskeventItem = visitsForDate - .map { it to traceLocationCheckInRisksForDate.find { checkInRisk -> checkInRisk.checkInId == it.checkInID } } + .map { + it to traceLocationCheckInRisksForDate.find { + checkInRisk -> + checkInRisk.checkInId == it.checkInID + } + } .toMap() .filter { it.value != null } .toRiskEventItem() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt index d73d9e89785..e82fa08336e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt @@ -13,14 +13,16 @@ class ContactVH(parent: ViewGroup) : private val contactAdapter by lazy { ContactAdapter() } - override val viewBinding: Lazy = - lazy { ContactDiaryOverviewDayListItemContactBinding.bind(itemView) } + override val viewBinding: + Lazy = + lazy { ContactDiaryOverviewDayListItemContactBinding.bind(itemView) } - override val onBindData: ContactDiaryOverviewDayListItemContactBinding.(item: ContactItem, payloads: List) -> Unit = - { item, _ -> - recyclerView.apply { - adapter = contactAdapter.apply { setItems(item.data) } - suppressLayout(true) + override val onBindData: + ContactDiaryOverviewDayListItemContactBinding.(item: ContactItem, payloads: List) -> Unit = + { item, _ -> + recyclerView.apply { + adapter = contactAdapter.apply { setItems(item.data) } + suppressLayout(true) + } } - } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt index b7aea443044..43f2b267356 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt @@ -13,12 +13,14 @@ class HeaderVH(parent: ViewGroup) : parent = parent ) { - override val viewBinding: Lazy = - lazy { ContactDiaryOverviewDayListItemHeaderBinding.bind(itemView) } + override val viewBinding: + Lazy = + lazy { ContactDiaryOverviewDayListItemHeaderBinding.bind(itemView) } - override val onBindData: ContactDiaryOverviewDayListItemHeaderBinding.(item: HeaderItem, payloads: List) -> Unit = - { item, _ -> - name.text = item.date.toFormattedDay(context.getLocale()) - headerBody.setOnClickListener { item.onclickListener(item) } - } + override val onBindData: + ContactDiaryOverviewDayListItemHeaderBinding.(item: HeaderItem, payloads: List) -> Unit = + { item, _ -> + name.text = item.date.toFormattedDay(context.getLocale()) + headerBody.setOnClickListener { item.onclickListener(item) } + } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt index a893dd012b6..4da681c0113 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt @@ -11,21 +11,23 @@ class RiskEnfVH(parent: ViewGroup) : parent = parent ) { - override val viewBinding: Lazy = - lazy { ContactDiaryOverviewDayListItemRiskEnfBinding.bind(itemView) } + override val viewBinding: + Lazy = + lazy { ContactDiaryOverviewDayListItemRiskEnfBinding.bind(itemView) } - override val onBindData: ContactDiaryOverviewDayListItemRiskEnfBinding.(item: RiskEnfItem, payloads: List) -> Unit = - { item, _ -> + override val onBindData: + ContactDiaryOverviewDayListItemRiskEnfBinding.(item: RiskEnfItem, payloads: List) -> Unit = + { item, _ -> - contactDiaryOverviewItemRiskTitle.text = context.getString(item.title) - this.contactDiaryOverviewRiskItemImage.setImageResource(item.drawableId) + contactDiaryOverviewItemRiskTitle.text = context.getString(item.title) + this.contactDiaryOverviewRiskItemImage.setImageResource(item.drawableId) - val sb = StringBuilder().append(context.getString(item.body)) + val sb = StringBuilder().append(context.getString(item.body)) - item.bodyExtended?.let { extend -> - sb.appendLine().append(context.getString(extend)) - } + item.bodyExtended?.let { extend -> + sb.appendLine().append(context.getString(extend)) + } - this.contactDiaryOverviewItemRiskBody.text = sb - } + this.contactDiaryOverviewItemRiskBody.text = sb + } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventAdapter.kt index 96be4752692..157b2cbc6f4 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventAdapter.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventAdapter.kt @@ -28,21 +28,24 @@ class RiskEventAdapter : BaseAdapter() { BaseAdapter.VH(R.layout.contact_diary_overview_day_list_item_risk_event_list_item, parent), BindableVH { - override val viewBinding: Lazy = - lazy { ContactDiaryOverviewDayListItemRiskEventListItemBinding.bind(itemView) } + override val viewBinding: + Lazy = + lazy { ContactDiaryOverviewDayListItemRiskEventListItemBinding.bind(itemView) } - override val onBindData: ContactDiaryOverviewDayListItemRiskEventListItemBinding.(item: RiskEventItem.Event, payloads: List) -> Unit = - { item, _ -> + override val onBindData: + ContactDiaryOverviewDayListItemRiskEventListItemBinding.(item: RiskEventItem.Event, payloads: List) + -> Unit = + { item, _ -> - bulletPointImage.drawable?.setTint(context.getColorCompat(item.bulledPointColor)) + bulletPointImage.drawable?.setTint(context.getColorCompat(item.bulledPointColor)) - var name = item.name + var name = item.name - item.riskInfoAddition?.let { - name += " (${context.getString(it)})" - } + item.riskInfoAddition?.let { + name += " (${context.getString(it)})" + } - eventName.text = name - } + eventName.text = name + } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt index 30f7bba16e2..795356c8868 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt @@ -16,7 +16,8 @@ class RiskEventVH(parent: ViewGroup) : override val viewBinding: Lazy = lazy { ContactDiaryOverviewDayListItemRiskEventBinding.bind(itemView) } - override val onBindData: ContactDiaryOverviewDayListItemRiskEventBinding.(item: RiskEventItem, payloads: List) -> Unit = + override val onBindData: ContactDiaryOverviewDayListItemRiskEventBinding.(item: RiskEventItem, payloads: List) + -> Unit = { item, _ -> with(context) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/lists/decorations/VerticalDividerItemDecorationExcludeLast.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/lists/decorations/VerticalDividerItemDecorationExcludeLast.kt index 829b0dd0b09..9cffc7aa041 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/lists/decorations/VerticalDividerItemDecorationExcludeLast.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/lists/decorations/VerticalDividerItemDecorationExcludeLast.kt @@ -11,6 +11,7 @@ class VerticalDividerItemDecorationExcludeLast( context: Context ) : DividerItemDecoration(context, VERTICAL) { + @Suppress("NestedBlockDepth") override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) { val left = parent.paddingLeft val right = parent.width - parent.paddingRight From a4ba0e880f33f1f5b4441527df33fe617c88de6b Mon Sep 17 00:00:00 2001 From: BMItter Date: Mon, 29 Mar 2021 14:18:23 +0200 Subject: [PATCH 13/30] Added migration tests, updated ContactDiaryDatabaseTest to utilize new attributes --- .../ContactDiaryDatabaseMigrationTest.kt | 103 +++++++++++++++++- .../storage/ContactDiaryDatabaseTest.kt | 12 +- .../ContactDiaryOverviewFragmentTest.kt | 13 ++- .../ui/contactdiary/DiaryData.kt | 5 + 4 files changed, 122 insertions(+), 11 deletions(-) diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt index c8f85180b71..cee61ec50ba 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt @@ -1,5 +1,7 @@ package de.rki.coronawarnapp.contactdiary.storage +import android.content.ContentValues +import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteException import androidx.room.testing.MigrationTestHelper import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory @@ -13,10 +15,12 @@ import de.rki.coronawarnapp.contactdiary.storage.entity.ContactDiaryPersonEncoun import de.rki.coronawarnapp.contactdiary.storage.entity.ContactDiaryPersonEncounterWrapper import de.rki.coronawarnapp.contactdiary.storage.entity.ContactDiaryPersonEntity import de.rki.coronawarnapp.contactdiary.storage.internal.migrations.ContactDiaryDatabaseMigration1To2 +import de.rki.coronawarnapp.contactdiary.storage.internal.migrations.ContactDiaryDatabaseMigration2To3 import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.shouldBe import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking +import org.joda.time.Duration import org.joda.time.LocalDate import org.junit.Rule import org.junit.Test @@ -110,7 +114,8 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { locationId = 1, locationName = "Location1", phoneNumber = null, - emailAddress = null + emailAddress = null, + null ) runBlocking { daoDb.locationDao().allEntries().first() }.single() shouldBe location @@ -131,7 +136,8 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { date = LocalDate.parse("2020-04-20"), fkLocationId = 1, duration = null, - circumstances = null + circumstances = null, + null ) ) @@ -151,6 +157,79 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { ) } + @Test + fun migrate2To3() { + val location = ContactDiaryLocationEntity( + locationId = 1, + locationName = "Why do you want to have this information?", + phoneNumber = "I'm not going to tell you yet", + emailAddress = "I'mnotgoingtotell@you.yet", + traceLocationGUID = null + ) + + val locationVisit = ContactDiaryLocationVisitEntity( + id = 2, + date = LocalDate.parse("2020-12-31"), + fkLocationId = 1, + duration = Duration.standardMinutes(13), + circumstances = "That's none of your business", + null + ) + + val locationAfter = location.copy(traceLocationGUID = "jshrgu-aifhioaio-aofsjof-samofp-kjsadngsgf") + val locationVisitAfter = locationVisit.copy(checkInID = 101) + + val locationValues = ContentValues().apply { + put("locationId", location.locationId) + put("locationName", location.locationName) + put("phoneNumber", location.phoneNumber) + put("emailAddress", location.emailAddress) + } + + val locationVisitValues = ContentValues().apply { + put("id", locationVisit.id) + put("date", locationVisit.date.toString()) + put("fkLocationId", locationVisit.fkLocationId) + put("duration", locationVisit.duration?.millis) + put("circumstances", locationVisit.circumstances) + } + + helper.createDatabase(DB_NAME, 2).apply { + insert("locations", SQLiteDatabase.CONFLICT_FAIL, locationValues) + insert("locationvisits", SQLiteDatabase.CONFLICT_FAIL, locationVisitValues) + + close() + } + + // Run migration + helper.runMigrationsAndValidate( + DB_NAME, + 3, + true, + ContactDiaryDatabaseMigration2To3 + ) + + val daoDb = ContactDiaryDatabase.Factory( + ctx = ApplicationProvider.getApplicationContext() + ).create(databaseName = DB_NAME) + + runBlocking { + daoDb.locationVisitDao().allEntries().first().single() shouldBe ContactDiaryLocationVisitWrapper( + contactDiaryLocationEntity = location, + contactDiaryLocationVisitEntity = locationVisit + ) + + // Test if new attributes are added correctly + daoDb.locationDao().update(locationAfter) + daoDb.locationVisitDao().update(locationVisitAfter) + + daoDb.locationVisitDao().allEntries().first().single() shouldBe ContactDiaryLocationVisitWrapper( + contactDiaryLocationEntity = locationAfter, + contactDiaryLocationVisitEntity = locationVisitAfter + ) + } + } + @Test fun migrate1To2_failure_throws() { helper.createDatabase(DB_NAME, 1).apply { @@ -177,6 +256,26 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { } } + @Test + fun migrate2To3_failure_throws() { + helper.createDatabase(DB_NAME, 2).apply { + execSQL("DROP TABLE IF EXISTS locations") + // Has incompatible existing column phoneNumber of wrong type + execSQL("CREATE TABLE IF NOT EXISTS `locations` (`locationId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationName` TEXT NOT NULL, `phoneNumber` TEXT, `emailAddress` TEXT, `traceLocationGUID` INTEGER)") + close() + } + + shouldThrow { + // Run migration + helper.runMigrationsAndValidate( + DB_NAME, + 3, + true, + ContactDiaryDatabaseMigration2To3 + ) + } + } + @Test @Throws(IOException::class) fun migrateAll() { diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseTest.kt index 95c5c04429e..17f3795b0cc 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseTest.kt @@ -36,7 +36,8 @@ class ContactDiaryDatabaseTest : BaseTestInstrumentation() { locationId = 2, locationName = "Rewe Wiesloch", emailAddress = "location-emailAddress", - phoneNumber = "location-phoneNumber" + phoneNumber = "location-phoneNumber", + traceLocationGUID = "a-b-c-d" ) private val personEncounter = ContactDiaryPersonEncounterEntity( id = 3, @@ -52,7 +53,8 @@ class ContactDiaryDatabaseTest : BaseTestInstrumentation() { date = date, fkLocationId = location.locationId, duration = Duration.standardMinutes(99), - circumstances = "I had to buy snacks." + circumstances = "I had to buy snacks.", + checkInID = 101 ) // DB @@ -144,14 +146,16 @@ class ContactDiaryDatabaseTest : BaseTestInstrumentation() { date = yesterday, fkLocationId = location.locationId, duration = Duration.standardMinutes(42), - circumstances = "visit-yesterday" + circumstances = "visit-yesterday", + checkInID = null ) val locationVisitTomorrow = ContactDiaryLocationVisitEntity( id = 8, date = tomorrow, fkLocationId = location.locationId, duration = Duration.standardMinutes(1), - circumstances = "visit-today" + circumstances = "visit-today", + checkInID = 155 ) val encounterList = listOf(personEncounter, personEncounterYesterday, personEncounterTomorrow) val visitList = listOf(locationVisit, locationVisitYesterday, locationVisitTomorrow) diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryOverviewFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryOverviewFragmentTest.kt index 604ccdd3a03..23cd43e4b6a 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryOverviewFragmentTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryOverviewFragmentTest.kt @@ -25,12 +25,10 @@ import io.mockk.spyk import org.joda.time.LocalDate import org.junit.After import org.junit.Before -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import testhelpers.BaseUITest import testhelpers.Screenshot -import testhelpers.SystemUIDemoModeRule import testhelpers.TestDispatcherProvider import testhelpers.launchFragment2 import testhelpers.launchInMainActivity @@ -49,9 +47,6 @@ class ContactDiaryOverviewFragmentTest : BaseUITest() { private lateinit var viewModel: ContactDiaryOverviewViewModel - @get:Rule - val systemUIDemoModeRule = SystemUIDemoModeRule() - @Before fun setup() { MockKAnnotations.init(this, relaxed = true) @@ -97,9 +92,15 @@ class ContactDiaryOverviewFragmentTest : BaseUITest() { takeScreenshot("2") } + + private fun contactDiaryOverviewItemLiveData(): LiveData> { val data = mutableListOf() data.add(OverviewSubHeaderItem) + + TODO("FIXME!!") + + /* val dayData = (0 until ContactDiaryOverviewViewModel.DAY_COUNT) .map { LocalDate.now().minusDays(it) } .mapIndexed { index, localDate -> @@ -124,6 +125,8 @@ class ContactDiaryOverviewFragmentTest : BaseUITest() { } } data.addAll(dayData) + + */ return MutableLiveData(data) } } diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt index e241f06989c..da8045da6e9 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt @@ -16,6 +16,9 @@ import org.joda.time.LocalDate object DiaryData { + //TODO("FIXME!!") + + /* val DATA_ITEMS = listOf( DayOverviewItem.Data( R.drawable.ic_contact_diary_location_item, @@ -62,6 +65,8 @@ object DiaryData { drawableId = R.drawable.ic_low_risk_alert ) + */ + val LOCATIONS: List = listOf( DiaryLocationListItem( item = DefaultContactDiaryLocation(locationName = "Physiotherapie"), From b7208165a18e9fb5051cd40fe395374bdc965585 Mon Sep 17 00:00:00 2001 From: BMItter Date: Mon, 29 Mar 2021 18:54:15 +0200 Subject: [PATCH 14/30] Replaced recyclerview with Flow, some layout improvements --- .../overview/ContactDiaryOverviewViewModel.kt | 43 +++------- .../overview/adapter/day/DayOverviewItem.kt | 7 +- .../ui/overview/adapter/day/DayOverviewVH.kt | 84 ++++++++++++++++--- .../overview/adapter/day/header/HeaderItem.kt | 3 +- .../overview/adapter/day/header/HeaderVH.kt | 18 ++-- ...t_diary_overview_day_list_item_contact.xml | 8 ++ ...ct_diary_overview_day_list_item_header.xml | 2 +- ..._diary_overview_day_list_item_risk_enf.xml | 8 ++ ...iary_overview_day_list_item_risk_event.xml | 11 ++- .../contact_diary_overview_list_item.xml | 24 +++++- 10 files changed, 144 insertions(+), 64 deletions(-) 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 bdad3431f2d..f2fb4910c76 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 @@ -69,15 +69,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( ) { dateList, locationVisists, personEncounters, riskLevelPerDateList, traceLocationCheckInRiskList -> mutableListOf().apply { add(OverviewSubHeaderItem) - addAll( - createListItemList( - dateList, - locationVisists, - personEncounters, - riskLevelPerDateList, - traceLocationCheckInRiskList - ) - ) + addAll(createListItemList(dateList, locationVisists, personEncounters, riskLevelPerDateList, traceLocationCheckInRiskList)) }.toList() }.asLiveData(dispatcherProvider.Default) @@ -98,11 +90,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( traceLocationCheckInRiskList: List ): List { Timber.v( - "createListItemList(dateList=%s, " + - "visits=%s, " + - "encounters=%s, " + - "riskLevelPerDateList=%s, " + - "traceLocationCheckInRiskList=%s", + "createListItemList(dateList=%s, visits=%s, encounters=%s, riskLevelPerDateList=%s, traceLocationCheckInRiskList=%s", dateList, visits, encounters, @@ -115,8 +103,6 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( val encountersForDate = encounters.filter { it.date == date } val traceLocationCheckInRisksForDate = traceLocationCheckInRiskList.filter { it.localDate == date } - val headerItem = HeaderItem(date) { openDayFragment(it.date) } - val coreItemData = encountersForDate.map { it.toContactItemData() } + visitsForDate.map { it.toContactItemData() } val contactItem = when (coreItemData.isNotEmpty()) { @@ -129,25 +115,17 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( ?.toRisk(coreItemData.isNotEmpty()) val riskeventItem = visitsForDate - .map { - it to traceLocationCheckInRisksForDate.find { - checkInRisk -> - checkInRisk.checkInId == it.checkInID - } - } + .map { it to traceLocationCheckInRisksForDate.find { checkInRisk -> checkInRisk.checkInId == it.checkInID } } .toMap() .filter { it.value != null } .toRiskEventItem() - // Items will be shown in order they are added to list - val items: List = listOf( - headerItem, - riskEnf, - riskeventItem, - contactItem - ).mapNotNull { it } - - DayOverviewItem(date = date, dayData = items) { onItemPress(it) } + DayOverviewItem( + date = date, + riskEnfItem = riskEnf, + riskEventItem = riskeventItem, + contactItem = contactItem + ) { onItemPress(it) } } } @@ -201,7 +179,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( riskInfoAddition = R.string.contact_diary_event_risk_high ) - val lowRiskEvent = RiskEventItem.Event( + val lowRiskEvent = RiskEventItem.Event( name = "Test low risk", bulledPointColor = R.color.colorBulletPointLowRisk ) @@ -213,6 +191,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( events = listOf(highRiskEvent, lowRiskEvent) ) + if (isEmpty()) return null val isHighRisk = values.any { it?.riskState == RiskState.INCREASED_RISK } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt index 4e5aaf6e430..31aa016b910 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt @@ -1,11 +1,16 @@ package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventItem import org.joda.time.LocalDate data class DayOverviewItem( val date: LocalDate, - val dayData: List, + val riskEnfItem: RiskEnfItem? = null, + val riskEventItem: RiskEventItem? = null, + val contactItem: ContactItem? = null, val onItemSelectionListener: (DayOverviewItem) -> Unit ) : DiaryOverviewItem { override val stableId: Long = date.hashCode().toLong() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt index f349a15178d..264654f4893 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt @@ -1,13 +1,23 @@ package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day import android.view.ViewGroup +import androidx.core.view.isGone import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewAdapter +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactAdapter +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventAdapter +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventItem import de.rki.coronawarnapp.contactdiary.util.getLocale +import de.rki.coronawarnapp.contactdiary.util.toFormattedDay import de.rki.coronawarnapp.contactdiary.util.toFormattedDayForAccessibility +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemContactBinding +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemHeaderBinding +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEnfBinding +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEventBinding import de.rki.coronawarnapp.databinding.ContactDiaryOverviewListItemBinding -import de.rki.coronawarnapp.util.lists.decorations.VerticalDividerItemDecorationExcludeLast -import de.rki.coronawarnapp.util.lists.diffutil.update +import org.joda.time.LocalDate class DayOverviewVH(parent: ViewGroup) : DiaryOverviewAdapter.ItemVH( @@ -15,22 +25,20 @@ class DayOverviewVH(parent: ViewGroup) : parent = parent ) { - private val dayDataAdapter by lazy { DayDataAdapter() } + private val riskEventAdapter: RiskEventAdapter by lazy { RiskEventAdapter() } + private val contactAdapter: ContactAdapter by lazy { ContactAdapter() } override val viewBinding: Lazy = lazy { ContactDiaryOverviewListItemBinding.bind(itemView) } override val onBindData: ContactDiaryOverviewListItemBinding.(item: DayOverviewItem, payloads: List) -> Unit = { item, _ -> - dayRecyclerView.apply { - if (adapter == null) { - adapter = dayDataAdapter - addItemDecoration(VerticalDividerItemDecorationExcludeLast(context)) - // To avoid flickering - itemAnimator = null - } - dayDataAdapter.update(item.dayData) - // suppressLayout(true) + + item.apply { + dayHeader.apply(date = date) + dayRiskEnf.apply(riskEnfItem = riskEnfItem) + dayRiskEvent.apply(riskEventItem = riskEventItem) + dayContact.apply(contactItem = contactItem) } dayElementBody.apply { @@ -38,4 +46,56 @@ class DayOverviewVH(parent: ViewGroup) : setOnClickListener { item.onItemSelectionListener(item) } } } + + private fun ContactDiaryOverviewDayListItemHeaderBinding.apply(date: LocalDate) = this.apply { + this.date.text = date.toFormattedDay(context.getLocale()) + } + + private fun ContactDiaryOverviewDayListItemRiskEnfBinding.apply(riskEnfItem: RiskEnfItem?) = this.apply { + root.isGone = riskEnfItem == null + + riskEnfItem?.let { + contactDiaryOverviewItemRiskTitle.text = context.getString(it.title) + contactDiaryOverviewRiskItemImage.setImageResource(it.drawableId) + + val sb = StringBuilder().append(context.getString(it.body)) + + it.bodyExtended?.let { extend -> + sb.appendLine().append(context.getString(extend)) + } + + contactDiaryOverviewItemRiskBody.text = sb + } + } + + private fun ContactDiaryOverviewDayListItemRiskEventBinding.apply(riskEventItem: RiskEventItem?) = this.apply { + root.isGone = riskEventItem == null + + riskEventItem?.let { + with(context) { + contactDiaryOverviewItemRiskTitle.text = getString(it.title) + contactDiaryOverviewItemRiskBody.text = getString(it.body) + } + + contactDiaryOverviewRiskItemImage.setImageResource(it.drawableId) + + with(contactDiaryOverviewItemRiskEventList) { + if (adapter == null) { + adapter = riskEventAdapter + } + riskEventAdapter.setItems(it.events) + } + } + } + + private fun ContactDiaryOverviewDayListItemContactBinding.apply(contactItem: ContactItem?) = this.apply { + root.isGone = contactItem == null + + contactItem?.let { + recyclerView.apply { + adapter = contactAdapter.apply { setItems(it.data) } + suppressLayout(true) + } + } + } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt index 10f37e25ef4..1848cb0160f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderItem.kt @@ -4,8 +4,7 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataItem import org.joda.time.LocalDate data class HeaderItem( - val date: LocalDate, - val onclickListener: (HeaderItem) -> Unit = { } + val date: LocalDate ) : DayDataItem { override val stableId: Long = date.hashCode().toLong() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt index 43f2b267356..f9e959ca0a8 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt @@ -3,8 +3,6 @@ package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header import android.view.ViewGroup import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataAdapter -import de.rki.coronawarnapp.contactdiary.util.getLocale -import de.rki.coronawarnapp.contactdiary.util.toFormattedDay import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemHeaderBinding class HeaderVH(parent: ViewGroup) : @@ -13,14 +11,12 @@ class HeaderVH(parent: ViewGroup) : parent = parent ) { - override val viewBinding: - Lazy = - lazy { ContactDiaryOverviewDayListItemHeaderBinding.bind(itemView) } + override val viewBinding: Lazy = + lazy { ContactDiaryOverviewDayListItemHeaderBinding.bind(itemView) } - override val onBindData: - ContactDiaryOverviewDayListItemHeaderBinding.(item: HeaderItem, payloads: List) -> Unit = - { item, _ -> - name.text = item.date.toFormattedDay(context.getLocale()) - headerBody.setOnClickListener { item.onclickListener(item) } - } + override val onBindData: ContactDiaryOverviewDayListItemHeaderBinding.(item: HeaderItem, payloads: List) -> Unit = + { item, _ -> + //name.text = item.date.toFormattedDay(context.getLocale()) + //headerBody.setOnClickListener { item.onclickListener(item) } + } } diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_contact.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_contact.xml index 6cb0515742d..8333ce839b6 100644 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_contact.xml +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_contact.xml @@ -4,6 +4,14 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> + + + + + + + tools:listitem="@layout/contact_diary_overview_day_list_item_risk_event_list_item" + tools:itemCount="4"/> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml index 037d69dfa21..e52dfe374e1 100644 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml @@ -8,12 +8,28 @@ android:layout_height="wrap_content" android:focusable="true"> - + + + + + + + + Date: Tue, 30 Mar 2021 11:10:14 +0200 Subject: [PATCH 15/30] Removed unused viewholders --- .../ui/overview/adapter/day/DayDataAdapter.kt | 47 ------------------- .../overview/adapter/day/contact/ContactVH.kt | 28 ----------- .../overview/adapter/day/header/HeaderVH.kt | 22 --------- .../overview/adapter/day/riskenf/RiskEnfVH.kt | 33 ------------- .../adapter/day/riskevent/RiskEventVH.kt | 37 --------------- 5 files changed, 167 deletions(-) delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt deleted file mode 100644 index 0171e5172c6..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataAdapter.kt +++ /dev/null @@ -1,47 +0,0 @@ -package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day - -import android.view.ViewGroup -import androidx.annotation.LayoutRes -import androidx.viewbinding.ViewBinding -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactVH -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderItem -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderVH -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfVH -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventItem -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventVH -import de.rki.coronawarnapp.util.lists.BindableVH -import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter -import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer -import de.rki.coronawarnapp.util.lists.modular.ModularAdapter -import de.rki.coronawarnapp.util.lists.modular.mods.DataBinderMod -import de.rki.coronawarnapp.util.lists.modular.mods.StableIdMod -import de.rki.coronawarnapp.util.lists.modular.mods.TypedVHCreatorMod - -class DayDataAdapter : - ModularAdapter>(), - AsyncDiffUtilAdapter { - - override val asyncDiffer: AsyncDiffer = AsyncDiffer(adapter = this) - - init { - modules.addAll( - listOf( - StableIdMod(data), - DataBinderMod>(data), - TypedVHCreatorMod({ data[it] is HeaderItem }) { HeaderVH(it) }, - TypedVHCreatorMod({ data[it] is RiskEnfItem }) { RiskEnfVH(it) }, - TypedVHCreatorMod({ data[it] is RiskEventItem }) { RiskEventVH(it) }, - TypedVHCreatorMod({ data[it] is ContactItem }) { ContactVH(it) } - ) - ) - } - - override fun getItemCount(): Int = data.size - - abstract class ItemVH( - @LayoutRes layoutRes: Int, - parent: ViewGroup - ) : ModularAdapter.VH(layoutRes, parent), BindableVH -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt deleted file mode 100644 index e82fa08336e..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactVH.kt +++ /dev/null @@ -1,28 +0,0 @@ -package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact - -import android.view.ViewGroup -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataAdapter -import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemContactBinding - -class ContactVH(parent: ViewGroup) : - DayDataAdapter.ItemVH( - layoutRes = R.layout.contact_diary_overview_day_list_item_contact, - parent = parent - ) { - - private val contactAdapter by lazy { ContactAdapter() } - - override val viewBinding: - Lazy = - lazy { ContactDiaryOverviewDayListItemContactBinding.bind(itemView) } - - override val onBindData: - ContactDiaryOverviewDayListItemContactBinding.(item: ContactItem, payloads: List) -> Unit = - { item, _ -> - recyclerView.apply { - adapter = contactAdapter.apply { setItems(item.data) } - suppressLayout(true) - } - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt deleted file mode 100644 index f9e959ca0a8..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/header/HeaderVH.kt +++ /dev/null @@ -1,22 +0,0 @@ -package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header - -import android.view.ViewGroup -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataAdapter -import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemHeaderBinding - -class HeaderVH(parent: ViewGroup) : - DayDataAdapter.ItemVH( - layoutRes = R.layout.contact_diary_overview_day_list_item_header, - parent = parent - ) { - - override val viewBinding: Lazy = - lazy { ContactDiaryOverviewDayListItemHeaderBinding.bind(itemView) } - - override val onBindData: ContactDiaryOverviewDayListItemHeaderBinding.(item: HeaderItem, payloads: List) -> Unit = - { item, _ -> - //name.text = item.date.toFormattedDay(context.getLocale()) - //headerBody.setOnClickListener { item.onclickListener(item) } - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt deleted file mode 100644 index 4da681c0113..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskenf/RiskEnfVH.kt +++ /dev/null @@ -1,33 +0,0 @@ -package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf - -import android.view.ViewGroup -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataAdapter -import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEnfBinding - -class RiskEnfVH(parent: ViewGroup) : - DayDataAdapter.ItemVH( - layoutRes = R.layout.contact_diary_overview_day_list_item_risk_enf, - parent = parent - ) { - - override val viewBinding: - Lazy = - lazy { ContactDiaryOverviewDayListItemRiskEnfBinding.bind(itemView) } - - override val onBindData: - ContactDiaryOverviewDayListItemRiskEnfBinding.(item: RiskEnfItem, payloads: List) -> Unit = - { item, _ -> - - contactDiaryOverviewItemRiskTitle.text = context.getString(item.title) - this.contactDiaryOverviewRiskItemImage.setImageResource(item.drawableId) - - val sb = StringBuilder().append(context.getString(item.body)) - - item.bodyExtended?.let { extend -> - sb.appendLine().append(context.getString(extend)) - } - - this.contactDiaryOverviewItemRiskBody.text = sb - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt deleted file mode 100644 index 795356c8868..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/riskevent/RiskEventVH.kt +++ /dev/null @@ -1,37 +0,0 @@ -package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent - -import android.view.ViewGroup -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataAdapter -import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEventBinding - -class RiskEventVH(parent: ViewGroup) : - DayDataAdapter.ItemVH( - layoutRes = R.layout.contact_diary_overview_day_list_item_risk_event, - parent = parent - ) { - - private val riskEventAdapter: RiskEventAdapter by lazy { RiskEventAdapter() } - - override val viewBinding: Lazy = - lazy { ContactDiaryOverviewDayListItemRiskEventBinding.bind(itemView) } - - override val onBindData: ContactDiaryOverviewDayListItemRiskEventBinding.(item: RiskEventItem, payloads: List) - -> Unit = - { item, _ -> - - with(context) { - contactDiaryOverviewItemRiskTitle.text = getString(item.title) - contactDiaryOverviewItemRiskBody.text = getString(item.body) - } - - contactDiaryOverviewRiskItemImage.setImageResource(item.drawableId) - - with(contactDiaryOverviewItemRiskEventList) { - if (adapter == null) { - adapter = riskEventAdapter - } - riskEventAdapter.setItems(item.events) - } - } -} From 0a160af1ce2fee253cac16a6462a61b228799c30 Mon Sep 17 00:00:00 2001 From: BMItter Date: Tue, 30 Mar 2021 11:14:12 +0200 Subject: [PATCH 16/30] Fixed contact diary test --- .../ContactDiaryOverviewFragmentTest.kt | 40 ++++++++--- .../ui/contactdiary/DiaryData.kt | 70 +++++++++++++++---- 2 files changed, 86 insertions(+), 24 deletions(-) diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryOverviewFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryOverviewFragmentTest.kt index 23cd43e4b6a..3d7bc4e5fbd 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryOverviewFragmentTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryOverviewFragmentTest.kt @@ -14,6 +14,7 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.ContactDiaryOverviewFragmen import de.rki.coronawarnapp.contactdiary.ui.overview.ContactDiaryOverviewViewModel import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem import de.rki.coronawarnapp.risk.storage.RiskLevelStorage import de.rki.coronawarnapp.task.TaskController @@ -25,10 +26,12 @@ import io.mockk.spyk import org.joda.time.LocalDate import org.junit.After import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import testhelpers.BaseUITest import testhelpers.Screenshot +import testhelpers.SystemUIDemoModeRule import testhelpers.TestDispatcherProvider import testhelpers.launchFragment2 import testhelpers.launchInMainActivity @@ -47,6 +50,9 @@ class ContactDiaryOverviewFragmentTest : BaseUITest() { private lateinit var viewModel: ContactDiaryOverviewViewModel + @get:Rule + val systemUIDemoModeRule = SystemUIDemoModeRule() + @Before fun setup() { MockKAnnotations.init(this, relaxed = true) @@ -92,19 +98,14 @@ class ContactDiaryOverviewFragmentTest : BaseUITest() { takeScreenshot("2") } - - private fun contactDiaryOverviewItemLiveData(): LiveData> { val data = mutableListOf() data.add(OverviewSubHeaderItem) - TODO("FIXME!!") - - /* val dayData = (0 until ContactDiaryOverviewViewModel.DAY_COUNT) .map { LocalDate.now().minusDays(it) } .mapIndexed { index, localDate -> - val dayData = mutableListOf().apply { + val dayData = mutableListOf().apply { if (index == 1) { add(DiaryData.DATA_ITEMS[0]) add(DiaryData.DATA_ITEMS[1]) @@ -112,21 +113,40 @@ class ContactDiaryOverviewFragmentTest : BaseUITest() { add(DiaryData.DATA_ITEMS[2]) } } - val risk = when (index % 5) { + + val riskEnf = when (index % 5) { 3 -> DiaryData.HIGH_RISK_DUE_LOW_RISK_ENCOUNTERS else -> null // DiaryData.LOW_RISK OR DiaryData.HIGH_RISK POSSIBLE } + + val riskEvent = when (index) { + 6 -> { + dayData.add(DiaryData.LOW_RISK_EVENT_LOCATION) + DiaryData.LOW_RISK_EVENT_ITEM + } + + 7 -> { + dayData.apply { + add(DiaryData.LOW_RISK_EVENT_LOCATION) + add(DiaryData.HIGH_RISK_EVENT_LOCATION) + } + DiaryData.HIGH_RISK_EVENT_ITEM + } + + else -> null + } + DayOverviewItem( date = localDate, - data = dayData, - risk = risk + contactItem = ContactItem(dayData), + riskEnfItem = riskEnf, + riskEventItem = riskEvent ) { // onClick } } data.addAll(dayData) - */ return MutableLiveData(data) } } diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt index da8045da6e9..d4639ca1391 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt @@ -10,25 +10,24 @@ import de.rki.coronawarnapp.contactdiary.model.DefaultContactDiaryPerson import de.rki.coronawarnapp.contactdiary.model.DefaultContactDiaryPersonEncounter import de.rki.coronawarnapp.contactdiary.ui.day.tabs.location.DiaryLocationListItem import de.rki.coronawarnapp.contactdiary.ui.day.tabs.person.DiaryPersonListItem -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventItem import org.joda.time.Duration import org.joda.time.LocalDate object DiaryData { - //TODO("FIXME!!") - - /* val DATA_ITEMS = listOf( - DayOverviewItem.Data( + ContactItem.Data( R.drawable.ic_contact_diary_location_item, "Supermarkt", Duration.standardMinutes(30), attributes = null, circumstances = null, - DayOverviewItem.Type.LOCATION + ContactItem.Type.LOCATION ), - DayOverviewItem.Data( + ContactItem.Data( R.drawable.ic_contact_diary_person_item, "Erika Musterfrau", null, @@ -37,35 +36,78 @@ object DiaryData { R.string.contact_diary_person_encounter_environment_outside ), null, - DayOverviewItem.Type.PERSON + ContactItem.Type.PERSON ), - DayOverviewItem.Data( + ContactItem.Data( R.drawable.ic_contact_diary_location_item, "Büro", null, null, null, - DayOverviewItem.Type.LOCATION + ContactItem.Type.LOCATION ) ) - val HIGH_RISK = DayOverviewItem.Risk( + val HIGH_RISK = RiskEnfItem( title = R.string.contact_diary_high_risk_title, body = R.string.contact_diary_risk_body, bodyExtended = R.string.contact_diary_risk_body_extended, drawableId = R.drawable.ic_high_risk_alert ) - val HIGH_RISK_DUE_LOW_RISK_ENCOUNTERS = HIGH_RISK.copy(body = R.string.contact_diary_risk_body_high_risk_due_to_low_risk_encounters) + val HIGH_RISK_DUE_LOW_RISK_ENCOUNTERS = + HIGH_RISK.copy(body = R.string.contact_diary_risk_body_high_risk_due_to_low_risk_encounters) - val LOW_RISK = DayOverviewItem.Risk( + val LOW_RISK = RiskEnfItem( title = R.string.contact_diary_low_risk_title, body = R.string.contact_diary_risk_body, bodyExtended = R.string.contact_diary_risk_body_extended, drawableId = R.drawable.ic_low_risk_alert ) - */ + val LOW_RISK_EVENT_LOCATION = ContactItem.Data( + R.drawable.ic_contact_diary_location_item, + "Jahrestreffen der deutsche SAP Anwendergruppe", + Duration.standardMinutes(25), + attributes = null, + circumstances = "Hauptstr 3, 69115 Heidelberg", + ContactItem.Type.LOCATION + ) + + val HIGH_RISK_EVENT_LOCATION = ContactItem.Data( + R.drawable.ic_contact_diary_location_item, + "Kiosk", + Duration.standardMinutes(15), + attributes = null, + circumstances = null, + ContactItem.Type.LOCATION + ) + + val HIGH_RISK_EVENT = RiskEventItem.Event( + name = HIGH_RISK_EVENT_LOCATION.name, + bulledPointColor = R.color.colorBulletPointHighRisk, + riskInfoAddition = R.string.contact_diary_event_risk_high + ) + + val LOW_RISK_EVENT = RiskEventItem.Event( + name = LOW_RISK_EVENT_LOCATION.name, + bulledPointColor = R.color.colorBulletPointLowRisk, + riskInfoAddition = R.string.contact_diary_event_risk_low + ) + + val HIGH_RISK_EVENT_ITEM = RiskEventItem( + title = R.string.contact_diary_high_risk_title, + body = R.string.contact_diary_event_risk_body, + drawableId = R.drawable.ic_high_risk_alert, + events = listOf(HIGH_RISK_EVENT, LOW_RISK_EVENT) + ) + + val LOW_RISK_EVENT_ITEM = RiskEventItem( + title = R.string.contact_diary_low_risk_title, + body = R.string.contact_diary_event_risk_body, + drawableId = R.drawable.ic_low_risk_alert, + events = listOf(LOW_RISK_EVENT) + ) val LOCATIONS: List = listOf( DiaryLocationListItem( From 94a712c5422eb4894c933073b452d2519d82f6a4 Mon Sep 17 00:00:00 2001 From: BMItter Date: Tue, 30 Mar 2021 11:24:39 +0200 Subject: [PATCH 17/30] Removed debug code --- .../overview/ContactDiaryOverviewViewModel.kt | 36 ++++++------------- 1 file changed, 11 insertions(+), 25 deletions(-) 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 f2fb4910c76..b31f12ac15d 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 @@ -14,10 +14,8 @@ import de.rki.coronawarnapp.contactdiary.retention.ContactDiaryCleanTask import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository import de.rki.coronawarnapp.contactdiary.ui.exporter.ContactDiaryExporter import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewItem -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayDataItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem -import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.header.HeaderItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem @@ -69,7 +67,15 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( ) { dateList, locationVisists, personEncounters, riskLevelPerDateList, traceLocationCheckInRiskList -> mutableListOf().apply { add(OverviewSubHeaderItem) - addAll(createListItemList(dateList, locationVisists, personEncounters, riskLevelPerDateList, traceLocationCheckInRiskList)) + addAll( + createListItemList( + dateList, + locationVisists, + personEncounters, + riskLevelPerDateList, + traceLocationCheckInRiskList + ) + ) }.toList() }.asLiveData(dispatcherProvider.Default) @@ -114,7 +120,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( .firstOrNull { riskLevelPerDate -> riskLevelPerDate.day == date } ?.toRisk(coreItemData.isNotEmpty()) - val riskeventItem = visitsForDate + val riskEventItem = visitsForDate .map { it to traceLocationCheckInRisksForDate.find { checkInRisk -> checkInRisk.checkInId == it.checkInID } } .toMap() .filter { it.value != null } @@ -123,7 +129,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( DayOverviewItem( date = date, riskEnfItem = riskEnf, - riskEventItem = riskeventItem, + riskEventItem = riskEventItem, contactItem = contactItem ) { onItemPress(it) } } @@ -172,26 +178,6 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( ) private fun Map.toRiskEventItem(): RiskEventItem? { - - val highRiskEvent = RiskEventItem.Event( - name = "Test high risk", - bulledPointColor = R.color.colorBulletPointHighRisk, - riskInfoAddition = R.string.contact_diary_event_risk_high - ) - - val lowRiskEvent = RiskEventItem.Event( - name = "Test low risk", - bulledPointColor = R.color.colorBulletPointLowRisk - ) - - return RiskEventItem( - title = R.string.contact_diary_high_risk_title, - body = R.string.contact_diary_event_risk_body, - drawableId = R.drawable.ic_high_risk_alert, - events = listOf(highRiskEvent, lowRiskEvent) - ) - - if (isEmpty()) return null val isHighRisk = values.any { it?.riskState == RiskState.INCREASED_RISK } From 44a2a5ed8fb06248abff5eaca30dd6837d038185 Mon Sep 17 00:00:00 2001 From: BMItter Date: Tue, 30 Mar 2021 11:27:53 +0200 Subject: [PATCH 18/30] Fixed broken tests --- .../ContactDiaryEditLocationsViewModelTest.kt | 1 + .../ContactDiaryOverviewViewModelTest.kt | 47 ++++++++----------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModelTest.kt index 85cec1b3738..d07c90de283 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModelTest.kt @@ -30,6 +30,7 @@ class ContactDiaryEditLocationsViewModelTest { override val phoneNumber: String? = null override val emailAddress: String? = null override val stableId = 1L + override val traceLocationGUID: String? = null } private val locationList = listOf(location) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt index a9cab888e37..fee22e12f88 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt @@ -9,6 +9,8 @@ import de.rki.coronawarnapp.contactdiary.model.DefaultContactDiaryPersonEncounte import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository import de.rki.coronawarnapp.contactdiary.ui.exporter.ContactDiaryExporter import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem import de.rki.coronawarnapp.contactdiary.util.ContactDiaryData import de.rki.coronawarnapp.contactdiary.util.mockStringsForContactDiaryExporterTests @@ -59,6 +61,7 @@ open class ContactDiaryOverviewViewModelTest { every { contactDiaryRepository.locationVisits } returns flowOf(emptyList()) every { contactDiaryRepository.personEncounters } returns flowOf(emptyList()) every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf(emptyList()) + every { riskLevelStorage.traceLocationCheckInRiskStates } returns flowOf(emptyList()) mockStringsForContactDiaryExporterTests(context) every { timeStamper.nowUTC } returns Instant.now() @@ -137,8 +140,7 @@ open class ContactDiaryOverviewViewModelTest { fun `navigate to day fragment with correct day`() { val listItem = DayOverviewItem( date = date, - data = emptyList(), - risk = null + contactItem = ContactItem(emptyList()) ) {} with(createInstance()) { @@ -163,12 +165,12 @@ open class ContactDiaryOverviewViewModelTest { } as DayOverviewItem with(item) { - data.validate( + contactItem!!.data.validate( hasPerson = true, hasLocation = true ) - risk!!.validate( + riskEnfItem!!.validate( highRisk = false, dueToLowEncounters = false, hasPersonOrLocation = true @@ -185,12 +187,9 @@ open class ContactDiaryOverviewViewModelTest { } as DayOverviewItem with(item) { - data.validate( - hasPerson = false, - hasLocation = false - ) + contactItem shouldBe null - risk!!.validate( + riskEnfItem!!.validate( highRisk = false, dueToLowEncounters = false, hasPersonOrLocation = false @@ -213,12 +212,12 @@ open class ContactDiaryOverviewViewModelTest { } as DayOverviewItem with(item) { - data.validate( + contactItem!!.data.validate( hasPerson = true, hasLocation = true ) - risk!!.validate( + riskEnfItem!!.validate( highRisk = true, dueToLowEncounters = false, hasPersonOrLocation = true @@ -239,12 +238,9 @@ open class ContactDiaryOverviewViewModelTest { } as DayOverviewItem with(item) { - data.validate( - hasPerson = false, - hasLocation = false - ) + contactItem shouldBe null - risk!!.validate( + riskEnfItem!!.validate( highRisk = true, dueToLowEncounters = false, hasPersonOrLocation = false @@ -267,12 +263,12 @@ open class ContactDiaryOverviewViewModelTest { } as DayOverviewItem with(item) { - data.validate( + contactItem!!.data.validate( hasPerson = true, hasLocation = true ) - risk!!.validate( + riskEnfItem!!.validate( highRisk = true, dueToLowEncounters = true, hasPersonOrLocation = true @@ -293,12 +289,9 @@ open class ContactDiaryOverviewViewModelTest { } as DayOverviewItem with(item) { - data.validate( - hasPerson = false, - hasLocation = false - ) + contactItem shouldBe null - risk!!.validate( + riskEnfItem!!.validate( highRisk = true, dueToLowEncounters = true, hasPersonOrLocation = false @@ -332,7 +325,7 @@ open class ContactDiaryOverviewViewModelTest { } } - private fun List.validate(hasPerson: Boolean, hasLocation: Boolean) { + private fun List.validate(hasPerson: Boolean, hasLocation: Boolean) { var count = 0 if (hasPerson) count++ if (hasLocation) count++ @@ -340,17 +333,17 @@ open class ContactDiaryOverviewViewModelTest { size shouldBe count forEach { when (it.type) { - DayOverviewItem.Type.PERSON -> { + ContactItem.Type.PERSON -> { it.drawableId shouldBe R.drawable.ic_contact_diary_person_item } - DayOverviewItem.Type.LOCATION -> { + ContactItem.Type.LOCATION -> { it.drawableId shouldBe R.drawable.ic_contact_diary_location_item } } } } - private fun DayOverviewItem.Risk.validate( + private fun RiskEnfItem.validate( highRisk: Boolean, dueToLowEncounters: Boolean, hasPersonOrLocation: Boolean From aa0346673029bbb1b7045837f2a016956207cd02 Mon Sep 17 00:00:00 2001 From: BMItter Date: Tue, 30 Mar 2021 12:43:19 +0200 Subject: [PATCH 19/30] Added test for risk by event --- .../ContactDiaryOverviewViewModelTest.kt | 204 ++++++++++++++++-- 1 file changed, 192 insertions(+), 12 deletions(-) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt index fee22e12f88..cb445a5ef72 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt @@ -11,9 +11,12 @@ import de.rki.coronawarnapp.contactdiary.ui.exporter.ContactDiaryExporter import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.contact.ContactItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskenf.RiskEnfItem +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.riskevent.RiskEventItem import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem import de.rki.coronawarnapp.contactdiary.util.ContactDiaryData import de.rki.coronawarnapp.contactdiary.util.mockStringsForContactDiaryExporterTests +import de.rki.coronawarnapp.risk.RiskState +import de.rki.coronawarnapp.risk.TraceLocationCheckInRisk import de.rki.coronawarnapp.risk.result.AggregatedRiskPerDateResult import de.rki.coronawarnapp.risk.storage.RiskLevelStorage import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass @@ -72,6 +75,44 @@ open class ContactDiaryOverviewViewModelTest { private val personEncounter = DefaultContactDiaryPersonEncounter(125, date, person) private val locationVisit = DefaultContactDiaryLocationVisit(126, date, location) + private val locationEventLowRisk = DefaultContactDiaryLocation( + locationId = 456, + locationName = "Jahrestreffen der deutschen SAP Anwendergruppe", + traceLocationGUID = "12ab-34cd-56ef-78gh-456" + ) + + private val locationEventHighRisk = DefaultContactDiaryLocation( + locationId = 457, + locationName = "Kiosk", + traceLocationGUID = "12ab-34cd-56ef-78gh-457" + ) + + private val locationEventLowRiskVisit = DefaultContactDiaryLocationVisit( + id = 458, + date = date, + contactDiaryLocation = locationEventLowRisk, + checkInID = 147L + ) + + private val locationEventHighRiskVisit = DefaultContactDiaryLocationVisit( + id = 459, + date = date, + contactDiaryLocation = locationEventHighRisk, + checkInID = 148L + ) + + private val traceLocationCheckInRiskLow = object : TraceLocationCheckInRisk { + override val checkInId: Long = 147 + override val localDate: LocalDate = date + override val riskState: RiskState = RiskState.LOW_RISK + } + + private val traceLocationCheckInRiskHigh = object : TraceLocationCheckInRisk { + override val checkInId: Long = 148 + override val localDate: LocalDate = date + override val riskState: RiskState = RiskState.INCREASED_RISK + } + private val aggregatedRiskPerDateResultLowRisk = AggregatedRiskPerDateResult( dateMillisSinceEpoch = dateMillis, riskLevel = RiskCalculationParametersOuterClass.NormalizedTimeToRiskLevelMapping.RiskLevel.LOW, @@ -79,14 +120,14 @@ open class ContactDiaryOverviewViewModelTest { minimumDistinctEncountersWithHighRisk = 0 ) - private val aggregatedRiskPerDateResultLowRiskDueToHighRiskEncounter = AggregatedRiskPerDateResult( + private val aggregatedRiskPerDateResultHighRiskDueToHighRiskEncounter = AggregatedRiskPerDateResult( dateMillisSinceEpoch = dateMillis, riskLevel = RiskCalculationParametersOuterClass.NormalizedTimeToRiskLevelMapping.RiskLevel.HIGH, minimumDistinctEncountersWithLowRisk = 0, minimumDistinctEncountersWithHighRisk = 1 ) - private val aggregatedRiskPerDateResultLowRiskDueToLowRiskEncounter = AggregatedRiskPerDateResult( + private val aggregatedRiskPerDateResultHighRiskDueToLowRiskEncounter = AggregatedRiskPerDateResult( dateMillisSinceEpoch = dateMillis, riskLevel = RiskCalculationParametersOuterClass.NormalizedTimeToRiskLevelMapping.RiskLevel.HIGH, minimumDistinctEncountersWithLowRisk = 10, @@ -155,7 +196,7 @@ open class ContactDiaryOverviewViewModelTest { } @Test - fun `low risk with person and location`() { + fun `low risk enf with person and location`() { every { contactDiaryRepository.personEncounters } returns flowOf(listOf(personEncounter)) every { contactDiaryRepository.locationVisits } returns flowOf(listOf(locationVisit)) every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf(listOf(aggregatedRiskPerDateResultLowRisk)) @@ -179,7 +220,7 @@ open class ContactDiaryOverviewViewModelTest { } @Test - fun `low risk without person or location`() { + fun `low risk enf without person or location`() { every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf(listOf(aggregatedRiskPerDateResultLowRisk)) val item = createInstance().listItems.getOrAwaitValue().first { @@ -198,12 +239,12 @@ open class ContactDiaryOverviewViewModelTest { } @Test - fun `high risk due to high risk encounter with person and location`() { + fun `high risk enf due to high risk encounter with person and location`() { every { contactDiaryRepository.personEncounters } returns flowOf(listOf(personEncounter)) every { contactDiaryRepository.locationVisits } returns flowOf(listOf(locationVisit)) every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf( listOf( - aggregatedRiskPerDateResultLowRiskDueToHighRiskEncounter + aggregatedRiskPerDateResultHighRiskDueToHighRiskEncounter ) ) @@ -226,10 +267,10 @@ open class ContactDiaryOverviewViewModelTest { } @Test - fun `high risk due to high risk encounter without person or location`() { + fun `high risk enf due to high risk encounter without person or location`() { every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf( listOf( - aggregatedRiskPerDateResultLowRiskDueToHighRiskEncounter + aggregatedRiskPerDateResultHighRiskDueToHighRiskEncounter ) ) @@ -249,12 +290,12 @@ open class ContactDiaryOverviewViewModelTest { } @Test - fun `high risk due to low risk encounter with person and location`() { + fun `high risk enf due to low risk encounter with person and location`() { every { contactDiaryRepository.personEncounters } returns flowOf(listOf(personEncounter)) every { contactDiaryRepository.locationVisits } returns flowOf(listOf(locationVisit)) every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf( listOf( - aggregatedRiskPerDateResultLowRiskDueToLowRiskEncounter + aggregatedRiskPerDateResultHighRiskDueToLowRiskEncounter ) ) @@ -277,10 +318,10 @@ open class ContactDiaryOverviewViewModelTest { } @Test - fun `high risk due to low risk encounter without person or location`() { + fun `high risk enf due to low risk encounter without person or location`() { every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf( listOf( - aggregatedRiskPerDateResultLowRiskDueToLowRiskEncounter + aggregatedRiskPerDateResultHighRiskDueToLowRiskEncounter ) ) @@ -299,6 +340,130 @@ open class ContactDiaryOverviewViewModelTest { } } + @Test + fun `risk enf and risk event are independently of each other`() { + every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf(listOf(aggregatedRiskPerDateResultLowRisk)) + every { riskLevelStorage.traceLocationCheckInRiskStates } returns flowOf(listOf(traceLocationCheckInRiskHigh)) + every { contactDiaryRepository.locationVisits } returns flowOf(listOf(locationEventHighRiskVisit)) + + var item = createInstance().listItems.getOrAwaitValue().first { + it is DayOverviewItem && it.date == date + } as DayOverviewItem + + with(item) { + riskEnfItem!!.validate( + highRisk = false, + dueToLowEncounters = false, + hasPersonOrLocation = true + ) + + riskEventItem!!.validate(highRisk = true) + } + + every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf(listOf(aggregatedRiskPerDateResultHighRiskDueToLowRiskEncounter)) + every { riskLevelStorage.traceLocationCheckInRiskStates } returns flowOf(listOf(traceLocationCheckInRiskLow)) + every { contactDiaryRepository.locationVisits } returns flowOf(listOf(locationEventLowRiskVisit)) + + item = createInstance().listItems.getOrAwaitValue().first { + it is DayOverviewItem && it.date == date + } as DayOverviewItem + + with(item) { + riskEnfItem!!.validate( + highRisk = true, + dueToLowEncounters = true, + hasPersonOrLocation = true + ) + + riskEventItem!!.validate(highRisk = false) + } + } + + @Test + fun `risk event item is null if no trace location check in risk exist`() { + val item = createInstance().listItems.getOrAwaitValue().first { + it is DayOverviewItem && it.date == date + } as DayOverviewItem + + item.riskEventItem shouldBe null + } + + @Test + fun `low risk event by attending event with low risk`() { + every { contactDiaryRepository.locationVisits } returns flowOf(listOf(locationEventLowRiskVisit)) + every { riskLevelStorage.traceLocationCheckInRiskStates } returns flowOf(listOf(traceLocationCheckInRiskLow)) + + val item = createInstance().listItems.getOrAwaitValue().first { + it is DayOverviewItem && it.date == date + } as DayOverviewItem + + with(item) { + riskEventItem!!.validate(highRisk = false) + + riskEventItem!!.events.first().run { + name shouldBe locationEventLowRisk.locationName + riskInfoAddition shouldBe null + bulledPointColor shouldBe R.color.colorBulletPointLowRisk + } + } + } + + @Test + fun `high risk event by attending event with high risk`() { + every { contactDiaryRepository.locationVisits } returns flowOf(listOf(locationEventHighRiskVisit)) + every { riskLevelStorage.traceLocationCheckInRiskStates } returns flowOf(listOf(traceLocationCheckInRiskHigh)) + + val item = createInstance().listItems.getOrAwaitValue().first { + it is DayOverviewItem && it.date == date + } as DayOverviewItem + + with(item) { + riskEventItem!!.validate(highRisk = true) + + riskEventItem!!.events.first().run { + name shouldBe locationEventHighRisk.locationName + riskInfoAddition shouldBe null + bulledPointColor shouldBe R.color.colorBulletPointHighRisk + } + } + } + + @Test + fun `text for each event tells if it caused a high or low risk when multiple events contribute to event risk`() { + every { contactDiaryRepository.locationVisits } returns flowOf( + listOf( + locationEventLowRiskVisit, + locationEventHighRiskVisit + ) + ) + every { riskLevelStorage.traceLocationCheckInRiskStates } returns flowOf( + listOf( + traceLocationCheckInRiskLow, + traceLocationCheckInRiskHigh + ) + ) + + val item = createInstance().listItems.getOrAwaitValue().first { + it is DayOverviewItem && it.date == date + } as DayOverviewItem + + with(item) { + riskEventItem!!.validate(highRisk = true) + + with(riskEventItem!!.events) { + find { it.name == locationEventLowRisk.locationName }!!.also { + it.riskInfoAddition shouldBe R.string.contact_diary_event_risk_low + it.bulledPointColor shouldBe R.color.colorBulletPointLowRisk + } + + find { it.name == locationEventHighRisk.locationName }!!.also { + it.riskInfoAddition shouldBe R.string.contact_diary_event_risk_high + it.bulledPointColor shouldBe R.color.colorBulletPointHighRisk + } + } + } + } + @Test fun `onExportPress() should post export`() { // In this test, now = January, 15 @@ -369,4 +534,19 @@ open class ContactDiaryOverviewViewModelTest { false -> null } } + + private fun RiskEventItem.validate(highRisk: Boolean) { + body shouldBe R.string.contact_diary_event_risk_body + + when (highRisk) { + true -> { + title shouldBe R.string.contact_diary_high_risk_title + drawableId shouldBe R.drawable.ic_high_risk_alert + } + false -> { + title shouldBe R.string.contact_diary_low_risk_title + drawableId shouldBe R.drawable.ic_low_risk_alert + } + } + } } From 0c5648a30e0f9164b4821d49308ad3f6a91d911d Mon Sep 17 00:00:00 2001 From: BMItter Date: Tue, 30 Mar 2021 13:21:40 +0200 Subject: [PATCH 20/30] Adjusted spacing --- ...ntact_diary_overview_day_list_item_risk_event_list_item.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml index 8717b3d9602..ad8947449d9 100644 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml @@ -2,6 +2,8 @@ @@ -16,7 +18,6 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - Date: Tue, 30 Mar 2021 14:09:03 +0200 Subject: [PATCH 21/30] cleanup, missing itemDecoration --- .../overview/ContactDiaryOverviewFragment.kt | 12 +++- .../ui/overview/adapter/day/DayOverviewVH.kt | 2 + ...t_diary_overview_nested_list_item_risk.xml | 60 ------------------- 3 files changed, 12 insertions(+), 62 deletions(-) delete mode 100644 Corona-Warn-App/src/main/res/layout/contact_diary_overview_nested_list_item_risk.xml 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 db541a96cec..74c6aa6b9ef 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 @@ -8,6 +8,7 @@ import androidx.core.app.ShareCompat import androidx.fragment.app.Fragment import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewAdapter +import de.rki.coronawarnapp.contactdiary.util.MarginRecyclerViewDecoration import de.rki.coronawarnapp.databinding.ContactDiaryOverviewFragmentBinding import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.diffutil.update @@ -30,9 +31,16 @@ class ContactDiaryOverviewFragment : Fragment(R.layout.contact_diary_overview_fr val adapter = DiaryOverviewAdapter() - binding.apply { - contactDiaryOverviewRecyclerview.adapter = adapter + binding.contactDiaryOverviewRecyclerview.apply { + this.adapter = adapter + addItemDecoration( + MarginRecyclerViewDecoration( + resources.getDimensionPixelSize(R.dimen.list_item_decoration_card_margins) + ) + ) + } + binding.apply { setupMenu(toolbar) toolbar.setNavigationOnClickListener { vm.onBackButtonPress() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt index 264654f4893..a73525eab6c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt @@ -17,6 +17,8 @@ import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemHeaderBin import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEnfBinding import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEventBinding import de.rki.coronawarnapp.databinding.ContactDiaryOverviewListItemBinding +import de.rki.coronawarnapp.util.lists.decorations.VerticalDividerItemDecorationExcludeLast +import de.rki.coronawarnapp.util.lists.diffutil.update import org.joda.time.LocalDate class DayOverviewVH(parent: ViewGroup) : diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_nested_list_item_risk.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_nested_list_item_risk.xml deleted file mode 100644 index 2ff42829cca..00000000000 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_nested_list_item_risk.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - \ No newline at end of file From fad79a893266a6dd1cab199bac659360d6049fcc Mon Sep 17 00:00:00 2001 From: BMItter Date: Tue, 30 Mar 2021 14:33:31 +0200 Subject: [PATCH 22/30] cleanup, detekt, reduced complexity --- .../ui/overview/ContactDiaryOverviewViewModel.kt | 14 ++++++++++++-- .../ui/overview/adapter/day/DayOverviewVH.kt | 7 +++---- 2 files changed, 15 insertions(+), 6 deletions(-) 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 b31f12ac15d..35a493cb166 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 @@ -96,7 +96,12 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( traceLocationCheckInRiskList: List ): List { Timber.v( - "createListItemList(dateList=%s, visits=%s, encounters=%s, riskLevelPerDateList=%s, traceLocationCheckInRiskList=%s", + "createListItemList(" + + "dateList=%s, " + + "visits=%s, " + + "encounters=%s, " + + "riskLevelPerDateList=%s, " + + "traceLocationCheckInRiskList=%s", dateList, visits, encounters, @@ -121,7 +126,12 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( ?.toRisk(coreItemData.isNotEmpty()) val riskEventItem = visitsForDate - .map { it to traceLocationCheckInRisksForDate.find { checkInRisk -> checkInRisk.checkInId == it.checkInID } } + .map { + it to traceLocationCheckInRisksForDate.find { + checkInRisk -> + checkInRisk.checkInId == it.checkInID + } + } .toMap() .filter { it.value != null } .toRiskEventItem() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt index a73525eab6c..58671eaf6fe 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt @@ -17,8 +17,6 @@ import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemHeaderBin import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEnfBinding import de.rki.coronawarnapp.databinding.ContactDiaryOverviewDayListItemRiskEventBinding import de.rki.coronawarnapp.databinding.ContactDiaryOverviewListItemBinding -import de.rki.coronawarnapp.util.lists.decorations.VerticalDividerItemDecorationExcludeLast -import de.rki.coronawarnapp.util.lists.diffutil.update import org.joda.time.LocalDate class DayOverviewVH(parent: ViewGroup) : @@ -70,7 +68,8 @@ class DayOverviewVH(parent: ViewGroup) : } } - private fun ContactDiaryOverviewDayListItemRiskEventBinding.apply(riskEventItem: RiskEventItem?) = this.apply { + private fun ContactDiaryOverviewDayListItemRiskEventBinding + .apply(riskEventItem: RiskEventItem?) { root.isGone = riskEventItem == null riskEventItem?.let { @@ -90,7 +89,7 @@ class DayOverviewVH(parent: ViewGroup) : } } - private fun ContactDiaryOverviewDayListItemContactBinding.apply(contactItem: ContactItem?) = this.apply { + private fun ContactDiaryOverviewDayListItemContactBinding.apply(contactItem: ContactItem?) { root.isGone = contactItem == null contactItem?.let { From c3a79f7f500334d2d749dcfb18573191ec3b5179 Mon Sep 17 00:00:00 2001 From: BMItter Date: Wed, 31 Mar 2021 13:00:27 +0200 Subject: [PATCH 23/30] named params --- .../storage/ContactDiaryDatabaseMigrationTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt index cee61ec50ba..49a0b1a8750 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt @@ -115,7 +115,7 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { locationName = "Location1", phoneNumber = null, emailAddress = null, - null + traceLocationGUID = null ) runBlocking { daoDb.locationDao().allEntries().first() }.single() shouldBe location @@ -137,7 +137,7 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { fkLocationId = 1, duration = null, circumstances = null, - null + checkInID = null ) ) @@ -173,7 +173,7 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { fkLocationId = 1, duration = Duration.standardMinutes(13), circumstances = "That's none of your business", - null + checkInID = null ) val locationAfter = location.copy(traceLocationGUID = "jshrgu-aifhioaio-aofsjof-samofp-kjsadngsgf") From 41011b44cdabf37fd2f383a5c5ae1b8155d98258 Mon Sep 17 00:00:00 2001 From: BMItter Date: Wed, 31 Mar 2021 13:01:55 +0200 Subject: [PATCH 24/30] Use srcCompat --- .../contact_diary_overview_day_list_item_header.xml | 4 ++-- ..._overview_day_list_item_risk_event_list_item.xml | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml index 0adc3fb4c63..e5d9f870cbe 100644 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_header.xml @@ -27,9 +27,9 @@ android:layout_marginEnd="@dimen/spacing_small" android:importantForAccessibility="no" android:scaleType="centerInside" - android:src="@drawable/ic_contact_diary_right_arrow" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/ic_contact_diary_right_arrow" /> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml index ad8947449d9..84e81ece535 100644 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_day_list_item_risk_event_list_item.xml @@ -1,11 +1,11 @@ + android:focusable="true"> + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/bullet_point" /> + \ No newline at end of file From bc3e4c94025c51f721db148678c4d941d47885b0 Mon Sep 17 00:00:00 2001 From: BMItter Date: Wed, 31 Mar 2021 13:06:50 +0200 Subject: [PATCH 25/30] replaced event with trace location --- .../rki/coronawarnapp/ui/contactdiary/DiaryData.kt | 8 ++++---- .../src/main/res/values-de/contact_diary_strings.xml | 12 ++++++------ .../src/main/res/values/contact_diary_strings.xml | 12 ++++++------ .../ui/overview/ContactDiaryOverviewViewModelTest.kt | 6 +++--- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt index d4639ca1391..49c71ca142a 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt @@ -86,25 +86,25 @@ object DiaryData { val HIGH_RISK_EVENT = RiskEventItem.Event( name = HIGH_RISK_EVENT_LOCATION.name, bulledPointColor = R.color.colorBulletPointHighRisk, - riskInfoAddition = R.string.contact_diary_event_risk_high + riskInfoAddition = R.string.contact_diary_trace_location_risk_high ) val LOW_RISK_EVENT = RiskEventItem.Event( name = LOW_RISK_EVENT_LOCATION.name, bulledPointColor = R.color.colorBulletPointLowRisk, - riskInfoAddition = R.string.contact_diary_event_risk_low + riskInfoAddition = R.string.contact_diary_trace_location_risk_low ) val HIGH_RISK_EVENT_ITEM = RiskEventItem( title = R.string.contact_diary_high_risk_title, - body = R.string.contact_diary_event_risk_body, + body = R.string.contact_diary_trace_location_risk_body, drawableId = R.drawable.ic_high_risk_alert, events = listOf(HIGH_RISK_EVENT, LOW_RISK_EVENT) ) val LOW_RISK_EVENT_ITEM = RiskEventItem( title = R.string.contact_diary_low_risk_title, - body = R.string.contact_diary_event_risk_body, + body = R.string.contact_diary_trace_location_risk_body, drawableId = R.drawable.ic_low_risk_alert, events = listOf(LOW_RISK_EVENT) ) diff --git a/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml index 2a83135cb85..0eab91a325c 100644 --- a/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml @@ -77,12 +77,12 @@ "aufgrund von mehreren Begegnungen mit niedrigem Risiko." "Diese müssen nicht in Zusammenhang mit den von Ihnen erfassten Personen und Orten stehen." - - "aufgrund ihrer Anwesenheit bei:" - - "erhöhtes Risiko" - - "niedriges Risiko" + + "aufgrund ihrer Anwesenheit bei:" + + "erhöhtes Risiko" + + "niedriges Risiko" diff --git a/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml index e73145f14f8..e67b86cde10 100644 --- a/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml +++ b/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml @@ -77,12 +77,12 @@ "based on multiple exposures with low risk." "They are not necessarily related to the people and places you have recorded." - - "" - - "" - - "" + + "" + + "" + + "" "A closed book with a bookmark" diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt index cb445a5ef72..c544dd3a901 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt @@ -452,12 +452,12 @@ open class ContactDiaryOverviewViewModelTest { with(riskEventItem!!.events) { find { it.name == locationEventLowRisk.locationName }!!.also { - it.riskInfoAddition shouldBe R.string.contact_diary_event_risk_low + it.riskInfoAddition shouldBe R.string.contact_diary_trace_location_risk_low it.bulledPointColor shouldBe R.color.colorBulletPointLowRisk } find { it.name == locationEventHighRisk.locationName }!!.also { - it.riskInfoAddition shouldBe R.string.contact_diary_event_risk_high + it.riskInfoAddition shouldBe R.string.contact_diary_trace_location_risk_high it.bulledPointColor shouldBe R.color.colorBulletPointHighRisk } } @@ -536,7 +536,7 @@ open class ContactDiaryOverviewViewModelTest { } private fun RiskEventItem.validate(highRisk: Boolean) { - body shouldBe R.string.contact_diary_event_risk_body + body shouldBe R.string.contact_diary_trace_location_risk_body when (highRisk) { true -> { From 7910de47d70ca2bbef492b57eecd262f5a41c95d Mon Sep 17 00:00:00 2001 From: BMItter Date: Wed, 31 Mar 2021 13:14:52 +0200 Subject: [PATCH 26/30] Respecting the tech spec --- .../storage/ContactDiaryDatabaseMigrationTest.kt | 6 +++--- .../contactdiary/storage/ContactDiaryDatabaseTest.kt | 2 +- .../contactdiary/model/ContactDiaryLocation.kt | 2 +- .../contactdiary/model/DefaultContactDiaryLocation.kt | 2 +- .../storage/entity/ContactDiaryLocationEntity.kt | 4 ++-- .../migrations/ContactDiaryDatabaseMigration2To3.kt | 4 ++-- .../ui/edit/ContactDiaryEditLocationsViewModelTest.kt | 2 +- .../ui/overview/ContactDiaryOverviewViewModelTest.kt | 4 ++-- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt index 49a0b1a8750..96435f4c2c2 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt @@ -115,7 +115,7 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { locationName = "Location1", phoneNumber = null, emailAddress = null, - traceLocationGUID = null + traceLocationID = null ) runBlocking { daoDb.locationDao().allEntries().first() }.single() shouldBe location @@ -164,7 +164,7 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { locationName = "Why do you want to have this information?", phoneNumber = "I'm not going to tell you yet", emailAddress = "I'mnotgoingtotell@you.yet", - traceLocationGUID = null + traceLocationID = null ) val locationVisit = ContactDiaryLocationVisitEntity( @@ -176,7 +176,7 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { checkInID = null ) - val locationAfter = location.copy(traceLocationGUID = "jshrgu-aifhioaio-aofsjof-samofp-kjsadngsgf") + val locationAfter = location.copy(traceLocationID = "jshrgu-aifhioaio-aofsjof-samofp-kjsadngsgf") val locationVisitAfter = locationVisit.copy(checkInID = 101) val locationValues = ContentValues().apply { diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseTest.kt index 17f3795b0cc..e3573457d05 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseTest.kt @@ -37,7 +37,7 @@ class ContactDiaryDatabaseTest : BaseTestInstrumentation() { locationName = "Rewe Wiesloch", emailAddress = "location-emailAddress", phoneNumber = "location-phoneNumber", - traceLocationGUID = "a-b-c-d" + traceLocationID = "a-b-c-d" ) private val personEncounter = ContactDiaryPersonEncounterEntity( id = 3, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocation.kt index c0116d8026f..e0486049d69 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocation.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/model/ContactDiaryLocation.kt @@ -8,7 +8,7 @@ interface ContactDiaryLocation : HasStableId { var locationName: String val phoneNumber: String? val emailAddress: String? - val traceLocationGUID: String? + val traceLocationID: String? } fun List.sortByNameAndIdASC(): List = 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 a9ef1b4bfcf..c121e261124 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 @@ -5,7 +5,7 @@ data class DefaultContactDiaryLocation( override var locationName: String, override val phoneNumber: String? = null, override val emailAddress: String? = null, - override val traceLocationGUID: String? = null + override val traceLocationID: String? = null ) : ContactDiaryLocation { override val stableId: Long get() = locationId diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt index c552279d64c..b09a84c8fb4 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt @@ -15,7 +15,7 @@ data class ContactDiaryLocationEntity( @ColumnInfo(name = "locationName") override var locationName: String, override val phoneNumber: String?, override val emailAddress: String?, - @ColumnInfo(name = "traceLocationGUID") override val traceLocationGUID: String? + @ColumnInfo(name = "traceLocationID") override val traceLocationID: String? ) : ContactDiaryLocation, Parcelable { override val stableId: Long get() = locationId @@ -30,5 +30,5 @@ fun ContactDiaryLocation.toContactDiaryLocationEntity(): ContactDiaryLocationEnt locationName = this.locationName.trimMaxCharacters(), phoneNumber = this.phoneNumber?.trimMaxCharacters(), emailAddress = this.emailAddress?.trimMaxCharacters(), - traceLocationGUID = this.traceLocationGUID + traceLocationID = this.traceLocationID ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/internal/migrations/ContactDiaryDatabaseMigration2To3.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/internal/migrations/ContactDiaryDatabaseMigration2To3.kt index 76706e36555..8cfe9235a45 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/internal/migrations/ContactDiaryDatabaseMigration2To3.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/internal/migrations/ContactDiaryDatabaseMigration2To3.kt @@ -34,8 +34,8 @@ object ContactDiaryDatabaseMigration2To3 : Migration(2, 3) { } private val migrateLocationsTable: SupportSQLiteDatabase.() -> Unit = { - Timber.d("Table 'locations': Add column 'traceLocationGUID'") - execSQL("ALTER TABLE `locations` ADD COLUMN `traceLocationGUID` TEXT") + Timber.d("Table 'locations': Add column 'traceLocationID'") + execSQL("ALTER TABLE `locations` ADD COLUMN `traceLocationID` TEXT") } private val migrateLocationVisitTable: SupportSQLiteDatabase.() -> Unit = { diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModelTest.kt index d07c90de283..e8ee5c3275b 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/edit/ContactDiaryEditLocationsViewModelTest.kt @@ -30,7 +30,7 @@ class ContactDiaryEditLocationsViewModelTest { override val phoneNumber: String? = null override val emailAddress: String? = null override val stableId = 1L - override val traceLocationGUID: String? = null + override val traceLocationID: String? = null } private val locationList = listOf(location) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt index c544dd3a901..8f56156ca58 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt @@ -78,13 +78,13 @@ open class ContactDiaryOverviewViewModelTest { private val locationEventLowRisk = DefaultContactDiaryLocation( locationId = 456, locationName = "Jahrestreffen der deutschen SAP Anwendergruppe", - traceLocationGUID = "12ab-34cd-56ef-78gh-456" + traceLocationID = "12ab-34cd-56ef-78gh-456" ) private val locationEventHighRisk = DefaultContactDiaryLocation( locationId = 457, locationName = "Kiosk", - traceLocationGUID = "12ab-34cd-56ef-78gh-457" + traceLocationID = "12ab-34cd-56ef-78gh-457" ) private val locationEventLowRiskVisit = DefaultContactDiaryLocationVisit( From 9df09cf03e041abbd9397f0d77ebeb42bf097f37 Mon Sep 17 00:00:00 2001 From: BMItter Date: Wed, 31 Mar 2021 14:19:03 +0200 Subject: [PATCH 27/30] conflicts resolved for OverviewViewModel --- .../ui/overview/ContactDiaryOverviewViewModel.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 35a493cb166..6b9780d0369 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 @@ -26,7 +26,7 @@ import de.rki.coronawarnapp.risk.storage.RiskLevelStorage import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass import de.rki.coronawarnapp.task.TaskController import de.rki.coronawarnapp.task.common.DefaultTaskRequest -import de.rki.coronawarnapp.util.TimeAndDateExtensions.toLocalDate +import de.rki.coronawarnapp.util.TimeAndDateExtensions.toLocalDateUtc import de.rki.coronawarnapp.util.TimeStamper import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.ui.SingleLiveEvent @@ -50,7 +50,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( val routeToScreen: SingleLiveEvent = SingleLiveEvent() val exportLocationsAndPersons: SingleLiveEvent = SingleLiveEvent() - private val dates = (0 until DAY_COUNT).map { timeStamper.nowUTC.toLocalDate().minusDays(it) } + private val dates = (0 until DAY_COUNT).map { timeStamper.nowUTC.toLocalDateUtc().minusDays(it) } private val locationVisitsFlow = contactDiaryRepository.locationVisits private val personEncountersFlow = contactDiaryRepository.personEncounters @@ -112,7 +112,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( val visitsForDate = visits.filter { it.date == date } val encountersForDate = encounters.filter { it.date == date } - val traceLocationCheckInRisksForDate = traceLocationCheckInRiskList.filter { it.localDate == date } + val traceLocationCheckInRisksForDate = traceLocationCheckInRiskList.filter { it.localDateUtc == date } val coreItemData = encountersForDate.map { it.toContactItemData() } + visitsForDate.map { it.toContactItemData() } @@ -122,13 +122,13 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( } val riskEnf = riskLevelPerDateList - .firstOrNull { riskLevelPerDate -> riskLevelPerDate.day == date } + .firstOrNull { riskLevelPerDate -> riskLevelPerDate.localDateUtc == date } ?.toRisk(coreItemData.isNotEmpty()) val riskEventItem = visitsForDate .map { it to traceLocationCheckInRisksForDate.find { - checkInRisk -> + checkInRisk -> checkInRisk.checkInId == it.checkInID } } @@ -192,7 +192,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( val isHighRisk = values.any { it?.riskState == RiskState.INCREASED_RISK } - val body: Int = R.string.contact_diary_event_risk_body + val body: Int = R.string.contact_diary_trace_location_risk_body val drawableID: Int val title: Int @@ -218,11 +218,11 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( when (entry.value?.riskState == RiskState.INCREASED_RISK) { true -> { bulletPointColor = R.color.colorBulletPointHighRisk - riskInfoAddition = R.string.contact_diary_event_risk_high + riskInfoAddition = R.string.contact_diary_trace_location_risk_high } false -> { bulletPointColor = R.color.colorBulletPointLowRisk - riskInfoAddition = R.string.contact_diary_event_risk_low + riskInfoAddition = R.string.contact_diary_trace_location_risk_low } } From 6826a75110a21e684023a577dfb6fe6f8bb9b861 Mon Sep 17 00:00:00 2001 From: BMItter Date: Wed, 31 Mar 2021 14:23:16 +0200 Subject: [PATCH 28/30] source clean --- .../3.json | 10 +++++----- .../ui/overview/ContactDiaryOverviewViewModel.kt | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Corona-Warn-App/schemas/de.rki.coronawarnapp.contactdiary.storage.ContactDiaryDatabase/3.json b/Corona-Warn-App/schemas/de.rki.coronawarnapp.contactdiary.storage.ContactDiaryDatabase/3.json index e0a59f046ba..4659001bb1a 100644 --- a/Corona-Warn-App/schemas/de.rki.coronawarnapp.contactdiary.storage.ContactDiaryDatabase/3.json +++ b/Corona-Warn-App/schemas/de.rki.coronawarnapp.contactdiary.storage.ContactDiaryDatabase/3.json @@ -2,11 +2,11 @@ "formatVersion": 1, "database": { "version": 3, - "identityHash": "f962ae2729d9b71eb3ed3fc51a110b95", + "identityHash": "0c01fcfc2460488a75680c56f829ab79", "entities": [ { "tableName": "locations", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationName` TEXT NOT NULL, `phoneNumber` TEXT, `emailAddress` TEXT, `traceLocationGUID` TEXT)", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`locationId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationName` TEXT NOT NULL, `phoneNumber` TEXT, `emailAddress` TEXT, `traceLocationID` TEXT)", "fields": [ { "fieldPath": "locationId", @@ -33,8 +33,8 @@ "notNull": false }, { - "fieldPath": "traceLocationGUID", - "columnName": "traceLocationGUID", + "fieldPath": "traceLocationID", + "columnName": "traceLocationID", "affinity": "TEXT", "notNull": false } @@ -238,7 +238,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f962ae2729d9b71eb3ed3fc51a110b95')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '0c01fcfc2460488a75680c56f829ab79')" ] } } \ No newline at end of file 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 6b9780d0369..36b4bb566ec 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 @@ -128,7 +128,7 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor( val riskEventItem = visitsForDate .map { it to traceLocationCheckInRisksForDate.find { - checkInRisk -> + checkInRisk -> checkInRisk.checkInId == it.checkInID } } From 4fca5ccefca51498f5e07c3ca873c30701027ea6 Mon Sep 17 00:00:00 2001 From: BMItter Date: Wed, 31 Mar 2021 15:06:18 +0200 Subject: [PATCH 29/30] fix conflicts to newest 2.0 merge --- .../ui/overview/ContactDiaryOverviewViewModelTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt index 8f56156ca58..80768278381 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt @@ -103,13 +103,13 @@ open class ContactDiaryOverviewViewModelTest { private val traceLocationCheckInRiskLow = object : TraceLocationCheckInRisk { override val checkInId: Long = 147 - override val localDate: LocalDate = date + override val localDateUtc: LocalDate = date override val riskState: RiskState = RiskState.LOW_RISK } private val traceLocationCheckInRiskHigh = object : TraceLocationCheckInRisk { override val checkInId: Long = 148 - override val localDate: LocalDate = date + override val localDateUtc: LocalDate = date override val riskState: RiskState = RiskState.INCREASED_RISK } From 91602dee7ab491353882074182849f62fdf8be6c Mon Sep 17 00:00:00 2001 From: BMItter Date: Wed, 31 Mar 2021 16:05:28 +0200 Subject: [PATCH 30/30] resolve merged migration test conflict --- .../storage/ContactDiaryDatabaseMigrationTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt index 96435f4c2c2..dd683c4bb19 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryDatabaseMigrationTest.kt @@ -257,11 +257,11 @@ class ContactDiaryDatabaseMigrationTest : BaseTestInstrumentation() { } @Test - fun migrate2To3_failure_throws() { + fun migrate2To3_failure_throws_SQLiteException() { helper.createDatabase(DB_NAME, 2).apply { execSQL("DROP TABLE IF EXISTS locations") - // Has incompatible existing column phoneNumber of wrong type - execSQL("CREATE TABLE IF NOT EXISTS `locations` (`locationId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationName` TEXT NOT NULL, `phoneNumber` TEXT, `emailAddress` TEXT, `traceLocationGUID` INTEGER)") + // Has incompatible existing column traceLocationID of wrong type + execSQL("CREATE TABLE IF NOT EXISTS `locations` (`locationId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `locationName` TEXT NOT NULL, `phoneNumber` TEXT, `emailAddress` TEXT, `traceLocationID` INTEGER)") close() }