Repository: corona-warn-app/cwa-app-android
File: Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/contact/ContactAdapter.kt (Kotlin)

Code before:

    override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): ContactItemViewHolder = ContactItemViewHolder(parent)

    override fun onBindBaseVH(holder: ContactItemViewHolder, position: Int, payloads: MutableList<Any>) {
        holder.bind(dataList[position], payloads)
    }

    override fun getItemCount(): Int = dataList.size

    inner class ContactItemViewHolder(parent: ViewGroup) :
        VH(R.layout.contact_diary_overview_nested_list_item, parent),
        BindableVH<ContactItem.Data, ContactDiaryOverviewNestedListItemBinding> {
        override val viewBinding: Lazy<ContactDiaryOverviewNestedListItemBinding> =
            lazy { ContactDiaryOverviewNestedListItemBinding.bind(itemView) }

        override val onBindData: ContactDiaryOverviewNestedListItemBinding.(
            item: ContactItem.Data,
            payloads: List<Any>
        ) -> Unit = { key, _ ->
            contactDiaryOverviewElementImage.setImageResource(key.drawableId)
            contactDiaryOverviewElementName.text = key.name
            contactDiaryOverviewElementNestedBody.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).dropLast(2)
            if (attributes.isNotEmpty()) {
                contactDiaryOverviewElementAttributes.text = attributes
            } else contactDiaryOverviewElementAttributes.visibility = View.GONE
        }

        private fun getAttributes(
            duration: Duration?,
            resources: List<Int>?,
            circumstances: String?,
            separator: String = ", "
        ): SpannableStringBuilder =
            SpannableStringBuilder().apply {
                duration?.run {
                    if (duration != Duration.ZERO) {
                        val durationSuffix = context.getString(R.string.contact_diary_location_visit_duration_hour)
                        append(toReadableDuration(suffix = durationSuffix))
                        append(separator)
                    }
                }
                resources?.run {
                    forEach {
                        append(context.getString(it))
                        append(separator)
                    }
                }

Review comment (suggestion):
I think this only works when circumstances are null. If circumstances are appended it would chop off the last chars of them

Code after:

    override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): ContactItemViewHolder = ContactItemViewHolder(parent)

    override fun onBindBaseVH(holder: ContactItemViewHolder, position: Int, payloads: MutableList<Any>) {
        holder.bind(dataList[position], payloads)
    }

    override fun getItemCount(): Int = dataList.size

    inner class ContactItemViewHolder(parent: ViewGroup) :
        VH(R.layout.contact_diary_overview_nested_list_item, parent),
        BindableVH<ContactItem.Data, ContactDiaryOverviewNestedListItemBinding> {
        override val viewBinding: Lazy<ContactDiaryOverviewNestedListItemBinding> =
            lazy { ContactDiaryOverviewNestedListItemBinding.bind(itemView) }

        override val onBindData: ContactDiaryOverviewNestedListItemBinding.(
            item: ContactItem.Data,
            payloads: List<Any>
        ) -> Unit = { key, _ ->
            contactDiaryOverviewElementImage.setImageResource(key.drawableId)
            contactDiaryOverviewElementName.text = key.name
            contactDiaryOverviewElementNestedBody.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
        }

        @Suppress("NestedBlockDepth")
        private fun getAttributes(
            duration: Duration?,
            resources: List<Int>?,
            circumstances: String?,
            separator: String = ", "
        ): SpannableStringBuilder =
            SpannableStringBuilder().apply {
                duration?.run {
                    if (duration != Duration.ZERO) {
                        val durationSuffix = context.getString(R.string.contact_diary_location_visit_duration_hour)
                        append(toReadableDuration(suffix = durationSuffix))
                        if (resources != null) append(separator)
                    }
                }
                resources?.run {
                    append(
                        resources.joinToString(separator) {
                            context.getString(it)
                        }