diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/SettingsScreen.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/SettingsScreen.kt index cb6f3e530..0453bc9d0 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/SettingsScreen.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/SettingsScreen.kt @@ -44,6 +44,7 @@ import com.utun.chat.data.RadioAudioEngine import com.utun.chat.data.RadioAutoSettings import com.utun.chat.data.ConfigProvider import com.utun.chat.data.UdpLogSettings +import com.utun.chat.data.MonitoringSettings import com.utun.chat.data.CallVideoBitrateRange import com.utun.chat.data.MicrophonePermission import com.utun.chat.data.LogManager @@ -320,6 +321,8 @@ private fun DeveloperSettingsTab(vm: ChatViewModel, onDirty: (Boolean) -> Unit, val scope = rememberCoroutineScope() var controlPort by remember { mutableStateOf("9999") } + var monitoringEnabled by remember { mutableStateOf(false) } + var monitoringLoaded by remember { mutableStateOf(false) } var controlBindIp by remember { mutableStateOf("127.0.0.1") } var ctrlBindLabel by remember { mutableStateOf("lo (127.0.0.1)") } var debugLevel by remember { mutableStateOf("info") } @@ -369,12 +372,21 @@ private fun DeveloperSettingsTab(vm: ChatViewModel, onDirty: (Boolean) -> Unit, } } + fun saveMonitoring() { + val settings = MonitoringSettings(monitoringEnabled, controlBindIp, controlPort.toIntOrNull() ?: 0) + if (settings.enabled && !settings.valid) return // Незавершённый ввод подсвечивается; последний верный endpoint сохранён. + onDirty(true) + val request = provider.saveMonitoringSettings(settings) + provider.changes.submit("monitoring") { request.await() } + } + LaunchedEffect(Unit) { try { - controlPort = provider.getInt("control.port").toString() - controlBindIp = provider.getString("control.bind_ip") ?: "127.0.0.1" + val monitoring = provider.getMonitoringSettings() + monitoringEnabled = monitoring.enabled; controlPort = monitoring.port.toString(); controlBindIp = monitoring.ip + monitoringLoaded = true val allIface = listOf("lo" to "127.0.0.1") + withContext(Dispatchers.IO) { provider.getAvailableInterfaces() } - ctrlBindLabel = allIface.firstOrNull { it.second == controlBindIp }?.let { "${it.first} (${it.second})" } ?: "lo (127.0.0.1)" + ctrlBindLabel = allIface.firstOrNull { it.second == controlBindIp }?.let { "${it.first} (${it.second})" } ?: controlBindIp debugLevel = provider.getString("debug.console_level") ?: "info" logFile = provider.getString("debug.log_file") ?: "utun.log" val udpLog = try { provider.getUdpLogSettings() } @@ -454,7 +466,7 @@ private fun DeveloperSettingsTab(vm: ChatViewModel, onDirty: (Boolean) -> Unit, } var ctrlExpanded by remember { mutableStateOf(false) } - val ctrlIfaces = listOf("lo" to "127.0.0.1") + availableIfaces + val ctrlIfaces = (listOf("lo" to "127.0.0.1") + availableIfaces.filter { !it.second.contains(':') }).distinct() val listState = rememberLazyListState() val openedAt = remember { android.os.SystemClock.uptimeMillis() } LaunchedEffect(Unit) { @@ -476,8 +488,24 @@ private fun DeveloperSettingsTab(vm: ChatViewModel, onDirty: (Boolean) -> Unit, color = MaterialTheme.colorScheme.onSurfaceVariant) } - /* Control interface */ - item(key = "control") { + item(key = "monitoring-enabled") { + Row(Modifier.fillMaxWidth().toggleable(value = monitoringEnabled, enabled = monitoringLoaded, + role = Role.Checkbox, onValueChange = { enabled -> + monitoringEnabled = enabled + if (!enabled) { + controlBindIp = "127.0.0.1"; controlPort = "9999"; ctrlBindLabel = "lo (127.0.0.1)"; ctrlExpanded = false + } + saveMonitoring() + }), verticalAlignment = Alignment.CenterVertically) { + Checkbox(checked = monitoringEnabled, onCheckedChange = null, enabled = monitoringLoaded) + Column { + Text(stringResource(R.string.monitoring_enabled)) + Text(stringResource(R.string.monitoring_description), style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant) + } + } + } + if (monitoringEnabled) item(key = "control") { Row(verticalAlignment = Alignment.CenterVertically) { ExposedDropdownMenuBox(expanded = ctrlExpanded, onExpandedChange = { ctrlExpanded = it }, modifier = Modifier.weight(1f)) { OutlinedTextField(ctrlBindLabel, {}, readOnly = true, singleLine = true, @@ -487,15 +515,15 @@ private fun DeveloperSettingsTab(vm: ChatViewModel, onDirty: (Boolean) -> Unit, ExposedDropdownMenu(ctrlExpanded, onDismissRequest = { ctrlExpanded = false }) { ctrlIfaces.forEach { (n, ip) -> DropdownMenuItem(text = { Text("$n ($ip)") }, onClick = { - controlBindIp = ip; ctrlBindLabel = "$n ($ip)"; onDirty(true) - provider.changes.submit("control address") { provider.setValue("control.bind_ip", ip) }; ctrlExpanded = false + controlBindIp = ip; ctrlBindLabel = "$n ($ip)"; saveMonitoring(); ctrlExpanded = false }) } } } Spacer(Modifier.width(8.dp)) - OutlinedTextField(controlPort, { v -> onDirty(true); controlPort = v; provider.changes.submit("control port") { provider.setValue("control.port", v) } }, + OutlinedTextField(controlPort, { v -> controlPort = v; saveMonitoring() }, label = { Text(stringResource(R.string.port)) }, modifier = Modifier.width(80.dp).heightIn(min = 40.dp), + isError = (controlPort.toIntOrNull() ?: 0) !in 1..65535, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), singleLine = true) } } diff --git a/tools/chatgui-android/app/src/main/res/values-ru/strings.xml b/tools/chatgui-android/app/src/main/res/values-ru/strings.xml index d6ff25f6d..ca0dc614a 100644 --- a/tools/chatgui-android/app/src/main/res/values-ru/strings.xml +++ b/tools/chatgui-android/app/src/main/res/values-ru/strings.xml @@ -277,6 +277,8 @@ Не меняйте настройки, если не уверены в своих действиях "Имя узла" IP мониторинга + Включить мониторинг + Доступ по TCP на выбранных IP и порту. Изменения применяются при выходе из настроек. Выключение удаляет адрес и порт. "Порт" "Ключи" "Публичный ключ" diff --git a/tools/chatgui-android/app/src/main/res/values/strings.xml b/tools/chatgui-android/app/src/main/res/values/strings.xml index e76d9dcd7..2547dfd0a 100644 --- a/tools/chatgui-android/app/src/main/res/values/strings.xml +++ b/tools/chatgui-android/app/src/main/res/values/strings.xml @@ -278,6 +278,8 @@ Do not change these settings unless you know what you are doing "Node name" Monitoring IP + Enable monitoring + TCP access on the selected IP and port. Changes apply when leaving settings. Disabling clears the address and port. "Port" "Keys" "Public key"