feat: material3 (#1862)

This commit is contained in:
James Rich 2025-05-17 11:39:53 -05:00 committed by GitHub
parent 8db9665ff3
commit 4cba13ea14
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
99 changed files with 2134 additions and 1606 deletions

View file

@ -18,7 +18,6 @@
package com.geeksville.mesh.ui.message
import android.content.ClipData
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
@ -28,25 +27,24 @@ import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.AlertDialog
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Scaffold
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.ContentCopy
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.SelectAll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.derivedStateOf
@ -59,11 +57,9 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusEvent
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.ClipEntry
import androidx.compose.ui.platform.LocalClipboard
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
@ -183,7 +179,6 @@ internal fun MessageScreen(
val isConnected = connState.isConnected()
Column(
modifier = Modifier
.background(MaterialTheme.colors.background)
.padding(start = 8.dp, end = 8.dp, bottom = 4.dp),
) {
QuickChatRow(isConnected, quickChat) { action ->
@ -248,7 +243,6 @@ private fun DeleteMessageDialog(
AlertDialog(
onDismissRequest = onDismiss,
shape = RoundedCornerShape(16.dp),
backgroundColor = MaterialTheme.colors.background,
text = {
Text(
text = deleteMessagesString,
@ -276,6 +270,7 @@ sealed class MessageMenuAction {
data object SelectAll : MessageMenuAction()
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ActionModeTopBar(
selectedList: Set<Long>,
@ -310,9 +305,9 @@ private fun ActionModeTopBar(
)
}
},
backgroundColor = MaterialTheme.colors.primary,
)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun MessageTopBar(
title: String,
@ -358,9 +353,6 @@ private fun QuickChatRow(
onClick = { onClick(action) },
modifier = Modifier.padding(horizontal = 4.dp),
enabled = enabled,
colors = ButtonDefaults.buttonColors(
backgroundColor = colorResource(id = R.color.colorMyMsg),
)
) {
Text(
text = action.name,
@ -396,10 +388,6 @@ private fun TextInput(
),
maxLines = 3,
shape = RoundedCornerShape(24.dp),
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
),
trailingIcon = {
IconButton(
onClick = {
@ -416,7 +404,6 @@ private fun TextInput(
Icon(
imageVector = Icons.AutoMirrored.Default.Send,
contentDescription = stringResource(id = R.string.send_text),
tint = MaterialTheme.colors.primary
)
}
}
@ -424,7 +411,7 @@ private fun TextInput(
if (isFocused) {
Text(
text = "${message.value.text.toByteArray().size}/$maxSize",
style = MaterialTheme.typography.caption,
style = MaterialTheme.typography.bodySmall,
modifier = Modifier
.align(Alignment.End)
.padding(top = 4.dp, end = 72.dp)

View file

@ -27,13 +27,6 @@ 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.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.Icon
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.twotone.Cloud
import androidx.compose.material.icons.twotone.CloudDone
@ -41,6 +34,11 @@ import androidx.compose.material.icons.twotone.CloudOff
import androidx.compose.material.icons.twotone.CloudUpload
import androidx.compose.material.icons.twotone.HowToReg
import androidx.compose.material.icons.twotone.Warning
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -50,7 +48,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.MessageStatus
import com.geeksville.mesh.R
@ -76,9 +73,9 @@ internal fun MessageItem(
onStatusClick: () -> Unit = {},
onSendReaction: (String) -> Unit = {},
) = Row(
modifier = Modifier
modifier = modifier
.fillMaxWidth()
.background(color = if (selected) Color.Gray else MaterialTheme.colors.background),
.background(color = if (selected) Color.Gray else MaterialTheme.colorScheme.background),
verticalAlignment = Alignment.CenterVertically,
) {
val fromLocal = node.user.id == DataPacket.ID_LOCAL
@ -102,70 +99,61 @@ internal fun MessageItem(
Card(
modifier = Modifier
.weight(1f)
.then(messageModifier),
elevation = 4.dp,
shape = RoundedCornerShape(topStart, topEnd, 12.dp, 12.dp),
) {
Surface(
modifier = modifier.combinedClickable(
.combinedClickable(
onClick = onClick,
onLongClick = onLongClick,
),
color = colorResource(id = messageColor),
)
.then(messageModifier),
colors = CardDefaults.cardColors(
containerColor = colorResource(messageColor)
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically,
Column(
modifier = Modifier.padding(top = 8.dp),
) {
Column(
modifier = Modifier.padding(top = 8.dp),
) {
if (!fromLocal) {
Text(
text = with(node.user) { "$longName ($id)" },
modifier = Modifier.padding(bottom = 4.dp),
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = MaterialTheme.typography.button.copy(
color = MaterialTheme.colors.onSurface,
letterSpacing = 0.1.sp,
)
)
}
AutoLinkText(
text = messageText.orEmpty(),
style = LocalTextStyle.current.copy(
color = MaterialTheme.colors.onBackground,
),
if (!fromLocal) {
Text(
text = with(node.user) { "$longName ($id)" },
modifier = Modifier.padding(bottom = 4.dp),
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = MaterialTheme.typography.labelLarge
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = messageTime,
color = MaterialTheme.colors.onSurface,
fontSize = MaterialTheme.typography.caption.fontSize,
}
AutoLinkText(
text = messageText.orEmpty(),
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = messageTime,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
)
AnimatedVisibility(visible = fromLocal) {
Icon(
imageVector = when (messageStatus) {
MessageStatus.RECEIVED -> Icons.TwoTone.HowToReg
MessageStatus.QUEUED -> Icons.TwoTone.CloudUpload
MessageStatus.DELIVERED -> Icons.TwoTone.CloudDone
MessageStatus.ENROUTE -> Icons.TwoTone.Cloud
MessageStatus.ERROR -> Icons.TwoTone.CloudOff
else -> Icons.TwoTone.Warning
},
contentDescription = stringResource(R.string.message_delivery_status),
modifier = Modifier
.padding(start = 8.dp)
.clickable { onStatusClick() },
)
AnimatedVisibility(visible = fromLocal) {
Icon(
imageVector = when (messageStatus) {
MessageStatus.RECEIVED -> Icons.TwoTone.HowToReg
MessageStatus.QUEUED -> Icons.TwoTone.CloudUpload
MessageStatus.DELIVERED -> Icons.TwoTone.CloudDone
MessageStatus.ENROUTE -> Icons.TwoTone.Cloud
MessageStatus.ERROR -> Icons.TwoTone.CloudOff
else -> Icons.TwoTone.Warning
},
contentDescription = stringResource(R.string.message_delivery_status),
modifier = Modifier
.padding(start = 8.dp)
.clickable { onStatusClick() },
)
}
}
}
}

View file

@ -33,17 +33,16 @@ import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Badge
import androidx.compose.material.BadgedBox
import androidx.compose.material.ContentAlpha
import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.EmojiEmotions
import androidx.compose.material3.Badge
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.Divider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -83,7 +82,6 @@ fun ReactionButton(
imageVector = Icons.Default.EmojiEmotions,
contentDescription = "emoji",
modifier = modifier.size(16.dp),
tint = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium),
)
}
}
@ -99,8 +97,8 @@ private fun ReactionItem(
badge = {
if (emojiCount > 1) {
Badge(
backgroundColor = MaterialTheme.colors.onBackground,
contentColor = MaterialTheme.colors.background,
containerColor = MaterialTheme.colorScheme.onBackground,
contentColor = MaterialTheme.colorScheme.background,
) {
Text(
fontWeight = FontWeight.Bold,
@ -113,9 +111,8 @@ private fun ReactionItem(
Surface(
modifier = Modifier
.clickable { onClick() },
color = MaterialTheme.colors.surface,
color = MaterialTheme.colorScheme.surface,
shape = RoundedCornerShape(32.dp),
elevation = 4.dp,
) {
Text(
text = emoji,
@ -192,7 +189,7 @@ fun ReactionDialog(
.clickable {
selectedEmoji = if (selectedEmoji == emoji) null else emoji
},
style = MaterialTheme.typography.body2
style = MaterialTheme.typography.bodyMedium
)
}
}
@ -211,11 +208,11 @@ fun ReactionDialog(
) {
Text(
text = reaction.user.longName,
style = MaterialTheme.typography.subtitle1
style = MaterialTheme.typography.titleMedium
)
Text(
text = reaction.emoji,
style = MaterialTheme.typography.h6
style = MaterialTheme.typography.titleLarge
)
}
}
@ -227,7 +224,7 @@ fun ReactionDialog(
fun ReactionItemPreview() {
AppTheme {
Column(
modifier = Modifier.background(MaterialTheme.colors.background)
modifier = Modifier.background(MaterialTheme.colorScheme.background)
) {
ReactionItem(emoji = "\uD83D\uDE42")
ReactionItem(emoji = "\uD83D\uDE42", emojiCount = 2)