feat: start adding user groups wrapper objects

This commit is contained in:
0x330a 2023-02-22 17:00:09 +11:00
parent fdd70ec6d0
commit 6006715b74
No known key found for this signature in database
GPG Key ID: 267811D6E6A2698C
9 changed files with 109 additions and 6 deletions

View File

@ -133,7 +133,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
configFactory.convoVolatile?.let { config -> configFactory.convoVolatile?.let { config ->
val convo = when { val convo = when {
// recipient closed group // 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 is open group
recipient.isOpenGroupRecipient -> { recipient.isOpenGroupRecipient -> {
val openGroupJoinUrl = getOpenGroup(threadId)?.joinURL ?: return 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) DatabaseComponent.get(context).groupDatabase().create(groupId, title, members, avatar, relay, admins, formationTimestamp)
val volatiles = configFactory.convoVolatile ?: return val volatiles = configFactory.convoVolatile ?: return
val groupPublicKey = GroupUtil.doubleDecodeGroupId(groupId) val groupPublicKey = GroupUtil.doubleDecodeGroupId(groupId)
val groupVolatileConfig = volatiles.getOrConstructLegacyClosedGroup(groupPublicKey) val groupVolatileConfig = volatiles.getOrConstructLegacyGroup(groupPublicKey)
groupVolatileConfig.lastRead = formationTimestamp groupVolatileConfig.lastRead = formationTimestamp
volatiles.set(groupVolatileConfig) volatiles.set(groupVolatileConfig)
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context) ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)

View File

@ -133,6 +133,7 @@ class ConfigFactory(private val context: Context,
is UserProfile -> userHashes.toList() is UserProfile -> userHashes.toList()
is Contacts -> contactsHashes.toList() is Contacts -> contactsHashes.toList()
is ConversationVolatileConfig -> convoHashes.toList() is ConversationVolatileConfig -> convoHashes.toList()
else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet")
} }
override fun removeHashesFor(forConfigObject: ConfigBase, deletedHashes: Set<String>) = override fun removeHashesFor(forConfigObject: ConfigBase, deletedHashes: Set<String>) =
@ -140,6 +141,7 @@ class ConfigFactory(private val context: Context,
is UserProfile -> userHashes.removeAll(deletedHashes) is UserProfile -> userHashes.removeAll(deletedHashes)
is Contacts -> contactsHashes.removeAll(deletedHashes) is Contacts -> contactsHashes.removeAll(deletedHashes)
is ConversationVolatileConfig -> convoHashes.removeAll(deletedHashes) is ConversationVolatileConfig -> convoHashes.removeAll(deletedHashes)
else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet")
} }
} }

View File

@ -3,8 +3,10 @@ package org.thoughtcrime.securesms.util
import android.content.Context import android.content.Context
import network.loki.messenger.libsession_util.ConfigBase import network.loki.messenger.libsession_util.ConfigBase
import network.loki.messenger.libsession_util.Contacts 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.UserProfile
import network.loki.messenger.libsession_util.util.Contact 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 network.loki.messenger.libsession_util.util.UserPic
import nl.komponents.kovenant.Promise import nl.komponents.kovenant.Promise
import org.session.libsession.messaging.MessagingModuleConfiguration 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.messages.control.ConfigurationMessage
import org.session.libsession.messaging.sending_receiving.MessageSender import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.utilities.Address import org.session.libsession.utilities.Address
import org.session.libsession.utilities.GroupUtil
import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
object ConfigurationMessageUtilities { object ConfigurationMessageUtilities {
@ -144,7 +148,39 @@ object ConfigurationMessageUtilities {
} }
fun generateConversationVolatileDump(context: Context): ByteArray? { 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
} }
} }

View File

@ -497,7 +497,7 @@ class InstrumentedTests {
c2.unread = true c2.unread = true
convos2.set(c2) convos2.set(c2)
val c3 = convos.getOrConstructLegacyClosedGroup( val c3 = convos.getOrConstructLegacyGroup(
"05cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" "05cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
) )
c3.lastRead = nowMs - 50 c3.lastRead = nowMs - 50

View File

@ -24,6 +24,7 @@ add_subdirectory(../../../libsession-util libsession)
set(SOURCES set(SOURCES
user_profile.cpp user_profile.cpp
user_groups.cpp
config_base.cpp config_base.cpp
contacts.cpp contacts.cpp
conversation.cpp conversation.cpp

View File

@ -244,7 +244,7 @@ Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getLegac
} }
extern "C" extern "C"
JNIEXPORT jobject JNICALL 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) { JNIEnv *env, jobject thiz, jstring group_id) {
auto convos = ptrToConvoInfo(env, thiz); auto convos = ptrToConvoInfo(env, thiz);
auto id_chars = env->GetStringUTFChars(group_id, nullptr); auto id_chars = env->GetStringUTFChars(group_id, nullptr);

View File

@ -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, "<init>", "(J)V");
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(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, "<init>", "(J)V");
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(user_groups));
return newConfig;
}
#pragma clang diagnostic pop

View File

@ -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

View File

@ -18,6 +18,7 @@ sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
is UserProfile -> Kind.USER_PROFILE is UserProfile -> Kind.USER_PROFILE
is Contacts -> Kind.CONTACTS is Contacts -> Kind.CONTACTS
is ConversationVolatileConfig -> Kind.CONVO_INFO_VOLATILE is ConversationVolatileConfig -> Kind.CONVO_INFO_VOLATILE
is UserGroupsConfig -> Kind.GROUPS
} }
const val isNewConfigEnabled = true const val isNewConfigEnabled = true
@ -98,7 +99,7 @@ class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) {
external fun eraseCommunity(baseUrl: String, room: String): Boolean external fun eraseCommunity(baseUrl: String, room: String): Boolean
external fun getLegacyClosedGroup(groupId: String): Conversation.LegacyGroup? 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 eraseLegacyClosedGroup(groupId: String): Boolean
external fun erase(conversation: Conversation): Boolean external fun erase(conversation: Conversation): Boolean
@ -122,3 +123,16 @@ class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) {
external fun all(): List<Conversation> external fun all(): List<Conversation>
} }
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
}
}