Browse Source

Request Android member snapshots on the core thread

master
evgeny 2 days ago
parent
commit
658c248867
  1. 9
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/ChatRepository.kt
  2. 3
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/NativeLib.kt
  3. 25
      tools/chatgui-android/jni_bridge/android_jni_bridge.c

9
tools/chatgui-android/app/src/main/java/com/utun/chat/data/ChatRepository.kt

@ -72,6 +72,7 @@ data class Message(val id: Long, val author: String, val text: String, val ts: L
data class ChatMember(val nodeId: Long, val name: String, val online: Boolean = false,
val isAdmin: Boolean = false, val isSuper: Boolean = false,
val isModer: Boolean = false, val isStorage: Boolean = false,
val radioActive: Boolean = false,
val isVerified: Boolean = false, val isDeleted: Boolean = false,
val nodeType: Int = 0,
val rtt: Int = 0, val isSelf: Boolean = false,
@ -167,7 +168,7 @@ data class MemberWire(
)
fun parseMemberWire(data: ByteArray, offset: Int = 0): MemberWire? {
if (offset + 79 > data.size) return null
if (offset < 0 || offset > data.size - 79) return null
val buf = ByteBuffer.wrap(data, offset, 79).order(ByteOrder.LITTLE_ENDIAN)
val nodeId = buf.getLong()
val online = buf.get().toInt() and 0xFF
@ -181,10 +182,12 @@ fun parseMemberWire(data: ByteArray, offset: Int = 0): MemberWire? {
return MemberWire(nodeId, online, isSelf, flags, rtt, natType, storage, name)
}
fun MemberWire.toChatMember(): ChatMember = ChatMember(
nodeId = nodeId, name = name, online = online != 0,
/* Wire не содержит verified/nodeType и состояния транспортов: сохраняем их из текущей строки. */
fun MemberWire.toChatMember(previous: ChatMember = ChatMember(nodeId, name)): ChatMember = previous.copy(
name = name, online = online != 0,
isAdmin = (flags and 2) != 0, isSuper = (flags and 1) != 0,
isModer = (flags and 4) != 0, isStorage = storage,
isDeleted = (flags and 8) != 0, radioActive = (flags and 0x10) != 0,
rtt = if (rtt == 0xFFFF) 0 else rtt, isSelf = isSelf
)

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

@ -115,6 +115,8 @@ object NativeLib {
/* ── Channel members ── */
fun getChannelMembers(channelId: String): String = nativeGetChannelMembers(channelId) ?: "[]"
/** Асинхронный live-снимок; ответ — событие MEMBER_LIST. */
fun requestMemberList(channelId: String): Boolean = nativeRequestMemberList(channelId)
fun getMemberDetail(channelId: String, nodeId: Long): String = nativeGetMemberDetail(channelId, nodeId) ?: "{}"
fun setMemberNick(channelId: String, nodeId: Long, nick: String) { nativeSetMemberNick(channelId, nodeId, nick) }
fun isChannelOwner(channelId: String): Boolean = nativeIsChannelOwner(channelId)
@ -240,6 +242,7 @@ object NativeLib {
/* ── Channel members JNI ── */
private external fun nativeGetChannelMembers(channelId: String): String?
private external fun nativeRequestMemberList(channelId: String): Boolean
private external fun nativeGetMemberDetail(channelId: String, nodeId: Long): String?
private external fun nativeSetMemberNick(channelId: String, nodeId: Long, nick: String)
private external fun nativeIsChannelOwner(channelId: String): Boolean

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

@ -27,6 +27,7 @@
#include "../../../lib/mem.h"
#include "../../../lib/sqlite3.h"
#include "../../../src/chat/chat_core.h"
#include "../../../src/chat/chat_member.h"
#include "../../../src/chat/invite_build.h"
#include "../../../src/chat/chat_setting.h"
#include "../../../src/routing_layer/topo_node_sqlite.h"
@ -2294,6 +2295,30 @@ JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeVoiceDecodeClose(
/* ── Channel members JNI ── */
/* Живой снимок группы читается в uasync; результат приходит как MEMBER_LIST. */
JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeRequestMemberList(
JNIEnv* env, jobject thiz, jstring channelId) {
(void)thiz;
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
struct UASYNC* ua = instance_lite_get_uasync();
if (!inst || !ua || !channelId) {
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "request_member_list: missing instance/uasync/channel"); return JNI_FALSE;
}
const char* ch = (*env)->GetStringUTFChars(env, channelId, NULL);
if (!ch) { DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "request_member_list: cannot read channel"); return JNI_FALSE; }
struct chat_member_list_req* req = u_calloc(1, sizeof(*req));
if (!req || !ch[0] || strlen(ch) >= sizeof(req->ch_id)) {
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "request_member_list: allocation/invalid channel ch=%s", ch);
u_free(req); (*env)->ReleaseStringUTFChars(env, channelId, ch); return JNI_FALSE;
}
req->inst = inst;
memcpy(req->ch_id, ch, strlen(ch) + 1);
DEBUG_DEBUG(DEBUG_CATEGORY_CHAT_SYNC, "request_member_list: queued ch=%s", ch);
(*env)->ReleaseStringUTFChars(env, channelId, ch);
uasync_post(ua, chat_core_request_member_list_trampoline, req);
return JNI_TRUE;
}
JNIEXPORT jstring JNICALL Java_com_utun_chat_data_NativeLib_nativeGetChannelMembers(
JNIEnv* env, jobject thiz, jstring channelId) {
(void)thiz;

Loading…
Cancel
Save