mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-25 02:55:23 +00:00
feat: more usergroup functionality, storage functionality for checking pinned status, adding pinned status for NTS/contacts, move community info parse full url to base community, add StorageProtocol logic for group info
This commit is contained in:
parent
2a701f2cc3
commit
66c997dfb2
@ -745,6 +745,11 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
return getThreadId(address)
|
||||
}
|
||||
|
||||
override fun getThreadId(openGroup: OpenGroup): Long? {
|
||||
val address = fromSerialized("${openGroup.server}.${openGroup.room}")
|
||||
return getThreadId(address)
|
||||
}
|
||||
|
||||
override fun getThreadId(address: Address): Long? {
|
||||
val recipient = Recipient.from(context, address, false)
|
||||
return getThreadId(recipient)
|
||||
@ -866,7 +871,15 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
return mmsSmsDb.getConversationCount(threadID)
|
||||
}
|
||||
|
||||
override fun setPinned(threadID: Long, isPinned: Boolean) {
|
||||
val threadDB = DatabaseComponent.get(context).threadDatabase()
|
||||
threadDB.setPinned(threadID, isPinned)
|
||||
}
|
||||
|
||||
override fun isPinned(threadID: Long): Boolean {
|
||||
val threadDB = DatabaseComponent.get(context).threadDatabase()
|
||||
return threadDB.isPinned(threadID)
|
||||
}
|
||||
|
||||
override fun getAttachmentDataUri(attachmentId: AttachmentId): Uri {
|
||||
return PartAuthority.getAttachmentDataUri(attachmentId)
|
||||
|
@ -740,6 +740,19 @@ public class ThreadDatabase extends Database {
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
public boolean isPinned(long threadId) {
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
Cursor cursor = db.query(TABLE_NAME, new String[]{DATE}, ID_WHERE, new String[]{String.valueOf(threadId)}, null, null, null);
|
||||
try {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return cursor.getInt(0) == 1;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
if (cursor != null) cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void markAllAsRead(long threadId, boolean isGroupRecipient, long lastSeenTime) {
|
||||
List<MarkedMessageInfo> messages = setRead(threadId, lastSeenTime);
|
||||
if (isGroupRecipient) {
|
||||
|
@ -4,9 +4,12 @@ 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.UserGroupsConfig
|
||||
import network.loki.messenger.libsession_util.UserProfile
|
||||
import network.loki.messenger.libsession_util.util.BaseCommunityInfo
|
||||
import network.loki.messenger.libsession_util.util.Contact
|
||||
import network.loki.messenger.libsession_util.util.Conversation
|
||||
import network.loki.messenger.libsession_util.util.GroupInfo
|
||||
import network.loki.messenger.libsession_util.util.UserPic
|
||||
import nl.komponents.kovenant.Promise
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
@ -19,7 +22,9 @@ import org.session.libsession.messaging.utilities.SessionId
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.utilities.Hex
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.toHexString
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||
|
||||
object ConfigurationMessageUtilities {
|
||||
@ -103,6 +108,8 @@ object ConfigurationMessageUtilities {
|
||||
private fun maybeUserSecretKey() = MessagingModuleConfiguration.shared.getUserED25519KeyPair()?.secretKey?.asBytes
|
||||
|
||||
fun generateUserProfileConfigDump(): ByteArray? {
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val ownPublicKey = storage.getUserPublicKey() ?: return null
|
||||
val config = ConfigurationMessage.getCurrent(listOf()) ?: return null
|
||||
val secretKey = maybeUserSecretKey() ?: return null
|
||||
val profile = UserProfile.newInstance(secretKey)
|
||||
@ -112,6 +119,13 @@ object ConfigurationMessageUtilities {
|
||||
if (!picUrl.isNullOrEmpty() && picKey.isNotEmpty()) {
|
||||
profile.setPic(UserPic(picUrl, picKey))
|
||||
}
|
||||
val ownThreadId = storage.getThreadId(Address.fromSerialized(ownPublicKey))
|
||||
profile.setNtsHidden(ownThreadId != null)
|
||||
if (ownThreadId != null) {
|
||||
// have NTS thread
|
||||
val ntsPinned = storage.isPinned(ownThreadId)
|
||||
profile.setNtsPriority(if (ntsPinned) 1 else 0) // TODO: implement the pinning priority here in future
|
||||
}
|
||||
val dump = profile.dump()
|
||||
profile.free()
|
||||
return dump
|
||||
@ -124,10 +138,16 @@ object ConfigurationMessageUtilities {
|
||||
val contactsWithSettings = storage.getAllContacts().filter { recipient ->
|
||||
recipient.sessionID != localUserKey
|
||||
}.map { contact ->
|
||||
contact to storage.getRecipientSettings(Address.fromSerialized(contact.sessionID))!!
|
||||
val address = Address.fromSerialized(contact.sessionID)
|
||||
val thread = storage.getThreadId(address)
|
||||
val isPinned = if (thread != null) {
|
||||
storage.isPinned(thread)
|
||||
} else false
|
||||
|
||||
Triple(contact, storage.getRecipientSettings(address)!!, isPinned)
|
||||
}
|
||||
val contactConfig = Contacts.newInstance(secretKey)
|
||||
for ((contact, settings) in contactsWithSettings) {
|
||||
for ((contact, settings, isPinned) in contactsWithSettings) {
|
||||
val url = contact.profilePictureURL
|
||||
val key = contact.profilePictureEncryptionKey
|
||||
val userPic = if (url.isNullOrEmpty() || key?.isNotEmpty() != true) {
|
||||
@ -143,7 +163,7 @@ object ConfigurationMessageUtilities {
|
||||
approved = settings.isApproved,
|
||||
approvedMe = settings.hasApprovedMe(),
|
||||
profilePicture = userPic ?: UserPic.DEFAULT,
|
||||
priority = if ()
|
||||
priority = if (isPinned) 1 else 0
|
||||
)
|
||||
contactConfig.set(contactInfo)
|
||||
}
|
||||
@ -196,4 +216,45 @@ object ConfigurationMessageUtilities {
|
||||
return dump
|
||||
}
|
||||
|
||||
fun generateUserGroupDump(context: Context): ByteArray? {
|
||||
val secretKey = maybeUserSecretKey() ?: return null
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val groupConfig = UserGroupsConfig.newInstance(secretKey)
|
||||
val allOpenGroups = storage.getAllOpenGroups().values.mapNotNull { openGroup ->
|
||||
val (baseUrl, room, pubKey) = BaseCommunityInfo.parseFullUrl(openGroup.joinURL) ?: return@mapNotNull null
|
||||
val pubKeyHex = Hex.toStringCondensed(pubKey)
|
||||
val baseInfo = BaseCommunityInfo(baseUrl, room, pubKeyHex)
|
||||
val threadId = storage.getThreadId(openGroup) ?: return@mapNotNull null
|
||||
val isPinned = storage.isPinned(threadId)
|
||||
GroupInfo.CommunityGroupInfo(baseInfo, if (isPinned) 1 else 0)
|
||||
}
|
||||
|
||||
val allLgc = storage.getAllGroups().filter { it.isClosedGroup }.mapNotNull { group ->
|
||||
val groupPublicKey = GroupUtil.doubleDecodeGroupID(group.encodedId).toHexString()
|
||||
val encryptionKeyPair = storage.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) ?: return@mapNotNull null
|
||||
val threadId = storage.getThreadId(group.encodedId)
|
||||
val isPinned = threadId?.let { storage.isPinned(threadId) } ?: false
|
||||
val sessionId = GroupUtil.doubleEncodeGroupID(group.getId())
|
||||
val admins = group.admins.map { it.serialize() to true }.toMap()
|
||||
val members = group.members.filterNot { it.serialize() !in admins.keys }.map { it.serialize() to false }.toMap()
|
||||
val encPub = storage.getClosedGroupEncryptionKeyPairs(group.)
|
||||
GroupInfo.LegacyGroupInfo(
|
||||
sessionId = sessionId,
|
||||
name = group.title,
|
||||
members = admins + members,
|
||||
hidden = threadId == null,
|
||||
priority = if (isPinned) 1 else 0,
|
||||
encPubKey = encryptionKeyPair.publicKey.serialize(),
|
||||
encSecKey = encryptionKeyPair.privateKey.serialize()
|
||||
)
|
||||
}
|
||||
|
||||
(allOpenGroups + allLgc).forEach { groupInfo ->
|
||||
groupConfig.set(groupInfo)
|
||||
}
|
||||
val dump = groupConfig.dump()
|
||||
groupConfig.free()
|
||||
return dump
|
||||
}
|
||||
|
||||
}
|
@ -3,25 +3,6 @@
|
||||
|
||||
#pragma clang diagnostic push
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_Conversation_00024Community_00024Companion_parseFullUrl(
|
||||
JNIEnv *env, jobject thiz, jstring full_url) {
|
||||
auto bytes = env->GetStringUTFChars(full_url, nullptr);
|
||||
auto [base, room, pk] = session::config::convo::community::parse_full_url(bytes);
|
||||
env->ReleaseStringUTFChars(full_url, bytes);
|
||||
|
||||
jclass clazz = env->FindClass("kotlin/Triple");
|
||||
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V");
|
||||
|
||||
auto base_j = env->NewStringUTF(base.data());
|
||||
auto room_j = env->NewStringUTF(room.data());
|
||||
auto pk_jbytes = util::bytes_from_ustring(env, pk);
|
||||
|
||||
jobject triple = env->NewObject(clazz, constructor, base_j, room_j, pk_jbytes);
|
||||
return triple;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
JNIEXPORT jobject JNICALL
|
||||
|
@ -110,6 +110,22 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getOrConstructLega
|
||||
return serialize_legacy_group_info(env, group);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_set__Lnetwork_loki_messenger_libsession_1util_util_GroupInfo_2(
|
||||
JNIEnv *env, jobject thiz, jobject group_info) {
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto communityInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
|
||||
auto legacyInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
|
||||
if (env->GetObjectClass(group_info) == communityInfo) {
|
||||
auto deserialized = deserialize_community_info(env, group_info);
|
||||
conf->set(deserialized);
|
||||
} else if (env->GetObjectClass(group_info) == legacyInfo) {
|
||||
auto deserialized = deserialize_legacy_group_info(env, group_info);
|
||||
conf->set(deserialized);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_set__Lnetwork_loki_messenger_libsession_1util_util_GroupInfo_CommunityGroupInfo_2(
|
||||
|
@ -102,3 +102,21 @@ Java_network_loki_messenger_libsession_1util_util_Sodium_ed25519PkToCurve25519(J
|
||||
jbyteArray curve_pk_jarray = util::bytes_from_ustring(env, session::ustring_view {curve_pk.data(), curve_pk.size()});
|
||||
return curve_pk_jarray;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_BaseCommunityInfo_00024Companion_parseFullUrl(
|
||||
JNIEnv *env, jobject thiz, jstring full_url) {
|
||||
auto bytes = env->GetStringUTFChars(full_url, nullptr);
|
||||
auto [base, room, pk] = session::config::community::parse_full_url(bytes);
|
||||
env->ReleaseStringUTFChars(full_url, bytes);
|
||||
|
||||
jclass clazz = env->FindClass("kotlin/Triple");
|
||||
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V");
|
||||
|
||||
auto base_j = env->NewStringUTF(base.data());
|
||||
auto room_j = env->NewStringUTF(room.data());
|
||||
auto pk_jbytes = util::bytes_from_ustring(env, pk);
|
||||
|
||||
jobject triple = env->NewObject(clazz, constructor, base_j, room_j, pk_jbytes);
|
||||
return triple;
|
||||
}
|
@ -155,6 +155,7 @@ class UserGroupsConfig(pointer: Long): ConfigBase(pointer) {
|
||||
external fun getLegacyGroupInfo(sessionId: String): GroupInfo.LegacyGroupInfo?
|
||||
external fun getOrConstructCommunityInfo(baseUrl: String, room: String, pubKeyHex: String): GroupInfo.CommunityGroupInfo
|
||||
external fun getOrConstructLegacyGroupInfo(sessionId: String): GroupInfo.LegacyGroupInfo
|
||||
external fun set(groupInfo: GroupInfo)
|
||||
external fun set(communityInfo: GroupInfo.CommunityGroupInfo)
|
||||
external fun set(legacyGroupInfo: GroupInfo.LegacyGroupInfo)
|
||||
external fun erase(communityInfo: GroupInfo.CommunityGroupInfo)
|
||||
|
@ -1,3 +1,10 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
data class BaseCommunityInfo(val baseUrl: String, val room: String, val pubKeyHex: String)
|
||||
data class BaseCommunityInfo(val baseUrl: String, val room: String, val pubKeyHex: String) {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun parseFullUrl(fullUrl: String): Triple<String, String, ByteArray>?
|
||||
}
|
||||
}
|
@ -153,6 +153,7 @@ interface StorageProtocol {
|
||||
fun getOrCreateThreadIdFor(address: Address): Long
|
||||
fun getOrCreateThreadIdFor(publicKey: String, groupPublicKey: String?, openGroupID: String?): Long
|
||||
fun getThreadId(publicKeyOrOpenGroupID: String): Long?
|
||||
fun getThreadId(openGroup: OpenGroup): Long?
|
||||
fun getThreadId(address: Address): Long?
|
||||
fun getThreadId(recipient: Recipient): Long?
|
||||
fun getThreadIdForMms(mmsId: Long): Long
|
||||
@ -160,6 +161,8 @@ interface StorageProtocol {
|
||||
fun trimThread(threadID: Long, threadLimit: Int)
|
||||
fun trimThreadBefore(threadID: Long, timestamp: Long)
|
||||
fun getMessageCount(threadID: Long): Long
|
||||
fun setPinned(threadID: Long, isPinned: Boolean)
|
||||
fun isPinned(threadID: Long): Boolean
|
||||
|
||||
// Contacts
|
||||
fun getContactWithSessionID(sessionID: String): Contact?
|
||||
|
Loading…
Reference in New Issue
Block a user