mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-05-12 08:42:01 -04:00
feat(messaging): Move message input to Scaffold bottomBar (#4530)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
@@ -33,7 +33,6 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.recalculateWindowInsets
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.foundation.layout.width
|
||||
@@ -464,7 +463,7 @@ fun MainScreen(uIViewModel: UIViewModel = hiltViewModel(), scanModel: BTScanMode
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = NodesRoutes.NodesGraph,
|
||||
modifier = Modifier.fillMaxSize().recalculateWindowInsets().safeDrawingPadding().imePadding(),
|
||||
modifier = Modifier.fillMaxSize().recalculateWindowInsets().safeDrawingPadding(),
|
||||
) {
|
||||
contactsGraph(navController, uIViewModel.scrollToTopEventFlow)
|
||||
nodesGraph(navController, uIViewModel.scrollToTopEventFlow)
|
||||
|
||||
@@ -303,6 +303,17 @@ fun MessageScreen(
|
||||
|
||||
sharedContact?.let { contact -> SharedContactDialog(contact = contact, onDismiss = { sharedContact = null }) }
|
||||
|
||||
val originalMessage by
|
||||
remember(replyingToPacketId, pagedMessages.itemCount) {
|
||||
derivedStateOf {
|
||||
replyingToPacketId?.let { id ->
|
||||
(0 until pagedMessages.itemCount).firstNotNullOfOrNull { index ->
|
||||
pagedMessages[index]?.takeIf { it.packetId == id }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
topBar = {
|
||||
@@ -357,82 +368,74 @@ fun MessageScreen(
|
||||
)
|
||||
}
|
||||
},
|
||||
) { paddingValues ->
|
||||
Column(Modifier.fillMaxSize().padding(paddingValues).focusable()) {
|
||||
Box(modifier = Modifier.weight(1f)) {
|
||||
MessageListPaged(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
listState = listState,
|
||||
state =
|
||||
MessageListPagedState(
|
||||
nodes = nodes,
|
||||
ourNode = ourNode,
|
||||
messages = pagedMessages,
|
||||
selectedIds = selectedMessageIds,
|
||||
contactKey = contactKey,
|
||||
firstUnreadMessageUuid = firstUnreadMessageUuid,
|
||||
hasUnreadMessages = hasUnreadMessages,
|
||||
filteredCount = filteredCount,
|
||||
showFiltered = showFiltered,
|
||||
filteringDisabled = filteringDisabled,
|
||||
),
|
||||
handlers =
|
||||
MessageListHandlers(
|
||||
onUnreadChanged = { messageUuid, timestamp ->
|
||||
onEvent(MessageScreenEvent.ClearUnreadCount(messageUuid, timestamp))
|
||||
bottomBar = {
|
||||
Column {
|
||||
AnimatedVisibility(visible = showQuickChat) {
|
||||
QuickChatRow(
|
||||
enabled = connectionState.isConnected(),
|
||||
actions = quickChatActions,
|
||||
onClick = { action ->
|
||||
handleQuickChatAction(
|
||||
action = action,
|
||||
messageInputState = messageInputState,
|
||||
onSendMessage = { text -> onEvent(MessageScreenEvent.SendMessage(text)) },
|
||||
)
|
||||
},
|
||||
onSendReaction = { emoji, id -> onEvent(MessageScreenEvent.SendReaction(emoji, id)) },
|
||||
onClickChip = { onEvent(MessageScreenEvent.NodeDetails(it)) },
|
||||
onDeleteMessages = { viewModel.deleteMessages(it) },
|
||||
onSendMessage = { text, key -> viewModel.sendMessage(text, key) },
|
||||
onReply = { message -> replyingToPacketId = message?.packetId },
|
||||
),
|
||||
quickEmojis = viewModel.frequentEmojis,
|
||||
)
|
||||
// Show FAB if we can scroll towards the newest messages (index 0).
|
||||
if (listState.canScrollBackward) {
|
||||
ScrollToBottomFab(coroutineScope, listState)
|
||||
)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(visible = showQuickChat) {
|
||||
QuickChatRow(
|
||||
enabled = connectionState.isConnected(),
|
||||
actions = quickChatActions,
|
||||
onClick = { action ->
|
||||
handleQuickChatAction(
|
||||
action = action,
|
||||
messageInputState = messageInputState,
|
||||
onSendMessage = { text -> onEvent(MessageScreenEvent.SendMessage(text)) },
|
||||
)
|
||||
ReplySnippet(
|
||||
originalMessage = originalMessage,
|
||||
onClearReply = { replyingToPacketId = null },
|
||||
ourNode = ourNode,
|
||||
)
|
||||
MessageInput(
|
||||
isEnabled = connectionState.isConnected(),
|
||||
isHomoglyphEncodingEnabled = homoglyphEncodingEnabled,
|
||||
textFieldState = messageInputState,
|
||||
onSendMessage = {
|
||||
val messageText = messageInputState.text.toString().trim()
|
||||
if (messageText.isNotEmpty()) {
|
||||
onEvent(MessageScreenEvent.SendMessage(messageText, replyingToPacketId))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
val originalMessage by
|
||||
remember(replyingToPacketId, pagedMessages.itemCount) {
|
||||
derivedStateOf {
|
||||
replyingToPacketId?.let { id ->
|
||||
(0 until pagedMessages.itemCount).firstNotNullOfOrNull { index ->
|
||||
pagedMessages[index]?.takeIf { it.packetId == id }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ReplySnippet(
|
||||
originalMessage = originalMessage,
|
||||
onClearReply = { replyingToPacketId = null },
|
||||
ourNode = ourNode,
|
||||
)
|
||||
MessageInput(
|
||||
isEnabled = connectionState.isConnected(),
|
||||
isHomoglyphEncodingEnabled = homoglyphEncodingEnabled,
|
||||
textFieldState = messageInputState,
|
||||
onSendMessage = {
|
||||
val messageText = messageInputState.text.toString().trim()
|
||||
if (messageText.isNotEmpty()) {
|
||||
onEvent(MessageScreenEvent.SendMessage(messageText, replyingToPacketId))
|
||||
}
|
||||
},
|
||||
},
|
||||
) { paddingValues ->
|
||||
Box(Modifier.fillMaxSize().padding(paddingValues).focusable()) {
|
||||
MessageListPaged(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
listState = listState,
|
||||
state =
|
||||
MessageListPagedState(
|
||||
nodes = nodes,
|
||||
ourNode = ourNode,
|
||||
messages = pagedMessages,
|
||||
selectedIds = selectedMessageIds,
|
||||
contactKey = contactKey,
|
||||
firstUnreadMessageUuid = firstUnreadMessageUuid,
|
||||
hasUnreadMessages = hasUnreadMessages,
|
||||
filteredCount = filteredCount,
|
||||
showFiltered = showFiltered,
|
||||
filteringDisabled = filteringDisabled,
|
||||
),
|
||||
handlers =
|
||||
MessageListHandlers(
|
||||
onUnreadChanged = { messageUuid, timestamp ->
|
||||
onEvent(MessageScreenEvent.ClearUnreadCount(messageUuid, timestamp))
|
||||
},
|
||||
onSendReaction = { emoji, id -> onEvent(MessageScreenEvent.SendReaction(emoji, id)) },
|
||||
onClickChip = { onEvent(MessageScreenEvent.NodeDetails(it)) },
|
||||
onDeleteMessages = { viewModel.deleteMessages(it) },
|
||||
onSendMessage = { text, key -> viewModel.sendMessage(text, key) },
|
||||
onReply = { message -> replyingToPacketId = message?.packetId },
|
||||
),
|
||||
quickEmojis = viewModel.frequentEmojis,
|
||||
)
|
||||
// Show FAB if we can scroll towards the newest messages (index 0).
|
||||
if (listState.canScrollBackward) {
|
||||
ScrollToBottomFab(coroutineScope, listState)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user