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 af9d953d..d7668881 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
@@ -72,7 +72,7 @@ fun SettingsScreen(vm: ChatViewModel, onBack: () -> Unit, onExit: () -> Unit = {
var dirty by rememberSaveable { mutableStateOf(false) }
var tabIndex by rememberSaveable { mutableStateOf(0) }
- val tabs = listOf(R.string.settings, R.string.audio, R.string.storage, R.string.radio)
+ val tabs = listOf(R.string.settings, R.string.audio, R.string.storage, R.string.radio, R.string.dev)
val handleBack = {
if (dirty && NativeLib.isReady()) {
@@ -101,25 +101,52 @@ fun SettingsScreen(vm: ChatViewModel, onBack: () -> Unit, onExit: () -> Unit = {
}
}
when (tabIndex) {
- 0 -> GeneralSettingsTab(vm, dirty, onDirty = { dirty = it }, onExit)
+ 0 -> GeneralSettingsTab(onDirty = { dirty = it })
1 -> AudioSettingsTab(vm)
2 -> StorageSettingsTab()
3 -> RadioSettingsTab()
+ 4 -> DeveloperSettingsTab(vm, onDirty = { dirty = it }, onExit)
}
}
}
}
-/* ── General Settings Tab ── */
+/* Основные настройки профиля и приложения. */
+
+@Composable
+private fun GeneralSettingsTab(onDirty: (Boolean) -> Unit) {
+ val provider = ChatApplication.instance.configProvider
+ val scope = rememberCoroutineScope()
+ var nodeName by remember { mutableStateOf("") }
+
+ LaunchedEffect(Unit) {
+ nodeName = provider.getString("node.name") ?: provider.getDeviceName()
+ LogManager.addLog("INFO", "SETTINGS", "General settings opened")
+ }
+
+ LazyColumn(
+ modifier = Modifier.fillMaxSize(),
+ contentPadding = PaddingValues(16.dp),
+ verticalArrangement = Arrangement.spacedBy(12.dp)
+ ) {
+ item(key = "language") { LanguageSetting() }
+ item(key = "battery") { BatteryOptimizationSetting(source = "settings") }
+ item(key = "node-name") {
+ OutlinedTextField(nodeName, { v -> onDirty(true); nodeName = v; scope.launch { provider.setValue("node.name", v) } },
+ label = { Text(stringResource(R.string.node_name)) }, singleLine = true, modifier = Modifier.heightIn(min = 40.dp))
+ }
+ item(key = "profile-avatar") { ProfileAvatarControls() }
+ }
+}
+
+/* Настройки разработчика: сеть, ключи, standby, диагностика и управление сервисом. */
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-private fun GeneralSettingsTab(vm: ChatViewModel, dirty: Boolean, onDirty: (Boolean) -> Unit,
- onExit: () -> Unit) {
+private fun DeveloperSettingsTab(vm: ChatViewModel, onDirty: (Boolean) -> Unit, onExit: () -> Unit) {
val provider = ChatApplication.instance.configProvider
val scope = rememberCoroutineScope()
- var nodeName by remember { mutableStateOf("") }
var listenPort by remember { mutableStateOf("12345") }
var controlPort by remember { mutableStateOf("9999") }
var controlBindIp by remember { mutableStateOf("127.0.0.1") }
@@ -152,7 +179,6 @@ private fun GeneralSettingsTab(vm: ChatViewModel, dirty: Boolean, onDirty: (Bool
var startOnBootError by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
- nodeName = provider.getString("node.name") ?: provider.getDeviceName()
listenPort = provider.getInt("node.listen_port").toString()
controlPort = provider.getInt("control.port").toString()
controlBindIp = provider.getString("control.bind_ip") ?: "127.0.0.1"
@@ -206,7 +232,7 @@ private fun GeneralSettingsTab(vm: ChatViewModel, dirty: Boolean, onDirty: (Bool
val openedAt = remember { android.os.SystemClock.uptimeMillis() }
LaunchedEffect(Unit) {
withFrameNanos { }
- LogManager.addLog("INFO", "SETTINGS", "General settings displayed: elapsedMs=${android.os.SystemClock.uptimeMillis() - openedAt} " +
+ LogManager.addLog("INFO", "SETTINGS", "Dev settings displayed: elapsedMs=${android.os.SystemClock.uptimeMillis() - openedAt} " +
"visibleItems=${listState.layoutInfo.visibleItemsInfo.size} totalItems=${listState.layoutInfo.totalItemsCount}")
}
@@ -217,15 +243,8 @@ private fun GeneralSettingsTab(vm: ChatViewModel, dirty: Boolean, onDirty: (Bool
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
- item(key = "language") { LanguageSetting() }
- item(key = "battery") { BatteryOptimizationSetting(source = "settings") }
-
/* Node */
item(key = "node-title") { Text(stringResource(R.string.node), style = MaterialTheme.typography.titleMedium) }
- item(key = "node-name") {
- OutlinedTextField(nodeName, { v -> onDirty(true); nodeName = v; scope.launch { provider.setValue("node.name", v) } },
- label = { Text(stringResource(R.string.node_name)) }, singleLine = true, modifier = Modifier.heightIn(min = 40.dp))
- }
item(key = "listen-port") {
OutlinedTextField(listenPort, { v -> onDirty(true); listenPort = v; scope.launch { provider.setValue("node.listen_port", v) } },
label = { Text(stringResource(R.string.listen_port)) }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
@@ -256,8 +275,6 @@ private fun GeneralSettingsTab(vm: ChatViewModel, dirty: Boolean, onDirty: (Bool
}
}
- item(key = "profile-avatar") { ProfileAvatarControls() }
-
/* Keys */
item(key = "keys-title") { Text(stringResource(R.string.keys), style = MaterialTheme.typography.titleMedium) }
item(key = "public-key") { OutlinedTextField(pubKey, {}, label = { Text(stringResource(R.string.public_key)) }, readOnly = true, singleLine = true) }
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 bb3552d7..81d6f4be 100644
--- a/tools/chatgui-android/app/src/main/res/values/strings.xml
+++ b/tools/chatgui-android/app/src/main/res/values/strings.xml
@@ -4,6 +4,7 @@
"Could not request microphone access"
"Microphone access is denied. Allow it in app settings, then try the call or PTT again."
"Settings"
+ Dev
"Cancel"
"Invalid channel ID"
"Microphone allowed. Press PTT again"