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"