feat: add `NodeMenu` options to messages

closes #682
pull/1457/head
andrekir 2024-12-10 16:21:19 -03:00
rodzic a19a28c4b3
commit a642e6a62e
2 zmienionych plików z 67 dodań i 19 usunięć

Wyświetl plik

@ -88,11 +88,14 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.R
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.database.entity.NodeEntity
import com.geeksville.mesh.database.entity.QuickChatAction
import com.geeksville.mesh.model.UIViewModel
import com.geeksville.mesh.model.getChannel
import com.geeksville.mesh.ui.message.components.MessageList
import com.geeksville.mesh.ui.components.NodeKeyStatusIcon
import com.geeksville.mesh.ui.components.NodeMenuAction
import com.geeksville.mesh.ui.message.components.MessageList
import com.geeksville.mesh.ui.navigateToNavGraph
import com.geeksville.mesh.ui.theme.AppTheme
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
@ -111,6 +114,19 @@ internal fun FragmentManager.navigateToMessages(contactKey: String, message: Str
class MessagesFragment : Fragment(), Logging {
private val model: UIViewModel by activityViewModels()
private fun navigateToMessages(node: NodeEntity) = node.user.let { user ->
val hasPKC = model.ourNodeInfo.value?.hasPKC == true && node.hasPKC // TODO use meta.hasPKC
val channel = if (hasPKC) DataPacket.PKC_CHANNEL_INDEX else node.channel
val contactKey = "$channel${user.id}"
info("calling MessagesFragment filter: $contactKey")
parentFragmentManager.navigateToMessages(contactKey)
}
private fun navigateToNodeDetails(nodeNum: Int) {
info("calling NodeDetails --> destNum: $nodeNum")
parentFragmentManager.navigateToNavGraph(nodeNum, "NodeDetails")
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -128,6 +144,8 @@ class MessagesFragment : Fragment(), Logging {
contactKey = contactKey,
message = message,
viewModel = model,
navigateToMessages = ::navigateToMessages,
navigateToNodeDetails = ::navigateToNodeDetails,
) { parentFragmentManager.popBackStack() }
}
}
@ -148,6 +166,8 @@ internal fun MessageScreen(
contactKey: String,
message: String,
viewModel: UIViewModel = hiltViewModel(),
navigateToMessages: (NodeEntity) -> Unit,
navigateToNodeDetails: (Int) -> Unit,
onNavigateBack: () -> Unit
) {
val coroutineScope = rememberCoroutineScope()
@ -255,8 +275,16 @@ internal fun MessageScreen(
onUnreadChanged = { viewModel.clearUnreadCount(contactKey, it) },
contentPadding = innerPadding,
onSendReaction = { emoji, id -> viewModel.sendReaction(emoji, id, contactKey) },
) {
// TODO onCLick()
) { action ->
when (action) {
is NodeMenuAction.Remove -> viewModel.removeNode(action.node.num)
is NodeMenuAction.Ignore -> viewModel.ignoreNode(action.node)
is NodeMenuAction.DirectMessage -> navigateToMessages(action.node)
is NodeMenuAction.RequestUserInfo -> viewModel.requestUserInfo(action.node.num)
is NodeMenuAction.RequestPosition -> viewModel.requestPosition(action.node.num)
is NodeMenuAction.TraceRoute -> viewModel.requestTraceroute(action.node.num)
is NodeMenuAction.MoreDetails -> navigateToNodeDetails(action.node.num)
}
}
}
}

Wyświetl plik

@ -17,8 +17,10 @@
package com.geeksville.mesh.ui.message.components
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
@ -32,17 +34,21 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback
import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.database.entity.Reaction
import com.geeksville.mesh.model.Message
import com.geeksville.mesh.ui.components.NodeMenu
import com.geeksville.mesh.ui.components.NodeMenuAction
import com.geeksville.mesh.ui.components.SimpleAlertDialog
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.debounce
@Suppress("LongMethod")
@Composable
internal fun MessageList(
messages: List<Message>,
@ -50,7 +56,7 @@ internal fun MessageList(
onUnreadChanged: (Long) -> Unit,
contentPadding: PaddingValues,
onSendReaction: (String, Int) -> Unit,
onClick: (Message) -> Unit = {}
onNodeMenuAction: (NodeMenuAction) -> Unit = {}
) {
val haptics = LocalHapticFeedback.current
val inSelectionMode by remember { derivedStateOf { selectedIds.value.isNotEmpty() } }
@ -90,21 +96,35 @@ internal fun MessageList(
val selected by remember { derivedStateOf { selectedIds.value.contains(msg.uuid) } }
ReactionRow(fromLocal, msg.emojis) { showReactionDialog = msg.emojis }
MessageItem(
node = msg.node,
messageText = msg.text,
messageTime = msg.time,
messageStatus = msg.status,
selected = selected,
onClick = { if (inSelectionMode) selectedIds.toggle(msg.uuid) },
onLongClick = {
selectedIds.toggle(msg.uuid)
haptics.performHapticFeedback(HapticFeedbackType.LongPress)
},
onChipClick = { onClick(msg) },
onStatusClick = { showStatusDialog = msg },
onSendReaction = { onSendReaction(it, msg.packetId) },
)
Box(Modifier.wrapContentSize(Alignment.TopStart)) {
var expandedNodeMenu by remember { mutableStateOf(false) }
MessageItem(
node = msg.node,
messageText = msg.text,
messageTime = msg.time,
messageStatus = msg.status,
selected = selected,
onClick = { if (inSelectionMode) selectedIds.toggle(msg.uuid) },
onLongClick = {
selectedIds.toggle(msg.uuid)
haptics.performHapticFeedback(HapticFeedbackType.LongPress)
},
onChipClick = {
if (msg.node.num != 0) {
expandedNodeMenu = true
}
},
onStatusClick = { showStatusDialog = msg },
onSendReaction = { onSendReaction(it, msg.packetId) },
)
NodeMenu(
node = msg.node,
showFullMenu = true,
onDismissRequest = { expandedNodeMenu = false },
expanded = expandedNodeMenu,
onAction = onNodeMenuAction
)
}
}
}
}