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:
0x330a
2023-03-06 15:27:06 +11:00
parent 2a701f2cc3
commit 66c997dfb2
9 changed files with 136 additions and 23 deletions

View File

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

View File

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

View File

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