From 9ab9d01907a1c0985e38d4e07db3680e31113516 Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 26 Oct 2026 10:09:59 +0100 Subject: [PATCH] Fix Android config storage limits for the strict parser --- tools/chatgui-android/AGENTS.md | 4 +- .../java/com/utun/chat/data/ConfigProvider.kt | 7 +-- .../utun/chat/ui/screens/SettingsScreen.kt | 18 ++++++- .../tests/test_config_provider.kt | 54 +++++++++++++++++++ 4 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 tools/chatgui-android/tests/test_config_provider.kt diff --git a/tools/chatgui-android/AGENTS.md b/tools/chatgui-android/AGENTS.md index d80b62de..2b64e91e 100644 --- a/tools/chatgui-android/AGENTS.md +++ b/tools/chatgui-android/AGENTS.md @@ -225,8 +225,8 @@ enabled=no [chat] storage_autoload=1 -storage_autoload_maxsize_mb=10 -storage_maxsize_gb=1 +storage_unit_size=10M +storage_total_size=1G opus_codec_preset=1 compressor_enabled=0 compressor_max_gain_db=25 diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt index 6e9095e0..7a3aa0f6 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt @@ -687,7 +687,8 @@ class ConfigProvider(private val context: Context) { fun saveServersToConfig(servers: List, commented: List = emptyList()) { val text = buildConfigFromServers(servers, commented) File(configFilePath()).writeText(text) - LogManager.addLog("INFO", "CFG", "saveServersToConfig: ${servers.size} active, ${commented.size} commented" + + LogManager.addLog("INFO", "CFG", "saveServersToConfig: ${servers.size} active, ${commented.size} commented, " + + "storage_unit_size=${getInt("chat.storage_autoload_maxsize_mb")}M storage_total_size=${getInt("chat.storage_maxsize_gb")}G; " + servers.joinToString(", ") { "${it.ifName}=${it.protocol}:${it.port}" }) } @@ -738,8 +739,8 @@ class ConfigProvider(private val context: Context) { val chatCompRiseRate = getInt("chat.compressor_rise_rate") val chatDlMaxPeers = getInt("chat.media_download_max_peers") appendLine("storage_autoload=$chatAutoload") - appendLine("storage_autoload_maxsize_mb=$chatAutoloadMaxMb") - appendLine("storage_maxsize_gb=$chatMaxGb") + appendLine("storage_unit_size=${chatAutoloadMaxMb}M") + appendLine("storage_total_size=${chatMaxGb}G") appendLine("opus_codec_preset=$chatOpusPreset") val radioAuto = getRadioAutoSettings() appendLine("radio_auto_enabled=${if (radioAuto.enabled) 1 else 0}") 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 ecda790c..43d46b7d 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 @@ -1284,13 +1284,27 @@ private fun StorageSettingsTab() { HorizontalDivider(Modifier.padding(vertical = 4.dp)) OutlinedTextField(autoloadMaxSizeMb, - { v -> autoloadMaxSizeMb = v; val nb = v.toIntOrNull(); if (nb != null && nb in 1..500) { scope.launch { provider.setValue("chat.storage_autoload_maxsize_mb", v) }; NativeLib.setChatSetting("storage_autoload_maxsize_mb", v) } }, + { v -> + autoloadMaxSizeMb = v + val size = v.toIntOrNull() + if (size != null && size in 1..500) scope.launch { + provider.setValue("chat.storage_autoload_maxsize_mb", v) + LogManager.addLog("INFO", "CFG", "Storage unit limit saved: ${v}M; applies on next core start") + } + }, label = { Text(stringResource(R.string.autoload_max_size)) }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), singleLine = true, modifier = Modifier.padding(top = 4.dp)) OutlinedTextField(maxStorageGb, - { v -> maxStorageGb = v; val nb = v.toIntOrNull(); if (nb != null && nb in 1..100) { scope.launch { provider.setValue("chat.storage_maxsize_gb", v) }; NativeLib.setChatSetting("storage_maxsize_gb", v) } }, + { v -> + maxStorageGb = v + val size = v.toIntOrNull() + if (size != null && size in 1..100) scope.launch { + provider.setValue("chat.storage_maxsize_gb", v) + LogManager.addLog("INFO", "CFG", "Storage total limit saved: ${v}G; applies on next core start") + } + }, label = { Text(stringResource(R.string.max_storage_size)) }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), singleLine = true) diff --git a/tools/chatgui-android/tests/test_config_provider.kt b/tools/chatgui-android/tests/test_config_provider.kt new file mode 100644 index 00000000..dd72313a --- /dev/null +++ b/tools/chatgui-android/tests/test_config_provider.kt @@ -0,0 +1,54 @@ +import android.content.Context +import android.content.ContextWrapper +import com.utun.chat.data.AutoSocketProtocols +import com.utun.chat.data.ConfigProvider +import com.utun.chat.data.ServerEntry +import kotlinx.coroutines.runBlocking +import java.io.File +import kotlin.system.exitProcess + +/* Запуск через app_process с собранным APK в CLASSPATH: настоящие ConfigProvider/DataStore, + * отдельный каталог без доступа к профилю приложения. Полученные .cfg проверяет test_node_config --validate. */ +fun main(args: Array): Unit = runBlocking { + val directory = File(args.single()) + check(directory.mkdirs()) { "Use a new output directory: $directory" } + val context = object : ContextWrapper(null) { + override fun getApplicationContext(): Context = this + override fun getFilesDir(): File = directory + } + val provider = ConfigProvider(context) + provider.setValue("node.name", "Android config probe") + provider.setValue("node.private_key", "704f2e012c8fa8768130cb0f988a997dccb628372bc5ceccacc78dcbfec5916f") + provider.setValue("node.public_key", "b3193173def895bd0fcea6f86af077c7d77216f10395275f627ac18242ec0f01") + provider.saveServersToConfig(emptyList()) + val defaults = File(provider.configFilePath()).readText() + check("storage_unit_size=10M\n" in defaults && "storage_total_size=1G\n" in defaults) + File(directory, "default.cfg").writeText(defaults) + provider.setValue("chat.storage_autoload_maxsize_mb", "23") + provider.setValue("chat.storage_maxsize_gb", "7") + provider.setValue("debug.categories", "config=debug,chat_sync=info,stream=debug") + provider.setConnectionMode("manual") + for (protocols in AutoSocketProtocols.values()) { + provider.setAutoSocketProtocols(protocols) + val servers = protocols.createServers("probe", "127.0.0.1", emptyList()) + + protocols.createServers("probe", "::1", emptyList()) + val inactive = listOf(ServerEntry("inactive", "offline", "192.0.2.1", "tcp", 4567)) + for (utun in 0..1) { + provider.setValue("gui.utun_enabled", "$utun") + provider.saveServersToConfig(servers, inactive) + val saved = File(provider.configFilePath()).readText() + check("#[server:offline_v4_tcp]" in saved) + val text = provider.buildConfigText() + check("storage_unit_size=23M\n" in text && "storage_total_size=7G\n" in text) + check("storage_autoload_maxsize_mb=" !in text && "storage_maxsize_gb=" !in text) + check("auto_socket_protocols=${protocols.configValue}\n" in text && "utun_enabled=$utun\n" in text) + check("radio_vad_enabled=" !in text && "radio_auto_enabled=" in text) + check(!text.contains("[server:offline_v4_tcp]")) + val name = "${protocols.configValue.replace('+', '-')}-utun$utun" + File(directory, "$name-saved.cfg").writeText(saved) + File(directory, "$name-start.cfg").writeText(text) + } + } + println("PASS: real Android ConfigProvider defaults, storage sizes, TCP/UDP, IPv4/IPv6, inactive sockets and UTUN policy") + exitProcess(0) +}