From 79aff9104aecf30a70ea638696a3b402b53034d8 Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Fri, 17 Dec 2021 23:54:10 +0100 Subject: [PATCH] Replaced elmo avatar placeholder by Color+Initial --- .../kotlin/app/images/NetworkImageLoader.kt | 13 ++-- src/main/kotlin/app/ui/CommitChanges.kt | 11 ++-- .../kotlin/app/ui/components/AvatarImage.kt | 62 ++++++++++++++++++ src/main/kotlin/app/ui/log/Log.kt | 12 ++-- src/main/resources/image.jpg | Bin 5658 -> 0 bytes 5 files changed, 78 insertions(+), 20 deletions(-) create mode 100644 src/main/kotlin/app/ui/components/AvatarImage.kt delete mode 100644 src/main/resources/image.jpg diff --git a/src/main/kotlin/app/images/NetworkImageLoader.kt b/src/main/kotlin/app/images/NetworkImageLoader.kt index f8360c6..f5e8cf0 100644 --- a/src/main/kotlin/app/images/NetworkImageLoader.kt +++ b/src/main/kotlin/app/images/NetworkImageLoader.kt @@ -49,16 +49,18 @@ object NetworkImageLoader { } } - @Composable -fun rememberNetworkImage(url: String): ImageBitmap { +fun rememberNetworkImageOrNull(url: String, placeHolderImageRes: String? = null): ImageBitmap? { val networkImageLoader = NetworkImageLoader var image by remember(url) { - mutableStateOf( - useResource("image.jpg") { + val placeHolderImage = if(placeHolderImageRes != null) + useResource(placeHolderImageRes) { Image.makeFromEncoded(it.toByteArray()).toComposeImageBitmap() } - ) + else + null + + mutableStateOf(placeHolderImage) } LaunchedEffect(url) { @@ -71,4 +73,3 @@ fun rememberNetworkImage(url: String): ImageBitmap { } fun ByteArray.toComposeImage() = Image.makeFromEncoded(this).toComposeImageBitmap() - diff --git a/src/main/kotlin/app/ui/CommitChanges.kt b/src/main/kotlin/app/ui/CommitChanges.kt index b341982..76144a9 100644 --- a/src/main/kotlin/app/ui/CommitChanges.kt +++ b/src/main/kotlin/app/ui/CommitChanges.kt @@ -20,11 +20,11 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import app.extensions.* import app.git.GitManager -import app.images.rememberNetworkImage import app.theme.headerBackground import app.theme.headerText import app.theme.primaryTextColor import app.theme.secondaryTextColor +import app.ui.components.AvatarImage import app.ui.components.ScrollableLazyColumn import app.ui.components.TooltipText import org.eclipse.jgit.diff.DiffEntry @@ -108,14 +108,11 @@ fun Author(commit: RevCommit) { .background(MaterialTheme.colors.background), verticalAlignment = Alignment.CenterVertically ) { - val url = "https://www.gravatar.com/avatar/${authorIdent.emailAddress.md5}" - Image( - bitmap = rememberNetworkImage(url), + AvatarImage( modifier = Modifier .padding(horizontal = 16.dp) - .height(40.dp) - .clip(CircleShape), - contentDescription = null, + .size(40.dp), + personIdent = commit.authorIdent, ) Column( diff --git a/src/main/kotlin/app/ui/components/AvatarImage.kt b/src/main/kotlin/app/ui/components/AvatarImage.kt new file mode 100644 index 0000000..8425483 --- /dev/null +++ b/src/main/kotlin/app/ui/components/AvatarImage.kt @@ -0,0 +1,62 @@ +package app.ui.components + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap +import app.extensions.md5 +import app.images.rememberNetworkImageOrNull +import org.eclipse.jgit.lib.PersonIdent + +@Composable +fun AvatarImage( + modifier: Modifier = Modifier, + personIdent: PersonIdent, + color: Color = MaterialTheme.colors.primary +) { + Box( + modifier = modifier + .clip(CircleShape) + ) { + val avatar = rememberAvatar(personIdent.emailAddress) + if(avatar == null) { + Box( + modifier = Modifier + .fillMaxSize() + .background(color), + contentAlignment = Alignment.Center, + ) { + Text( + text = personIdent.name.firstOrNull()?.uppercase() ?: "#", + color = Color.White, + ) + } + } else { + Image( + bitmap = avatar, + modifier = Modifier + .fillMaxSize(), + contentDescription = null, + ) + } + } +} + + +@Composable +fun rememberAvatar(email: String): ImageBitmap? { + val url = "https://www.gravatar.com/avatar/${email.md5}?s=60&d=404" + return rememberNetworkImageOrNull( + url = url, + placeHolderImageRes = null, + ) +} \ No newline at end of file diff --git a/src/main/kotlin/app/ui/log/Log.kt b/src/main/kotlin/app/ui/log/Log.kt index 1c34412..b410251 100644 --- a/src/main/kotlin/app/ui/log/Log.kt +++ b/src/main/kotlin/app/ui/log/Log.kt @@ -37,9 +37,9 @@ import app.extensions.* import app.git.GitManager import app.git.LogStatus import app.git.graph.GraphNode -import app.images.rememberNetworkImage import app.theme.* import app.ui.SelectedItem +import app.ui.components.AvatarImage import app.ui.components.ScrollableLazyColumn import app.ui.context_menu.branchContextMenuItems import app.ui.context_menu.tagContextMenuItems @@ -592,12 +592,10 @@ fun CommitNode( .border(2.dp, color, shape = CircleShape) .clip(CircleShape) ) { - val url = "https://www.gravatar.com/avatar/${plotCommit.authorIdent.emailAddress.md5}?s=60" - Image( - bitmap = rememberNetworkImage(url), - modifier = Modifier - .fillMaxSize(), - contentDescription = null + AvatarImage( + modifier = Modifier.fillMaxSize(), + personIdent = plotCommit.authorIdent, + color = color, ) } } diff --git a/src/main/resources/image.jpg b/src/main/resources/image.jpg deleted file mode 100644 index 514f3f20b4ad119b969c7f370a4dac67cddeac36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5658 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 Pkn~jKy?YU(m(%|PcZZSV