diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/UserAvatar.kt b/app/src/main/java/com/geeksville/mesh/ui/components/UserAvatar.kt new file mode 100644 index 000000000..7bd36564b --- /dev/null +++ b/app/src/main/java/com/geeksville/mesh/ui/components/UserAvatar.kt @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025 Meshtastic LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.geeksville.mesh.ui.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.rememberTextMeasurer +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import com.geeksville.mesh.model.Node +import com.geeksville.mesh.ui.preview.NodePreviewParameterProvider +import com.geeksville.mesh.ui.theme.AppTheme + +@Composable +fun UserAvatar( + node: Node, + modifier: Modifier = Modifier, + onClick: () -> Unit = {} +) { + val textMeasurer = rememberTextMeasurer() + val textStyle = MaterialTheme.typography.button.copy( + fontWeight = FontWeight.Normal, + ) + val textLayoutResult = remember { + textMeasurer.measure(text = "MMMM", style = textStyle) + } + + Box( + contentAlignment = Alignment.Center, + modifier = modifier + .size(with(LocalDensity.current) { textLayoutResult.size.width.toDp() }) + .background( + color = Color(node.colors.second), + shape = CircleShape + ) + .clickable(onClick = onClick) + ) { + Text( + text = node.user.shortName.ifEmpty { "?" }, + color = Color(node.colors.first), + style = textStyle, + textAlign = TextAlign.Center, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + ) + } +} + +@Preview(showBackground = true) +@Composable +private fun AvatarPreview( + @PreviewParameter(NodePreviewParameterProvider::class) + node: Node +) { + AppTheme { + UserAvatar(node) + } +} diff --git a/app/src/main/java/com/geeksville/mesh/ui/message/components/MessageItem.kt b/app/src/main/java/com/geeksville/mesh/ui/message/components/MessageItem.kt index 3764e7b97..5aeccf99c 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/message/components/MessageItem.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/message/components/MessageItem.kt @@ -27,12 +27,8 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Card -import androidx.compose.material.Chip -import androidx.compose.material.ChipDefaults -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.Icon import androidx.compose.material.LocalTextStyle import androidx.compose.material.MaterialTheme @@ -51,8 +47,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp @@ -62,11 +56,12 @@ import com.geeksville.mesh.MessageStatus import com.geeksville.mesh.R import com.geeksville.mesh.model.Node import com.geeksville.mesh.ui.components.AutoLinkText +import com.geeksville.mesh.ui.components.UserAvatar import com.geeksville.mesh.ui.preview.NodePreviewParameterProvider import com.geeksville.mesh.ui.theme.AppTheme @Suppress("LongMethod", "CyclomaticComplexMethod") -@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class) +@OptIn(ExperimentalFoundationApi::class) @Composable internal fun MessageItem( node: Node, @@ -95,6 +90,15 @@ internal fun MessageItem( Modifier.padding(start = 8.dp, top = 8.dp, end = 0.dp, bottom = 6.dp) } + if (!fromLocal) { + UserAvatar( + node = node, + modifier = Modifier + .padding(start = 8.dp, top = 8.dp) + .align(Alignment.Top), + ) { onChipClick() } + } + Card( modifier = Modifier .weight(1f) @@ -115,26 +119,6 @@ internal fun MessageItem( .padding(horizontal = 8.dp), verticalAlignment = Alignment.CenterVertically, ) { - if (!fromLocal) { - Chip( - onClick = onChipClick, - modifier = Modifier - .padding(end = 8.dp) - .width(72.dp), - colors = ChipDefaults.chipColors( - backgroundColor = Color(node.colors.second), - contentColor = Color(node.colors.first), - ), - ) { - Text( - text = node.user.shortName, - modifier = Modifier.fillMaxWidth(), - fontSize = MaterialTheme.typography.button.fontSize, - fontWeight = FontWeight.Normal, - textAlign = TextAlign.Center, - ) - } - } Column( modifier = Modifier.padding(top = 8.dp), ) {