mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Refactor: Improve network device selection UI and logic (#2268)
This commit is contained in:
parent
d709b2d2d0
commit
53cd893df1
2 changed files with 65 additions and 35 deletions
|
|
@ -359,6 +359,11 @@ fun ConnectionsScreen(
|
|||
}
|
||||
|
||||
var selectedDeviceType by remember { mutableStateOf(DeviceType.BLE) }
|
||||
LaunchedEffect(selectedDevice) {
|
||||
// Determine based on the selected device - if disconnected, keep the last selected type
|
||||
selectedDeviceType =
|
||||
selectedDevice.let { DeviceType.fromAddress(it) } ?: selectedDeviceType
|
||||
}
|
||||
SingleChoiceSegmentedButtonRow(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
|
|
@ -709,7 +714,25 @@ private tailrec fun Context.findActivity(): Activity = when (this) {
|
|||
private enum class DeviceType {
|
||||
BLE,
|
||||
TCP,
|
||||
USB,
|
||||
USB;
|
||||
|
||||
companion object {
|
||||
fun fromAddress(address: String): DeviceType? {
|
||||
val prefix = address[0]
|
||||
val isBLE: Boolean = prefix == 'x'
|
||||
val isUSB: Boolean = prefix == 's'
|
||||
val isTCP: Boolean = prefix == 't'
|
||||
val isMock: Boolean = prefix == 'm'
|
||||
val isDisconnect: Boolean = prefix == 'n'
|
||||
return when {
|
||||
isBLE -> BLE
|
||||
isUSB -> USB
|
||||
isTCP -> TCP
|
||||
isMock -> USB // Treat mock as USB for UI purposes
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val SCAN_PERIOD: Long = 10000 // 10 seconds
|
||||
|
|
|
|||
|
|
@ -17,28 +17,28 @@
|
|||
|
||||
package com.geeksville.mesh.ui.connections.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
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.layout.size
|
||||
import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.text.input.TextFieldLineLimits
|
||||
import androidx.compose.foundation.text.input.rememberTextFieldState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.WifiFind
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -47,6 +47,7 @@ import com.geeksville.mesh.model.BTScanModel
|
|||
import com.geeksville.mesh.repository.network.NetworkRepository
|
||||
import com.geeksville.mesh.ui.connections.isIPAddress
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Suppress("MagicNumber", "LongMethod")
|
||||
@Composable
|
||||
fun NetworkDevices(
|
||||
|
|
@ -86,56 +87,62 @@ fun NetworkDevices(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.selectable(
|
||||
selected = ("t$manualIpAddress:$manualIpPort" == selectedDevice),
|
||||
onClick = {
|
||||
if (manualIpAddress.text.toString().isIPAddress()) {
|
||||
scanModel.onSelected(
|
||||
BTScanModel.DeviceListEntry(
|
||||
"",
|
||||
"t$manualIpAddress:$manualIpPort",
|
||||
true
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
enabled = manualIpAddress.text.toString().isIPAddress(),
|
||||
role = Role.Companion.RadioButton
|
||||
)
|
||||
.padding(8.dp),
|
||||
verticalAlignment = Alignment.Companion.CenterVertically
|
||||
verticalAlignment = Alignment.Companion.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally)
|
||||
) {
|
||||
RadioButton(
|
||||
selected = ("t$manualIpAddress:$manualIpPort" == selectedDevice),
|
||||
onClick = null,
|
||||
enabled = manualIpAddress.toString().isIPAddress()
|
||||
)
|
||||
OutlinedTextField(
|
||||
state = manualIpAddress,
|
||||
lineLimits = TextFieldLineLimits.SingleLine,
|
||||
label = { Text(stringResource(R.string.ip_address)) },
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Companion.Number,
|
||||
imeAction = ImeAction.Done
|
||||
keyboardType = KeyboardType.Companion.Decimal,
|
||||
imeAction = ImeAction.Next
|
||||
),
|
||||
modifier = Modifier
|
||||
.weight(0.7f)
|
||||
.padding(start = 16.dp)
|
||||
modifier = Modifier.weight(.7f, fill = false) // Fill 70% of the space
|
||||
)
|
||||
OutlinedTextField(
|
||||
state = manualIpPort,
|
||||
placeholder = { Text(NetworkRepository.SERVICE_PORT.toString()) },
|
||||
lineLimits = TextFieldLineLimits.SingleLine,
|
||||
label = { Text(stringResource(R.string.ip_port)) },
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Companion.Number,
|
||||
keyboardType = KeyboardType.Companion.Decimal,
|
||||
imeAction = ImeAction.Done
|
||||
),
|
||||
modifier = Modifier
|
||||
.weight(weight = 0.3f)
|
||||
.padding(start = 8.dp)
|
||||
modifier = Modifier.weight(.3f, fill = false) // Fill remaining space
|
||||
)
|
||||
IconButton(
|
||||
onClick = {
|
||||
if (manualIpAddress.text.toString().isIPAddress()) {
|
||||
val fullAddress =
|
||||
"t" + if (
|
||||
manualIpPort.text.isNotEmpty() &&
|
||||
manualIpPort.text.toString().toInt() != NetworkRepository.SERVICE_PORT
|
||||
) {
|
||||
"${manualIpAddress.text}:${manualIpPort.text}"
|
||||
} else {
|
||||
"${manualIpAddress.text}"
|
||||
}
|
||||
scanModel.onSelected(
|
||||
BTScanModel.DeviceListEntry(
|
||||
"${manualIpAddress.text}",
|
||||
fullAddress,
|
||||
true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.WifiFind,
|
||||
contentDescription = stringResource(R.string.add),
|
||||
modifier = Modifier.size(32.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue