Repository: thunderbird/thunderbird-android
File: legacy/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/item/MessageItemContent.kt (Kotlin)

Code before:
                    ContactImageAvatar(
                        address = item.displayAddress ?: Address(""),
                        imageLoader = imageLoader,
                    )
                }
            },
            onClick = onClick,
            onLongClick = onLongClick,
            onLeadingClick = onAvatarClick,
            onFavouriteChange = onFavouriteClick,
            favourite = item.isStarred,
            selected = isSelected,
            maxPreviewLines = appearance.previewLines,
            threadCount = item.threadCount,
            hasAttachments = item.hasAttachments,
            swapSenderWithSubject = !appearance.senderAboveSubject,
        )
    }
}

@Composable
fun ContactImageAvatar(address: Address, imageLoader: ImageLoader, modifier: Modifier = Modifier) {
    val model = remember(address) {
        ContactImageModel(address = address, contactLetterOnly = false)
    }
    CoilImage(
        imageModel = { model },
        imageLoader = { imageLoader },
        imageOptions = ImageOptions(
            contentScale = ContentScale.Crop,
            alignment = Alignment.Center,
        ),
        modifier = modifier
            .size(40.dp)
            .clip(CircleShape),
        loading = {
            CircularProgressIndicator(modifier = Modifier.size(20.dp))
        },
    )
}


Review comment (bug):
Instead of using `CoilImage` directly. We already have a `RemoteImage` in the design system.

I think you would need a updated version which allows you to provide a nullable url and instead of the placeholder, a loading and a separate failure view.

Code after:
                        onAvatarClick = onAvatarClick,
                    )
                }
            },
            onClick = onClick,
            onLongClick = onLongClick,
            onLeadingClick = onAvatarClick,
            onFavouriteChange = onFavouriteClick,
            favourite = item.isStarred,
            selected = isSelected,
            maxPreviewLines = appearance.previewLines,
            threadCount = item.threadCount,
            hasAttachments = item.hasAttachments,
            swapSenderWithSubject = !appearance.senderAboveSubject,
        )

        else -> UnreadMessageItem(
            sender = "${item.displayName}",
            subject = item.subject ?: "n/a",
            preview = item.previewText,
            receivedAt = receivedAt,
            avatar = {
                if (appearance.showContactPicture) {
                    ContactImageAvatar(
                        contactImageUri = uri,
                        contactImageMonogram = monogram,
                        onAvatarClick = onAvatarClick,
                    )
                }
            },
            onClick = onClick,
            onLongClick = onLongClick,
            onLeadingClick = onAvatarClick,
            onFavouriteChange = onFavouriteClick,
            favourite = item.isStarred,
            selected = isSelected,
            maxPreviewLines = appearance.previewLines,
            threadCount = item.threadCount,
            hasAttachments = item.hasAttachments,
            swapSenderWithSubject = !appearance.senderAboveSubject,
        )
    }
}

@Composable
fun ContactImageAvatar(
    contactImageUri: Uri?,
    contactImageMonogram: String,
    modifier: Modifier = Modifier,
    onAvatarClick: () -> Unit,
) {