Browse Source

Expose native debug categories and fix Android level fields

master
evgeny 6 days ago
parent
commit
7fa7a42673
  1. 2
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt
  2. 23
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/SettingsScreen.kt
  3. 19
      tools/chatgui-android/jni_bridge/android_jni_bridge.c

2
tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt

@ -111,6 +111,7 @@ object NativeLib {
fun feedbackCommand(json: String, requestId: Long = 0): Boolean = nativeFeedbackCommand(json.toByteArray(Charsets.UTF_8), requestId)
fun clearDatabase(): Boolean = nativeClearDatabase()
fun setDebugLevel(category: String, level: String) { nativeSetDebugLevel(category, level) }
fun getDebugCategories(): List<String> = nativeGetDebugCategories()?.split(",")?.filter { it.isNotEmpty() } ?: emptyList()
/* ── Chat settings (live update via C side) ── */
fun setChatSetting(name: String, value: String) { nativeSetChatSetting(name, value) }
@ -294,6 +295,7 @@ object NativeLib {
private external fun nativeGetMessages(channelId: String, limit: Int, anchor: ByteArray, exact: Boolean): String?
private external fun nativeFeedbackCommand(json: ByteArray, requestId: Long): Boolean
private external fun nativeSetDebugLevel(category: String, level: String)
private external fun nativeGetDebugCategories(): String?
private external fun nativeSetChatSetting(name: String, value: String)
private external fun nativeGetChatSettingInt(name: String, def: Int): Int
private external fun nativeGetSoundOnMessage(chId: String): Int

23
tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/SettingsScreen.kt

@ -60,14 +60,7 @@ import kotlinx.coroutines.withContext
import java.util.UUID
import java.io.IOException
private val LEVELS = listOf("NONE", "ERROR", "WARN", "INFO", "DEBUG", "TRACE")
private val CATEGORIES = listOf(
"sys", "connection", "etcp", "crypto",
"config", "tun", "routing", "timers", "bgp", "chat",
"socket", "control", "dump", "traffic", "debug", "general",
"nat", "keepalive", "media", "etcp_route", "etcp_dump",
"chat_sync", "member_sync", "proxy", "radio", "vad"
)
private val LEVELS = listOf("DISABLED", "NONE", "ERROR", "WARN", "INFO", "DEBUG", "TRACE")
private val PROTOCOLS = listOf("tcp", "udp")
@OptIn(ExperimentalMaterial3Api::class)
@ -173,6 +166,7 @@ private fun DeveloperSettingsTab(vm: ChatViewModel, onDirty: (Boolean) -> Unit,
var showClearDb by remember { mutableStateOf(false) }
var clearingDb by remember { mutableStateOf(false) }
var catLevels by remember { mutableStateOf<Map<String, String>>(emptyMap()) }
val debugCategories = remember { NativeLib.getDebugCategories() }
var servers by remember { mutableStateOf<List<ServerEntry>>(emptyList()) }
var availableIfaces by remember { mutableStateOf<List<Pair<String, String>>>(emptyList()) }
var connectionMode by remember { mutableStateOf("manual") }
@ -219,11 +213,10 @@ private fun DeveloperSettingsTab(vm: ChatViewModel, onDirty: (Boolean) -> Unit,
}
}
val setDebug = { level: String ->
onDirty(true); NativeLib.setDebugLevel("", level)
NativeLib.setDebugLevel("", level)
scope.launch { provider.setValue("debug.console_level", level) }; debugLevel = level
}
val setCatLevel = { cat: String, lvl: String ->
onDirty(true)
val updated = catLevels.toMutableMap()
if (lvl == "") updated.remove(cat) else updated[cat] = lvl
catLevels = updated
@ -474,7 +467,7 @@ private fun DeveloperSettingsTab(vm: ChatViewModel, onDirty: (Boolean) -> Unit,
}
}
if (showDebugCategories) {
items(CATEGORIES, key = { "debug-$it" }) { cat ->
items(debugCategories, key = { "debug-$it" }) { cat ->
val current = catLevels[cat] ?: ""
DebugLevelDropdown(label = cat, current = current.ifEmpty { stringResource(R.string.global_level_hint) },
onSelect = { setCatLevel(cat, if (it == "NONE") "" else it) }, compact = true)
@ -1141,10 +1134,10 @@ private fun DebugLevelDropdown(label: String, current: String, onSelect: (String
if (compact) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(label, modifier = Modifier.width(120.dp), style = MaterialTheme.typography.labelMedium)
ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = it }) {
ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = it }, modifier = Modifier.weight(1f)) {
OutlinedTextField(current, {}, readOnly = true,
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded) },
modifier = Modifier.menuAnchor().height(48.dp).weight(1f), singleLine = true)
modifier = Modifier.menuAnchor().fillMaxWidth().heightIn(min = 56.dp), singleLine = true)
ExposedDropdownMenu(expanded, onDismissRequest = { expanded = false }) {
LEVELS.forEach { lvl ->
DropdownMenuItem(text = { Text(lvl) }, onClick = { onSelect(lvl); expanded = false })
@ -1153,10 +1146,10 @@ private fun DebugLevelDropdown(label: String, current: String, onSelect: (String
}
}
} else {
ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = it }) {
ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = it }, modifier = Modifier.fillMaxWidth()) {
OutlinedTextField(current, {}, readOnly = true, label = { Text(stringResource(R.string.debug_level_label, label)) },
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded) },
modifier = Modifier.menuAnchor(), singleLine = true)
modifier = Modifier.menuAnchor().fillMaxWidth().heightIn(min = 56.dp), singleLine = true)
ExposedDropdownMenu(expanded, onDismissRequest = { expanded = false }) {
LEVELS.forEach { lvl ->
DropdownMenuItem(text = { Text(lvl) }, onClick = { onSelect(lvl); expanded = false })

19
tools/chatgui-android/jni_bridge/android_jni_bridge.c

@ -671,13 +671,14 @@ int utun_bridge_dm_send_file(const char* conv_id, const char* path, const char*
}
void utun_bridge_set_debug_level(const char* category, const char* level) {
if (!level) return;
if (!level) { bridge_log(BLEV_ERROR, "Debug level: missing level"); return; }
if (!category || !category[0]) {
debug_level_t lvl = debug_level_from_name(level);
debug_set_level(lvl);
} else {
debug_set_category_level_by_name(category, level);
}
bridge_log(BLEV_INFO, "Debug level applied: %s=%s", category && category[0] ? category : "global", level);
}
void utun_bridge_chat_setting_set(const char* name, const char* value) {
@ -2190,6 +2191,22 @@ JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeConnectMemberNode
if (ch) (*env)->ReleaseStringUTFChars(env, channelId, ch);
}
JNIEXPORT jstring JNICALL Java_com_utun_chat_data_NativeLib_nativeGetDebugCategories(JNIEnv* env, jobject thiz) {
(void)thiz;
struct strbuf names = strbuf_new();
for (int category = 1; category < DEBUG_CATEGORY_COUNT; category++) {
const char* name = debug_get_category_name(category);
if (strcmp(name, "UNKNOWN") == 0) continue;
if (strbuf_addf(&names, "%s%s", names.len ? "," : "", name) < 0) {
bridge_log(BLEV_ERROR, "Debug categories: allocation failed");
strbuf_free(&names); return NULL;
}
}
jstring result = (*env)->NewStringUTF(env, strbuf_str(&names));
if (!result) bridge_log(BLEV_ERROR, "Debug categories: Java string allocation failed");
strbuf_free(&names); return result;
}
JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeSetDebugLevel(
JNIEnv* env, jobject thiz, jstring category, jstring level) {
(void)thiz;

Loading…
Cancel
Save