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 aaa0687e66..88aa81b186 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -133,7 +133,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF configFactory.convoVolatile?.let { config -> val convo = when { // recipient closed group - recipient.isClosedGroupRecipient -> config.getOrConstructLegacyClosedGroup(GroupUtil.doubleDecodeGroupId(recipient.address.serialize())) + recipient.isClosedGroupRecipient -> config.getOrConstructLegacyGroup(GroupUtil.doubleDecodeGroupId(recipient.address.serialize())) // recipient is open group recipient.isOpenGroupRecipient -> { val openGroupJoinUrl = getOpenGroup(threadId)?.joinURL ?: return @@ -570,7 +570,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF DatabaseComponent.get(context).groupDatabase().create(groupId, title, members, avatar, relay, admins, formationTimestamp) val volatiles = configFactory.convoVolatile ?: return val groupPublicKey = GroupUtil.doubleDecodeGroupId(groupId) - val groupVolatileConfig = volatiles.getOrConstructLegacyClosedGroup(groupPublicKey) + val groupVolatileConfig = volatiles.getOrConstructLegacyGroup(groupPublicKey) groupVolatileConfig.lastRead = formationTimestamp volatiles.set(groupVolatileConfig) ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context) diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt index bef2e01a5f..e951eac9e4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt @@ -133,6 +133,7 @@ class ConfigFactory(private val context: Context, is UserProfile -> userHashes.toList() is Contacts -> contactsHashes.toList() is ConversationVolatileConfig -> convoHashes.toList() + else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet") } override fun removeHashesFor(forConfigObject: ConfigBase, deletedHashes: Set) = @@ -140,6 +141,7 @@ class ConfigFactory(private val context: Context, is UserProfile -> userHashes.removeAll(deletedHashes) is Contacts -> contactsHashes.removeAll(deletedHashes) is ConversationVolatileConfig -> convoHashes.removeAll(deletedHashes) + else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet") } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt index 47650cf967..54800d4883 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt @@ -3,8 +3,10 @@ package org.thoughtcrime.securesms.util import android.content.Context import network.loki.messenger.libsession_util.ConfigBase import network.loki.messenger.libsession_util.Contacts +import network.loki.messenger.libsession_util.ConversationVolatileConfig import network.loki.messenger.libsession_util.UserProfile import network.loki.messenger.libsession_util.util.Contact +import network.loki.messenger.libsession_util.util.Conversation import network.loki.messenger.libsession_util.util.UserPic import nl.komponents.kovenant.Promise import org.session.libsession.messaging.MessagingModuleConfiguration @@ -14,8 +16,10 @@ import org.session.libsession.messaging.messages.Destination import org.session.libsession.messaging.messages.control.ConfigurationMessage import org.session.libsession.messaging.sending_receiving.MessageSender import org.session.libsession.utilities.Address +import org.session.libsession.utilities.GroupUtil import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.utilities.Log +import org.thoughtcrime.securesms.dependencies.DatabaseComponent object ConfigurationMessageUtilities { @@ -144,7 +148,39 @@ object ConfigurationMessageUtilities { } fun generateConversationVolatileDump(context: Context): ByteArray? { - TODO() + val secretKey = maybeUserSecretKey() ?: return null + val storage = MessagingModuleConfiguration.shared.storage + val localUserKey = storage.getUserPublicKey() ?: return null + val convoConfig = ConversationVolatileConfig.newInstance(secretKey) + val threadDb = DatabaseComponent.get(context).threadDatabase() + threadDb.approvedConversationList.use { cursor -> + val reader = threadDb.readerFor(cursor) + var current = reader.current + while (current != null) { + val recipient = current.recipient + val contact = when { + recipient.isOpenGroupRecipient -> { + val openGroup = storage.getOpenGroup(current.threadId) ?: continue + val (base, room, pubKey) = Conversation.Community.parseFullUrl(openGroup.joinURL) ?: continue + convoConfig.getOrConstructCommunity(base, room, pubKey) + } + recipient.isClosedGroupRecipient -> { + val groupPublicKey = GroupUtil.doubleDecodeGroupId(recipient.address.serialize()) + convoConfig.getOrConstructLegacyGroup(groupPublicKey) + } + recipient.isContactRecipient -> convoConfig.getOrConstructOneToOne(recipient.address.serialize()) + else -> null + } ?: continue + contact.lastRead = current.lastSeen + contact.unread = false // TODO: make the forced unread work at DB level + convoConfig.set(contact) + current = reader.next + } + } + + val dump = convoConfig.dump() + convoConfig.free() + return dump } } \ No newline at end of file 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 dc41d3d31b..9e37dfbaa1 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 @@ -497,7 +497,7 @@ class InstrumentedTests { c2.unread = true convos2.set(c2) - val c3 = convos.getOrConstructLegacyClosedGroup( + val c3 = convos.getOrConstructLegacyGroup( "05cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" ) c3.lastRead = nowMs - 50 diff --git a/libsession-util/src/main/cpp/CMakeLists.txt b/libsession-util/src/main/cpp/CMakeLists.txt index 5ce7b41669..4ac9025414 100644 --- a/libsession-util/src/main/cpp/CMakeLists.txt +++ b/libsession-util/src/main/cpp/CMakeLists.txt @@ -24,6 +24,7 @@ add_subdirectory(../../../libsession-util libsession) set(SOURCES user_profile.cpp + user_groups.cpp config_base.cpp contacts.cpp conversation.cpp diff --git a/libsession-util/src/main/cpp/conversation.cpp b/libsession-util/src/main/cpp/conversation.cpp index 96a75ee2fb..5d87272298 100644 --- a/libsession-util/src/main/cpp/conversation.cpp +++ b/libsession-util/src/main/cpp/conversation.cpp @@ -244,7 +244,7 @@ Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getLegac } extern "C" JNIEXPORT jobject JNICALL -Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getOrConstructLegacyClosedGroup( +Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getOrConstructLegacyGroup( JNIEnv *env, jobject thiz, jstring group_id) { auto convos = ptrToConvoInfo(env, thiz); auto id_chars = env->GetStringUTFChars(group_id, nullptr); diff --git a/libsession-util/src/main/cpp/user_groups.cpp b/libsession-util/src/main/cpp/user_groups.cpp new file mode 100644 index 0000000000..f44cfbeec8 --- /dev/null +++ b/libsession-util/src/main/cpp/user_groups.cpp @@ -0,0 +1,36 @@ +#include "user_groups.h" + + +#pragma clang diagnostic push +#pragma ide diagnostic ignored "bugprone-reserved-identifier" +extern "C" +JNIEXPORT jobject JNICALL +Java_network_loki_messenger_libsession_1util_UserGroupsConfig_00024Companion_newInstance___3B( + JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key) { + auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key); + + auto* user_groups = new session::config::UserGroups(secret_key, std::nullopt); + + jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/UserGroupsConfig"); + jmethodID constructor = env->GetMethodID(contactsClass, "", "(J)V"); + jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast(user_groups)); + + return newConfig; +} + +extern "C" +JNIEXPORT jobject JNICALL +Java_network_loki_messenger_libsession_1util_UserGroupsConfig_00024Companion_newInstance___3B_3B( + JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key, jbyteArray initial_dump) { + auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key); + auto initial = util::ustring_from_bytes(env, initial_dump); + + auto* user_groups = new session::config::UserGroups(secret_key, initial); + + jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts"); + jmethodID constructor = env->GetMethodID(contactsClass, "", "(J)V"); + jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast(user_groups)); + + return newConfig; +} +#pragma clang diagnostic pop diff --git a/libsession-util/src/main/cpp/user_groups.h b/libsession-util/src/main/cpp/user_groups.h new file mode 100644 index 0000000000..bd4a46e260 --- /dev/null +++ b/libsession-util/src/main/cpp/user_groups.h @@ -0,0 +1,14 @@ +#ifndef SESSION_ANDROID_USER_GROUPS_H +#define SESSION_ANDROID_USER_GROUPS_H + +#include "jni.h" +#include "util.h" +#include "session/config/user_groups.hpp" + +inline session::config::UserGroups* ptrToUserGroups(JNIEnv *env, jobject obj) { + jclass configClass = env->FindClass("network/loki/messenger/libsession_util/UserGroupsConfig"); + jfieldID pointerField = env->GetFieldID(configClass, "pointer", "J"); + return (session::config::UserGroups*) env->GetLongField(obj, pointerField); +} + +#endif //SESSION_ANDROID_USER_GROUPS_H diff --git a/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt b/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt index c0cb554a16..7a548fc9bd 100644 --- a/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt +++ b/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt @@ -18,6 +18,7 @@ sealed class ConfigBase(protected val /* yucky */ pointer: Long) { is UserProfile -> Kind.USER_PROFILE is Contacts -> Kind.CONTACTS is ConversationVolatileConfig -> Kind.CONVO_INFO_VOLATILE + is UserGroupsConfig -> Kind.GROUPS } const val isNewConfigEnabled = true @@ -98,7 +99,7 @@ class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) { external fun eraseCommunity(baseUrl: String, room: String): Boolean external fun getLegacyClosedGroup(groupId: String): Conversation.LegacyGroup? - external fun getOrConstructLegacyClosedGroup(groupId: String): Conversation.LegacyGroup + external fun getOrConstructLegacyGroup(groupId: String): Conversation.LegacyGroup external fun eraseLegacyClosedGroup(groupId: String): Boolean external fun erase(conversation: Conversation): Boolean @@ -121,4 +122,17 @@ class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) { external fun allLegacyClosedGroups(): List external fun all(): List +} + +class UserGroupsConfig(pointer: Long): ConfigBase(pointer) { + companion object { + init { + System.loadLibrary("session_util") + } + external fun newInstance(ed25519SecretKey: ByteArray): UserGroupsConfig + external fun newInstance(ed25519SecretKey: ByteArray, initialDump: ByteArray): UserGroupsConfig + } + + + } \ No newline at end of file