diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index a88738bd8e..ff5577a624 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -261,7 +261,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co val convo = when { // recipient closed group recipient.isLegacyClosedGroupRecipient -> config.getOrConstructLegacyGroup(GroupUtil.doubleDecodeGroupId(recipient.address.serialize())) - recipient.isClosedGroupRecipient -> config.getOrConstructGroup(recipient.address.serialize()) + recipient.isClosedGroupRecipient -> config.getOrConstructClosedGroup(recipient.address.serialize()) // recipient is open group recipient.isOpenGroupRecipient -> { val openGroupJoinUrl = getOpenGroup(threadId)?.joinURL ?: return @@ -528,6 +528,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co is Conversation.OneToOne -> getThreadIdFor(conversation.sessionId, null, null, createThread = false) is Conversation.LegacyGroup -> getThreadIdFor("", conversation.groupId,null, createThread = false) is Conversation.Community -> getThreadIdFor("",null, "${conversation.baseCommunityInfo.baseUrl.removeSuffix("/")}.${conversation.baseCommunityInfo.room}", createThread = false) + is Conversation.ClosedGroup -> getThreadIdFor(conversation.sessionId, null, null, createThread = false) } if (threadId != null) { if (conversation.lastRead > getLastSeen(threadId)) { @@ -872,7 +873,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co groupVolatileConfig.lastRead = formationTimestamp volatiles.set(groupVolatileConfig) val groupInfo = GroupInfo.LegacyGroupInfo( - sessionId = groupPublicKey, + sessionId = SessionId.from(groupPublicKey), name = name, members = members, priority = PRIORITY_VISIBLE, @@ -965,9 +966,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co } override fun isClosedGroup(publicKey: String): Boolean { - val isClosedGroup = DatabaseComponent.get(context).lokiAPIDatabase().isClosedGroup(publicKey) - val address = fromSerialized(publicKey) - return address.isClosedGroup || isClosedGroup + return DatabaseComponent.get(context).lokiAPIDatabase().isClosedGroup(publicKey) } override fun getClosedGroupEncryptionKeyPairs(groupPublicKey: String): MutableList { @@ -1313,7 +1312,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co groups.set(newGroupInfo) } threadRecipient.isClosedGroupRecipient -> { - val newGroupInfo = groups.getGroupInfo(threadRecipient.address.serialize()).copy ( + val newGroupInfo = groups.getOrConstructClosedGroup(threadRecipient.address.serialize()).copy ( priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE ) groups.set(newGroupInfo) diff --git a/libsession-util/src/androidTest/java/network/loki/messenger/libsession_util/InstrumentedTests.kt b/libsession-util/src/androidTest/java/network/loki/messenger/libsession_util/InstrumentedTests.kt index 905c28e039..3f5bee9049 100644 --- a/libsession-util/src/androidTest/java/network/loki/messenger/libsession_util/InstrumentedTests.kt +++ b/libsession-util/src/androidTest/java/network/loki/messenger/libsession_util/InstrumentedTests.kt @@ -560,6 +560,7 @@ class InstrumentedTests { is Conversation.OneToOne -> seen.add("1-to-1: ${convo.sessionId}") is Conversation.Community -> seen.add("og: ${convo.baseCommunityInfo.baseUrl}/r/${convo.baseCommunityInfo.room}") is Conversation.LegacyGroup -> seen.add("cl: ${convo.groupId}") + is Conversation.ClosedGroup -> TODO() } } diff --git a/libsession-util/src/main/cpp/conversation.cpp b/libsession-util/src/main/cpp/conversation.cpp index e43df280d7..8b75d1b88d 100644 --- a/libsession-util/src/main/cpp/conversation.cpp +++ b/libsession-util/src/main/cpp/conversation.cpp @@ -371,12 +371,20 @@ extern "C" JNIEXPORT jobject JNICALL Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getOrConstructClosedGroup( JNIEnv *env, jobject thiz, jstring session_id) { - // TODO: implement getOrConstructClosedGroup() + auto config = ptrToConvoInfo(env, thiz); + auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr); + auto group = config->get_or_construct_group(session_id_bytes); + env->ReleaseStringUTFChars(session_id, session_id_bytes); + return serialize_closed_group(env, group); } extern "C" JNIEXPORT jboolean JNICALL Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_eraseClosedGroup( JNIEnv *env, jobject thiz, jstring session_id) { - // TODO: implement eraseClosedGroup() + auto config = ptrToConvoInfo(env, thiz); + auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr); + auto erased = config->erase_group(session_id_bytes); + env->ReleaseStringUTFChars(session_id, session_id_bytes); + return erased; } \ No newline at end of file diff --git a/libsession-util/src/main/cpp/conversation.h b/libsession-util/src/main/cpp/conversation.h index 17288d96eb..330e0e499f 100644 --- a/libsession-util/src/main/cpp/conversation.h +++ b/libsession-util/src/main/cpp/conversation.h @@ -58,6 +58,8 @@ inline jobject serialize_any(JNIEnv *env, session::config::convo::any any) { return serialize_open_group(env, *og); } else if (auto* lgc = std::get_if(&any)) { return serialize_legacy_group(env, *lgc); + } else if (auto* gc = std::get_if(&any)) { + return serialize_closed_group(env, *gc); } return nullptr; } @@ -113,10 +115,30 @@ inline session::config::convo::legacy_group deserialize_legacy_closed_group(JNIE return deserialized; } +inline session::config::convo::group deserialize_closed_group(JNIEnv* env, jobject info, session::config::ConvoInfoVolatile* conf) { + auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$ClosedGroup"); + auto id_getter = env->GetFieldID(clazz, "sessionId", "Ljava/lang/String;"); + auto last_read_getter = env->GetFieldID(clazz, "lastRead", "J"); + auto unread_getter = env->GetFieldID(clazz, "unread", "Z"); + auto session_id = (jstring)env->GetObjectField(info, id_getter); + auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr); + auto last_read = env->GetLongField(info, last_read_getter); + auto unread = env->GetBooleanField(info, unread_getter); + + auto group = conf->get_or_construct_group(session_id_bytes); + group.last_read = last_read; + group.unread = unread; + + env->ReleaseStringUTFChars(session_id, session_id_bytes); + return group; +} + inline std::optional deserialize_any(JNIEnv *env, jobject convo, session::config::ConvoInfoVolatile *conf) { auto oto_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$OneToOne"); auto og_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$Community"); auto lgc_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$LegacyGroup"); + auto gc_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$ClosedGroup"); + auto object_class = env->GetObjectClass(convo); if (env->IsSameObject(object_class, oto_class)) { return session::config::convo::any{deserialize_one_to_one(env, convo, conf)}; @@ -124,6 +146,8 @@ inline std::optional deserialize_any(JNIEnv *env, j return session::config::convo::any{deserialize_community(env, convo, conf)}; } else if (env->IsSameObject(object_class, lgc_class)) { return session::config::convo::any{deserialize_legacy_closed_group(env, convo, conf)}; + } else if (env->IsSameObject(object_class, gc_class)) { + return session::config::convo::any{deserialize_closed_group(env, convo, conf)}; } return std::nullopt; } diff --git a/libsession-util/src/main/cpp/user_groups.h b/libsession-util/src/main/cpp/user_groups.h index 7cd5b4eb3e..22d7643adc 100644 --- a/libsession-util/src/main/cpp/user_groups.h +++ b/libsession-util/src/main/cpp/user_groups.h @@ -132,9 +132,9 @@ inline jobject serialize_closed_group_info(JNIEnv* env, session::config::group_i jbyteArray auth_bytes = util::bytes_from_ustring(env, info.auth_data); jclass group_info_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo"); - jmethodID constructor = env->GetMethodID(group_info_class, "", "(Lorg/session/libsignal/utilities/SessionId;[B[B)V"); + jmethodID constructor = env->GetMethodID(group_info_class, "", "(Lorg/session/libsignal/utilities/SessionId;[B[BJ)V"); jobject return_object = env->NewObject(group_info_class,constructor, - session_id, admin_bytes, auth_bytes); + session_id, admin_bytes, auth_bytes, (jlong)info.priority); return return_object; } @@ -143,6 +143,8 @@ inline session::config::group_info deserialize_closed_group_info(JNIEnv* env, jo jfieldID id_field = env->GetFieldID(closed_group_class, "groupSessionId", "Lorg/session/libsignal/utilities/SessionId;"); jfieldID secret_field = env->GetFieldID(closed_group_class, "adminKey", "[B"); jfieldID auth_field = env->GetFieldID(closed_group_class, "authData", "[B"); + jfieldID priority_field = env->GetFieldID(closed_group_class, "priority", "J"); + jobject id_jobject = env->GetObjectField(info_serialized, id_field); jbyteArray secret_jBytes = (jbyteArray)env->GetObjectField(info_serialized, secret_field); @@ -155,6 +157,7 @@ inline session::config::group_info deserialize_closed_group_info(JNIEnv* env, jo session::config::group_info group_info(id_bytes); group_info.auth_data = auth_bytes; group_info.secretkey = secret_bytes; + group_info.priority = env->GetLongField(info_serialized, priority_field); return group_info; } diff --git a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupInfo.kt b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupInfo.kt index 1754cc342b..ac472b73e8 100644 --- a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupInfo.kt +++ b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupInfo.kt @@ -9,7 +9,8 @@ sealed class GroupInfo { data class ClosedGroupInfo( val groupSessionId: SessionId, val adminKey: ByteArray, - val authData: ByteArray + val authData: ByteArray, + val priority: Long, ): GroupInfo() { override fun equals(other: Any?): Boolean { if (this === other) return true