From 9bdfb93b501738ebe5f6a5c9cad761d5f483aced Mon Sep 17 00:00:00 2001 From: evgeny Date: Sun, 4 Oct 2026 14:59:08 +0200 Subject: [PATCH] Expose PM invitation operations and membership checks through JNI --- .../main/java/com/utun/chat/data/NativeLib.kt | 5 +++ .../jni_bridge/android_jni_bridge.c | 39 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt index 52569573..10b2d6c7 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt @@ -196,6 +196,9 @@ object NativeLib { /* ── DM (личные сообщения) ── */ fun dmStart(nodeId: Long, sourceChId: String, peerName: String) { nativeDmStart(nodeId, sourceChId, peerName) } fun dmSend(convId: String, text: String) { nativeDmSend(convId, text) } + fun dmInvite(requestId: Long, peer: Long, source: String, channelId: Long, name: String, cancel: Boolean = false): Boolean = + nativeDmInvite(requestId, peer, source, channelId, name, cancel) + fun isChannelMember(channelId: String, nodeId: Long): Boolean = nativeIsChannelMember(channelId, nodeId) fun dmRequestConversations() { nativeDmRequestConversations() } fun dmRequestCallRoute(convId: String) { nativeDmRequestCallRoute(convId) } fun dmRequestMessages(convId: String) { nativeDmRequestMessages(convId) } @@ -310,6 +313,8 @@ object NativeLib { /* ── DM JNI ── */ private external fun nativeDmStart(nodeId: Long, sourceChId: String, peerName: String) private external fun nativeDmSend(convId: String, text: String) + private external fun nativeDmInvite(requestId: Long, peer: Long, source: String, channelId: Long, name: String, cancel: Boolean): Boolean + private external fun nativeIsChannelMember(channelId: String, nodeId: Long): Boolean private external fun nativeDmRequestConversations() private external fun nativeDmRequestCallRoute(convId: String) private external fun nativeDmRequestMessages(convId: String) diff --git a/tools/chatgui-android/jni_bridge/android_jni_bridge.c b/tools/chatgui-android/jni_bridge/android_jni_bridge.c index b64ad03e..11e93d02 100644 --- a/tools/chatgui-android/jni_bridge/android_jni_bridge.c +++ b/tools/chatgui-android/jni_bridge/android_jni_bridge.c @@ -29,6 +29,7 @@ #include "../../../src/chat/chat_core.h" #include "../../../src/chat/invite_build.h" #include "../../../src/chat/chat_setting.h" +#include "../../../src/routing_layer/topo_node_sqlite.h" #include "../../../src/utun_instance.h" #include "../../../src/transport_layer/etcp.h" #include "../../../src/transport_layer/etcp_connections.h" @@ -1906,6 +1907,44 @@ JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeDmSend( if (c) (*env)->ReleaseStringUTFChars(env, convId, c); } +/* UI получает подтверждение commit через CHAT_EVT_DM_INVITE_RESULT, а не через return JNI. */ +JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeDmInvite( + JNIEnv* env, jobject thiz, jlong request_id, jlong peer, jstring source, jlong channel, jstring name, jboolean cancel) { + (void)thiz; + struct UASYNC* ua = instance_lite_get_uasync(); + struct UTUN_INSTANCE* inst = instance_lite_get_instance(); + if (!uasync_is_running(ua) || !inst) { bridge_log(BLEV_ERROR, "invite PM: core unavailable"); return JNI_FALSE; } + struct dm_invite_req* req = u_calloc(1, sizeof(*req)); + if (!req) { bridge_log(BLEV_ERROR, "invite PM: request allocation failed"); return JNI_FALSE; } + const char* src = (*env)->GetStringUTFChars(env, source, NULL); + const char* nm = src ? (*env)->GetStringUTFChars(env, name, NULL) : NULL; + if (!src || !nm) { + if (src) (*env)->ReleaseStringUTFChars(env, source, src); + bridge_log(BLEV_ERROR, "invite PM: string conversion failed"); u_free(req); return JNI_FALSE; + } + req->inst = inst; req->request_id = (uint64_t)request_id; req->peer_node_id = (uint64_t)peer; + req->channel_id = (uint64_t)channel; req->cancel = cancel ? 1 : 0; + snprintf(req->source_ch_id, sizeof(req->source_ch_id), "%s", src); + snprintf(req->peer_name, sizeof(req->peer_name), "%s", nm); + (*env)->ReleaseStringUTFChars(env, source, src); (*env)->ReleaseStringUTFChars(env, name, nm); + if (uasync_post(ua, dm_invite_trampoline, req) != 0) { + bridge_log(BLEV_ERROR, "invite PM: post failed"); u_free(req); return JNI_FALSE; + } + return JNI_TRUE; +} + +/* Чтение членства для выбора групп и открытия уже присоединённого канала. */ +JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeIsChannelMember( + JNIEnv* env, jobject thiz, jstring channel, jlong node) { + (void)thiz; + struct UTUN_INSTANCE* inst = instance_lite_get_instance(); + const char* id = (*env)->GetStringUTFChars(env, channel, NULL); + if (!id) { bridge_log(BLEV_ERROR, "channel membership: string conversion failed"); return JNI_FALSE; } + int member = inst && topo_node_sqlite_member_in_channel(inst->topo_sqlite_db, id, (uint64_t)node); + (*env)->ReleaseStringUTFChars(env, channel, id); + return member ? JNI_TRUE : JNI_FALSE; +} + JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeDmRequestConversations( JNIEnv* env, jobject thiz) { (void)env; (void)thiz;