mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: material3 (#1862)
This commit is contained in:
parent
8db9665ff3
commit
4cba13ea14
99 changed files with 2134 additions and 1606 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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() },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue