allow deleting of recent nodes, use long name (#2456)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
Co-authored-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
DaneEvans 2025-07-21 00:48:34 +10:00 committed by GitHub
parent 5e5fc19fc0
commit be30757720
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 119 additions and 30 deletions

View file

@ -278,6 +278,8 @@ fun ConnectionsScreen(
val isConnected by uiViewModel.isConnected.collectAsState(false)
val ourNode by uiViewModel.ourNodeInfo.collectAsState()
// Set the connected node long name for BTScanModel
scanModel.connectedNodeLongName = ourNode?.user?.longName
if (isConnected) {
ourNode?.let { node ->
Row(

View file

@ -63,12 +63,12 @@ fun BLEDevices(
)
btDevices.forEach { device ->
DeviceListItem(
connectionState,
device,
device.fullAddress == selectedDevice
) {
scanModel.onSelected(device)
}
connectionState = connectionState,
device = device,
selected = device.fullAddress == selectedDevice,
onSelect = { scanModel.onSelected(device) },
modifier = Modifier
)
}
if (isScanning) {
Column(

View file

@ -48,6 +48,7 @@ fun DeviceListItem(
device: BTScanModel.DeviceListEntry,
selected: Boolean,
onSelect: () -> Unit,
modifier: Modifier = Modifier,
) {
val icon = if (device.isBLE) {
Icons.Default.Bluetooth
@ -102,13 +103,18 @@ fun DeviceListItem(
}
}
val useSelectable = modifier == Modifier
ListItem(
modifier = Modifier
.fillMaxWidth()
.selectable(
selected = selected,
onClick = onSelect,
),
modifier = if (useSelectable) {
modifier
.fillMaxWidth()
.selectable(
selected = selected,
onClick = onSelect,
)
} else {
modifier.fillMaxWidth()
},
headlineContent = { Text(device.name) },
leadingContent = {
Icon(

View file

@ -47,6 +47,13 @@ import com.geeksville.mesh.model.BTScanModel
import com.geeksville.mesh.repository.network.NetworkRepository
import com.geeksville.mesh.service.MeshService
import com.geeksville.mesh.ui.connections.isIPAddress
import androidx.compose.foundation.combinedClickable
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.remember
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Suppress("MagicNumber", "LongMethod")
@ -59,15 +66,50 @@ fun NetworkDevices(
) {
val manualIpAddress = rememberTextFieldState("")
val manualIpPort = rememberTextFieldState(NetworkRepository.Companion.SERVICE_PORT.toString())
var showDeleteDialog by remember { mutableStateOf(false) }
var deviceToDelete by remember { mutableStateOf<BTScanModel.DeviceListEntry?>(null) }
Text(
text = stringResource(R.string.network),
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(vertical = 8.dp)
)
networkDevices.forEach { device ->
DeviceListItem(connectionState, device, device.fullAddress == selectedDevice) {
scanModel.onSelected(device)
val isRecent = device.isTCP && device.fullAddress.startsWith("t")
val modifier = if (isRecent) {
Modifier.combinedClickable(
onClick = { scanModel.onSelected(device) },
onLongClick = {
deviceToDelete = device
showDeleteDialog = true
}
)
} else {
Modifier
}
DeviceListItem(
connectionState, device, device.fullAddress == selectedDevice, onSelect = { scanModel.onSelected(device) },
modifier = modifier
)
}
if (showDeleteDialog && deviceToDelete != null) {
AlertDialog(
onDismissRequest = { showDeleteDialog = false },
title = { Text(stringResource(R.string.delete)) },
text = { Text(stringResource(R.string.confirm_delete_node)) },
confirmButton = {
Button(onClick = {
scanModel.removeRecentAddress(deviceToDelete!!.fullAddress)
showDeleteDialog = false
}) {
Text(stringResource(R.string.delete))
}
},
dismissButton = {
Button(onClick = { showDeleteDialog = false }) {
Text(stringResource(R.string.cancel))
}
}
)
}
if (networkDevices.filterNot { it.isDisconnect }.isEmpty()) {
Column(

View file

@ -48,9 +48,13 @@ fun UsbDevices(
modifier = Modifier.padding(vertical = 8.dp)
)
usbDevices.forEach { device ->
DeviceListItem(connectionState, device, device.fullAddress == selectedDevice) {
scanModel.onSelected(device)
}
DeviceListItem(
connectionState = connectionState,
device = device,
selected = device.fullAddress == selectedDevice,
onSelect = { scanModel.onSelected(device) },
modifier = Modifier
)
}
if (usbDevices.filterNot { it.isDisconnect || it.isMock }.isEmpty()) {
Column(