Bind private conversation start requests to the worker conversation ID

This commit is contained in:
evgeny committed 2026-10-29 13:35:41 +01:00
1 parent c1ad35e152
commit 69ae8b57cb
3 files changed
+16 -7

No files matched your search

@@ -543,7 +543,8 @@ class ChatRepository(private val reportFailure: (String) -> Unit = { LogManager.
/* ── DM (личные сообщения) ── */
fun dmStart(nodeId: Long, sourceChId: String, peerName: String) =
/** ID принятого запроса, привязанный к instance; null означает отказ очереди, событие ещё не подтверждает commit. */
fun dmStart(nodeId: Long, sourceChId: String, peerName: String): String? =
NativeLib.dmStart(nodeId, sourceChId, peerName)
fun dmSend(convId: String, text: String, generation: Long, requestId: Long): Boolean =
@@ -379,7 +379,9 @@ object NativeLib {
fun radioTalkEnd(groupId: Long) { nativeRadioTalkEnd(groupId) }
/* ── DM (личные сообщения) ── */
fun dmStart(nodeId: Long, sourceChId: String, peerName: String): Boolean = nativeDmStart(nodeId, sourceChId, peerName)
/** Зафиксированный worker ID принятой беседы; null — отказ без события. Commit подтверждает DM_CONV_UPDATED с тем же ID. */
fun dmStart(nodeId: Long, sourceChId: String, peerName: String): String? =
nativeDmStart(nodeId, sourceChId, peerName).takeIf { it != 0L }?.toULong()?.toString()
/** UTF-8 без Modified UTF-8: true подтверждает очередь, CHAT_EVT_MSG_SUBMITTED — запись истории/outbox. */
fun dmSend(convId: String, text: String, generation: Long, requestId: Long): Boolean =
nativeDmSend(convId, text.toByteArray(Charsets.UTF_8), generation, requestId)
@@ -522,7 +524,7 @@ object NativeLib {
/* ── DM JNI ── */
private external fun nativeDmDelete(convId: String, generation: Long, request: Long): Boolean
private external fun nativeDmStart(nodeId: Long, sourceChId: String, peerName: String): Boolean
private external fun nativeDmStart(nodeId: Long, sourceChId: String, peerName: String): Long
private external fun nativeDmSend(convId: String, text: ByteArray, generation: Long, requestId: Long): Boolean
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
@@ -22,6 +22,7 @@
#include "../../../src/radio/radio_call.h"
#include "../../../src/radio/radio_audio.h"
#include "../../../src/dm/dm_core.h"
#include "../../../src/dm/dm_crypto.h"
#include "../../../src/dm/dm_media.h"
#include "../../../lib/debug_config.h"
#include "../../../lib/u_async.h"
@@ -1590,7 +1591,7 @@ static jobject g_event_callback = NULL;
static jmethodID g_event_mid = NULL;
static pthread_mutex_t g_event_callback_lock = PTHREAD_MUTEX_INITIALIZER;
enum bridge_query_kind { QUERY_CHANNELS, QUERY_MESSAGES, QUERY_MEMBERS, QUERY_DETAIL, QUERY_LINKS, QUERY_NODE, QUERY_SET_NICK,
enum bridge_query_kind { QUERY_CHANNELS, QUERY_MESSAGES, QUERY_MEMBERS, QUERY_DETAIL, QUERY_LINKS, QUERY_NODE, QUERY_SET_NICK, QUERY_DM_START,
QUERY_OWNER, QUERY_MEMBERSHIP, QUERY_SETTING, QUERY_SOUND, QUERY_RADIO_SUBSCRIBERS, QUERY_RADIO_START };
/* Строки/ID заимствованы до возврата instance_lite_call; JSON становится собственностью JNI caller. */
struct bridge_query {
@@ -1613,6 +1614,10 @@ static void bridge_query_run(void* arg) {
case QUERY_LINKS: q->json = utun_bridge_get_member_links_json(q->node); break;
case QUERY_NODE: q->number = (int64_t)utun_bridge_get_my_node_id(); break;
case QUERY_SET_NICK: utun_bridge_set_member_nick(q->channel, q->node, q->value); break;
case QUERY_DM_START:
if (!utun_bridge_dm_start(q->node, q->channel, q->value))
q->number = (int64_t)dm_derive_conv_id(instance_lite_get_instance()->node_id, q->node);
break;
case QUERY_OWNER: q->number = utun_bridge_is_channel_owner(q->channel); break;
case QUERY_MEMBERSHIP: q->number = topo_node_sqlite_member_in_channel(instance_lite_get_instance()->topo_sqlite_db,
q->channel, q->node); break;
@@ -2266,15 +2271,16 @@ JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeFeedbackComma
((char*)(req + 1))[len] = 0; int posted = bridge_post_request(chat_feedback_command_trampoline, req, &req->inst); return posted == 0 ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeDmStart(
JNIEXPORT jlong JNICALL Java_com_utun_chat_data_NativeLib_nativeDmStart(
JNIEnv* env, jobject thiz, jlong nodeId, jstring sourceChId, jstring peerName) {
(void)thiz;
const char* ch = sourceChId ? jni_utf8(env, sourceChId) : NULL;
const char* nm = peerName ? jni_utf8(env, peerName) : NULL;
int result = utun_bridge_dm_start((uint64_t)nodeId, ch, nm);
struct bridge_query query = {.kind = QUERY_DM_START, .channel = ch, .value = nm, .node = (uint64_t)nodeId};
if ((!sourceChId || ch) && (!peerName || nm)) bridge_query_call(&query);
if (nm) u_free((void*)nm);
if (ch) u_free((void*)ch);
return result == 0 ? JNI_TRUE : JNI_FALSE;
return (jlong)query.number;
}
JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeDmSend(