mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-25 11:07:38 +00:00
feat: finish most wrappers and compile issues, start new closed group compose code
This commit is contained in:
@@ -19,7 +19,7 @@ object MentionManagerUtilities {
|
|||||||
}
|
}
|
||||||
recipient.address.isClosedGroup -> {
|
recipient.address.isClosedGroup -> {
|
||||||
val members = storage.getMembers(recipient.address.serialize())
|
val members = storage.getMembers(recipient.address.serialize())
|
||||||
TODO("Fix when compile errors are dealt with for recipient closed groups")
|
result.addAll(members.map { it.sessionId })
|
||||||
}
|
}
|
||||||
recipient.address.isOpenGroup -> {
|
recipient.address.isOpenGroup -> {
|
||||||
val messageDatabase = DatabaseComponent.get(context).mmsSmsDatabase()
|
val messageDatabase = DatabaseComponent.get(context).mmsSmsDatabase()
|
||||||
|
@@ -10,7 +10,7 @@ import network.loki.messenger.libsession_util.Contacts
|
|||||||
import network.loki.messenger.libsession_util.ConversationVolatileConfig
|
import network.loki.messenger.libsession_util.ConversationVolatileConfig
|
||||||
import network.loki.messenger.libsession_util.GroupInfoConfig
|
import network.loki.messenger.libsession_util.GroupInfoConfig
|
||||||
import network.loki.messenger.libsession_util.GroupKeysConfig
|
import network.loki.messenger.libsession_util.GroupKeysConfig
|
||||||
import network.loki.messenger.libsession_util.GroupMemberConfig
|
import network.loki.messenger.libsession_util.GroupMembersConfig
|
||||||
import network.loki.messenger.libsession_util.UserGroupsConfig
|
import network.loki.messenger.libsession_util.UserGroupsConfig
|
||||||
import network.loki.messenger.libsession_util.UserProfile
|
import network.loki.messenger.libsession_util.UserProfile
|
||||||
import network.loki.messenger.libsession_util.util.BaseCommunityInfo
|
import network.loki.messenger.libsession_util.util.BaseCommunityInfo
|
||||||
@@ -94,6 +94,7 @@ import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
|||||||
import org.thoughtcrime.securesms.util.SessionMetaProtocol
|
import org.thoughtcrime.securesms.util.SessionMetaProtocol
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import network.loki.messenger.libsession_util.util.Contact as LibSessionContact
|
import network.loki.messenger.libsession_util.util.Contact as LibSessionContact
|
||||||
|
import network.loki.messenger.libsession_util.util.GroupMember as LibSessionGroupMember
|
||||||
|
|
||||||
open class Storage(context: Context, helper: SQLCipherOpenHelper, private val configFactory: ConfigFactory) : Database(context, helper), StorageProtocol,
|
open class Storage(context: Context, helper: SQLCipherOpenHelper, private val configFactory: ConfigFactory) : Database(context, helper), StorageProtocol,
|
||||||
ThreadDatabase.ConversationThreadUpdateListener {
|
ThreadDatabase.ConversationThreadUpdateListener {
|
||||||
@@ -460,9 +461,9 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
|||||||
is Contacts -> updateContacts(forConfigObject)
|
is Contacts -> updateContacts(forConfigObject)
|
||||||
is ConversationVolatileConfig -> updateConvoVolatile(forConfigObject)
|
is ConversationVolatileConfig -> updateConvoVolatile(forConfigObject)
|
||||||
is UserGroupsConfig -> updateUserGroups(forConfigObject)
|
is UserGroupsConfig -> updateUserGroups(forConfigObject)
|
||||||
is GroupInfoConfig -> TODO()
|
is GroupInfoConfig -> updateGroupInfo(forConfigObject)
|
||||||
is GroupKeysConfig -> TODO()
|
is GroupKeysConfig -> updateGroupKeys(forConfigObject)
|
||||||
is GroupMemberConfig -> TODO()
|
is GroupMembersConfig -> updateGroupMembers(forConfigObject)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -499,6 +500,19 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateGroupInfo(groupInfoConfig: GroupInfoConfig) {
|
||||||
|
val threadId = getOrCreateThreadIdFor(Address.fromSerialized(groupInfoConfig.id().hexString()))
|
||||||
|
// TODO: handle deleted group, handle delete attachment / message before a certain time
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateGroupKeys(groupKeys: GroupKeysConfig) {
|
||||||
|
// TODO: update something here?
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateGroupMembers(groupMembers: GroupMembersConfig) {
|
||||||
|
// TODO: maybe clear out some contacts or something?
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateContacts(contacts: Contacts) {
|
private fun updateContacts(contacts: Contacts) {
|
||||||
val extracted = contacts.all().toList()
|
val extracted = contacts.all().toList()
|
||||||
addLibSessionContacts(extracted)
|
addLibSessionContacts(extracted)
|
||||||
@@ -1030,10 +1044,8 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMembers(groupPublicKey: String): List<GroupMember> {
|
override fun getMembers(groupPublicKey: String): List<LibSessionGroupMember> =
|
||||||
val groups = configFactory.userGroups ?: return emptyList()
|
configFactory.groupMemberConfig(SessionId.from(groupPublicKey))?.all()?.toList() ?: emptyList()
|
||||||
TODO("Add group specific configs")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setServerCapabilities(server: String, capabilities: List<String>) {
|
override fun setServerCapabilities(server: String, capabilities: List<String>) {
|
||||||
return DatabaseComponent.get(context).lokiAPIDatabase().setServerCapabilities(server, capabilities)
|
return DatabaseComponent.get(context).lokiAPIDatabase().setServerCapabilities(server, capabilities)
|
||||||
@@ -1603,8 +1615,8 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
|||||||
}
|
}
|
||||||
getAllContacts().forEach { contact ->
|
getAllContacts().forEach { contact ->
|
||||||
val sessionId = SessionId(contact.sessionID)
|
val sessionId = SessionId(contact.sessionID)
|
||||||
if (sessionId.prefix == IdPrefix.STANDARD && SodiumUtilities.sessionId(sessionId.hexString, blindedId, serverPublicKey)) {
|
if (sessionId.prefix == IdPrefix.STANDARD && SodiumUtilities.sessionId(sessionId.hexString(), blindedId, serverPublicKey)) {
|
||||||
val contactMapping = mapping.copy(sessionId = sessionId.hexString)
|
val contactMapping = mapping.copy(sessionId = sessionId.hexString())
|
||||||
db.addBlindedIdMapping(contactMapping)
|
db.addBlindedIdMapping(contactMapping)
|
||||||
return contactMapping
|
return contactMapping
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,9 @@ import android.os.Trace
|
|||||||
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.ConversationVolatileConfig
|
||||||
|
import network.loki.messenger.libsession_util.GroupInfoConfig
|
||||||
|
import network.loki.messenger.libsession_util.GroupKeysConfig
|
||||||
|
import network.loki.messenger.libsession_util.GroupMembersConfig
|
||||||
import network.loki.messenger.libsession_util.UserGroupsConfig
|
import network.loki.messenger.libsession_util.UserGroupsConfig
|
||||||
import network.loki.messenger.libsession_util.UserProfile
|
import network.loki.messenger.libsession_util.UserProfile
|
||||||
import org.session.libsession.snode.SnodeAPI
|
import org.session.libsession.snode.SnodeAPI
|
||||||
@@ -12,7 +15,9 @@ import org.session.libsession.utilities.ConfigFactoryProtocol
|
|||||||
import org.session.libsession.utilities.ConfigFactoryUpdateListener
|
import org.session.libsession.utilities.ConfigFactoryUpdateListener
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage
|
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage
|
||||||
|
import org.session.libsignal.utilities.Hex
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.session.libsignal.utilities.SessionId
|
||||||
import org.thoughtcrime.securesms.database.ConfigDatabase
|
import org.thoughtcrime.securesms.database.ConfigDatabase
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
|
||||||
import org.thoughtcrime.securesms.groups.GroupManager
|
import org.thoughtcrime.securesms.groups.GroupManager
|
||||||
@@ -61,7 +66,7 @@ class ConfigFactory(
|
|||||||
listeners -= listener
|
listeners -= listener
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <T> synchronizedWithLog(lock: Any, body: ()->T): T {
|
private inline fun <T> synchronizedWithLog(lock: Any, body: () -> T): T {
|
||||||
Trace.beginSection("synchronizedWithLog")
|
Trace.beginSection("synchronizedWithLog")
|
||||||
val result = synchronized(lock) {
|
val result = synchronized(lock) {
|
||||||
body()
|
body()
|
||||||
@@ -72,7 +77,11 @@ class ConfigFactory(
|
|||||||
|
|
||||||
override val user: UserProfile?
|
override val user: UserProfile?
|
||||||
get() = synchronizedWithLog(userLock) {
|
get() = synchronizedWithLog(userLock) {
|
||||||
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
|
if (!ConfigBase.isNewConfigEnabled(
|
||||||
|
isConfigForcedOn,
|
||||||
|
SnodeAPI.nowWithOffset
|
||||||
|
)
|
||||||
|
) return null
|
||||||
if (_userConfig == null) {
|
if (_userConfig == null) {
|
||||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
||||||
val userDump = configDatabase.retrieveConfigAndHashes(
|
val userDump = configDatabase.retrieveConfigAndHashes(
|
||||||
@@ -92,7 +101,11 @@ class ConfigFactory(
|
|||||||
|
|
||||||
override val contacts: Contacts?
|
override val contacts: Contacts?
|
||||||
get() = synchronizedWithLog(contactsLock) {
|
get() = synchronizedWithLog(contactsLock) {
|
||||||
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
|
if (!ConfigBase.isNewConfigEnabled(
|
||||||
|
isConfigForcedOn,
|
||||||
|
SnodeAPI.nowWithOffset
|
||||||
|
)
|
||||||
|
) return null
|
||||||
if (_contacts == null) {
|
if (_contacts == null) {
|
||||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
||||||
val contactsDump = configDatabase.retrieveConfigAndHashes(
|
val contactsDump = configDatabase.retrieveConfigAndHashes(
|
||||||
@@ -112,7 +125,11 @@ class ConfigFactory(
|
|||||||
|
|
||||||
override val convoVolatile: ConversationVolatileConfig?
|
override val convoVolatile: ConversationVolatileConfig?
|
||||||
get() = synchronizedWithLog(convoVolatileLock) {
|
get() = synchronizedWithLog(convoVolatileLock) {
|
||||||
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
|
if (!ConfigBase.isNewConfigEnabled(
|
||||||
|
isConfigForcedOn,
|
||||||
|
SnodeAPI.nowWithOffset
|
||||||
|
)
|
||||||
|
) return null
|
||||||
if (_convoVolatileConfig == null) {
|
if (_convoVolatileConfig == null) {
|
||||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
||||||
val convoDump = configDatabase.retrieveConfigAndHashes(
|
val convoDump = configDatabase.retrieveConfigAndHashes(
|
||||||
@@ -133,7 +150,11 @@ class ConfigFactory(
|
|||||||
|
|
||||||
override val userGroups: UserGroupsConfig?
|
override val userGroups: UserGroupsConfig?
|
||||||
get() = synchronizedWithLog(userGroupsLock) {
|
get() = synchronizedWithLog(userGroupsLock) {
|
||||||
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
|
if (!ConfigBase.isNewConfigEnabled(
|
||||||
|
isConfigForcedOn,
|
||||||
|
SnodeAPI.nowWithOffset
|
||||||
|
)
|
||||||
|
) return null
|
||||||
if (_userGroups == null) {
|
if (_userGroups == null) {
|
||||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
||||||
val userGroupsDump = configDatabase.retrieveConfigAndHashes(
|
val userGroupsDump = configDatabase.retrieveConfigAndHashes(
|
||||||
@@ -151,6 +172,61 @@ class ConfigFactory(
|
|||||||
_userGroups
|
_userGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getGroupAuthInfo(groupSessionId: SessionId) = userGroups?.getClosedGroup(groupSessionId.hexString())?.let {
|
||||||
|
it.adminKey to it.authData
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun groupInfoConfig(groupSessionId: SessionId): GroupInfoConfig? = getGroupAuthInfo(groupSessionId)?.let { (sk, _) ->
|
||||||
|
// get any potential initial dumps
|
||||||
|
val dump = configDatabase.retrieveConfigAndHashes(
|
||||||
|
SharedConfigMessage.Kind.CLOSED_GROUP_INFO.name,
|
||||||
|
groupSessionId.hexString()
|
||||||
|
) ?: byteArrayOf()
|
||||||
|
|
||||||
|
GroupInfoConfig.newInstance(Hex.fromStringCondensed(groupSessionId.publicKey), sk, dump)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun groupKeysConfig(groupSessionId: SessionId): GroupKeysConfig? = getGroupAuthInfo(groupSessionId)?.let { (sk, _) ->
|
||||||
|
// Get the user info or return early
|
||||||
|
val (userSk, _) = maybeGetUserInfo() ?: return@let null
|
||||||
|
|
||||||
|
// Get the group info or return early
|
||||||
|
val info = groupInfoConfig(groupSessionId) ?: return@let null
|
||||||
|
|
||||||
|
// Get the group members or return early
|
||||||
|
val members = groupMemberConfig(groupSessionId) ?: return@let null
|
||||||
|
|
||||||
|
// Get the dump or empty
|
||||||
|
val dump = configDatabase.retrieveConfigAndHashes(
|
||||||
|
SharedConfigMessage.Kind.ENCRYPTION_KEYS.name,
|
||||||
|
groupSessionId.hexString()
|
||||||
|
) ?: byteArrayOf()
|
||||||
|
|
||||||
|
// Put it all together
|
||||||
|
GroupKeysConfig.newInstance(
|
||||||
|
userSk,
|
||||||
|
Hex.fromStringCondensed(groupSessionId.publicKey),
|
||||||
|
sk,
|
||||||
|
dump,
|
||||||
|
info,
|
||||||
|
members
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun groupMemberConfig(groupSessionId: SessionId): GroupMembersConfig? = getGroupAuthInfo(groupSessionId)?.let { (sk, auth) ->
|
||||||
|
// Get initial dump if we have one
|
||||||
|
val dump = configDatabase.retrieveConfigAndHashes(
|
||||||
|
SharedConfigMessage.Kind.CLOSED_GROUP_MEMBERS.name,
|
||||||
|
groupSessionId.hexString()
|
||||||
|
) ?: byteArrayOf()
|
||||||
|
|
||||||
|
GroupMembersConfig.newInstance(
|
||||||
|
Hex.fromStringCondensed(groupSessionId.publicKey),
|
||||||
|
sk,
|
||||||
|
dump
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getUserConfigs(): List<ConfigBase> =
|
override fun getUserConfigs(): List<ConfigBase> =
|
||||||
listOfNotNull(user, contacts, convoVolatile, userGroups)
|
listOfNotNull(user, contacts, convoVolatile, userGroups)
|
||||||
|
|
||||||
@@ -158,13 +234,23 @@ class ConfigFactory(
|
|||||||
private fun persistUserConfigDump(timestamp: Long) = synchronized(userLock) {
|
private fun persistUserConfigDump(timestamp: Long) = synchronized(userLock) {
|
||||||
val dumped = user?.dump() ?: return
|
val dumped = user?.dump() ?: return
|
||||||
val (_, publicKey) = maybeGetUserInfo() ?: return
|
val (_, publicKey) = maybeGetUserInfo() ?: return
|
||||||
configDatabase.storeConfig(SharedConfigMessage.Kind.USER_PROFILE.name, publicKey, dumped, timestamp)
|
configDatabase.storeConfig(
|
||||||
|
SharedConfigMessage.Kind.USER_PROFILE.name,
|
||||||
|
publicKey,
|
||||||
|
dumped,
|
||||||
|
timestamp
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun persistContactsConfigDump(timestamp: Long) = synchronized(contactsLock) {
|
private fun persistContactsConfigDump(timestamp: Long) = synchronized(contactsLock) {
|
||||||
val dumped = contacts?.dump() ?: return
|
val dumped = contacts?.dump() ?: return
|
||||||
val (_, publicKey) = maybeGetUserInfo() ?: return
|
val (_, publicKey) = maybeGetUserInfo() ?: return
|
||||||
configDatabase.storeConfig(SharedConfigMessage.Kind.CONTACTS.name, publicKey, dumped, timestamp)
|
configDatabase.storeConfig(
|
||||||
|
SharedConfigMessage.Kind.CONTACTS.name,
|
||||||
|
publicKey,
|
||||||
|
dumped,
|
||||||
|
timestamp
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun persistConvoVolatileConfigDump(timestamp: Long) = synchronized(convoVolatileLock) {
|
private fun persistConvoVolatileConfigDump(timestamp: Long) = synchronized(convoVolatileLock) {
|
||||||
@@ -181,7 +267,12 @@ class ConfigFactory(
|
|||||||
private fun persistUserGroupsConfigDump(timestamp: Long) = synchronized(userGroupsLock) {
|
private fun persistUserGroupsConfigDump(timestamp: Long) = synchronized(userGroupsLock) {
|
||||||
val dumped = userGroups?.dump() ?: return
|
val dumped = userGroups?.dump() ?: return
|
||||||
val (_, publicKey) = maybeGetUserInfo() ?: return
|
val (_, publicKey) = maybeGetUserInfo() ?: return
|
||||||
configDatabase.storeConfig(SharedConfigMessage.Kind.GROUPS.name, publicKey, dumped, timestamp)
|
configDatabase.storeConfig(
|
||||||
|
SharedConfigMessage.Kind.GROUPS.name,
|
||||||
|
publicKey,
|
||||||
|
dumped,
|
||||||
|
timestamp
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun persist(forConfigObject: ConfigBase, timestamp: Long) {
|
override fun persist(forConfigObject: ConfigBase, timestamp: Long) {
|
||||||
@@ -214,23 +305,21 @@ class ConfigFactory(
|
|||||||
if (openGroupId != null) {
|
if (openGroupId != null) {
|
||||||
val userGroups = userGroups ?: return false
|
val userGroups = userGroups ?: return false
|
||||||
val threadId = GroupManager.getOpenGroupThreadID(openGroupId, context)
|
val threadId = GroupManager.getOpenGroupThreadID(openGroupId, context)
|
||||||
val openGroup = get(context).lokiThreadDatabase().getOpenGroupChat(threadId) ?: return false
|
val openGroup =
|
||||||
|
get(context).lokiThreadDatabase().getOpenGroupChat(threadId) ?: return false
|
||||||
|
|
||||||
// Not handling the `hidden` behaviour for communities so just indicate the existence
|
// Not handling the `hidden` behaviour for communities so just indicate the existence
|
||||||
return (userGroups.getCommunityInfo(openGroup.server, openGroup.room) != null)
|
return (userGroups.getCommunityInfo(openGroup.server, openGroup.room) != null)
|
||||||
}
|
} else if (groupPublicKey != null) {
|
||||||
else if (groupPublicKey != null) {
|
|
||||||
val userGroups = userGroups ?: return false
|
val userGroups = userGroups ?: return false
|
||||||
|
|
||||||
// Not handling the `hidden` behaviour for legacy groups so just indicate the existence
|
// Not handling the `hidden` behaviour for legacy groups so just indicate the existence
|
||||||
return (userGroups.getLegacyGroupInfo(groupPublicKey) != null)
|
return (userGroups.getLegacyGroupInfo(groupPublicKey) != null)
|
||||||
}
|
} else if (publicKey == userPublicKey) {
|
||||||
else if (publicKey == userPublicKey) {
|
|
||||||
val user = user ?: return false
|
val user = user ?: return false
|
||||||
|
|
||||||
return (!visibleOnly || user.getNtsPriority() != ConfigBase.PRIORITY_HIDDEN)
|
return (!visibleOnly || user.getNtsPriority() != ConfigBase.PRIORITY_HIDDEN)
|
||||||
}
|
} else if (publicKey != null) {
|
||||||
else if (publicKey != null) {
|
|
||||||
val contacts = contacts ?: return false
|
val contacts = contacts ?: return false
|
||||||
val targetContact = contacts.get(publicKey) ?: return false
|
val targetContact = contacts.get(publicKey) ?: return false
|
||||||
|
|
||||||
@@ -240,12 +329,18 @@ class ConfigFactory(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canPerformChange(variant: String, publicKey: String, changeTimestampMs: Long): Boolean {
|
override fun canPerformChange(
|
||||||
|
variant: String,
|
||||||
|
publicKey: String,
|
||||||
|
changeTimestampMs: Long
|
||||||
|
): Boolean {
|
||||||
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return true
|
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return true
|
||||||
|
|
||||||
val lastUpdateTimestampMs = configDatabase.retrieveConfigLastUpdateTimestamp(variant, publicKey)
|
val lastUpdateTimestampMs =
|
||||||
|
configDatabase.retrieveConfigLastUpdateTimestamp(variant, publicKey)
|
||||||
|
|
||||||
// Ensure the change occurred after the last config message was handled (minus the buffer period)
|
// Ensure the change occurred after the last config message was handled (minus the buffer period)
|
||||||
return (changeTimestampMs >= (lastUpdateTimestampMs - ConfigFactory.configChangeBufferPeriod))
|
return (changeTimestampMs >= (lastUpdateTimestampMs - ConfigFactory.configChangeBufferPeriod))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -34,16 +34,9 @@ object ClosedGroupManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ConfigFactory.removeLegacyGroup(group: GroupRecord): Boolean {
|
|
||||||
val groups = userGroups ?: return false
|
|
||||||
if (!group.isClosedGroup) return false
|
|
||||||
val groupPublicKey = GroupUtil.doubleEncodeGroupID(group.getId())
|
|
||||||
return groups.eraseLegacyGroup(groupPublicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConfigFactory.updateLegacyGroup(groupRecipientSettings: Recipient.RecipientSettings, group: GroupRecord) {
|
fun ConfigFactory.updateLegacyGroup(groupRecipientSettings: Recipient.RecipientSettings, group: GroupRecord) {
|
||||||
val groups = userGroups ?: return
|
val groups = userGroups ?: return
|
||||||
if (!group.isClosedGroup) return
|
if (!group.isLegacyClosedGroup) return
|
||||||
val storage = MessagingModuleConfiguration.shared.storage
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
val threadId = storage.getThreadId(group.encodedId) ?: return
|
val threadId = storage.getThreadId(group.encodedId) ?: return
|
||||||
val groupPublicKey = GroupUtil.doubleEncodeGroupID(group.getId())
|
val groupPublicKey = GroupUtil.doubleEncodeGroupID(group.getId())
|
||||||
|
@@ -7,6 +7,13 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
@@ -21,6 +28,7 @@ import nl.komponents.kovenant.ui.successUi
|
|||||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||||
import org.session.libsession.messaging.sending_receiving.groupSizeLimit
|
import org.session.libsession.messaging.sending_receiving.groupSizeLimit
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
|
import org.session.libsession.utilities.Contact
|
||||||
import org.session.libsession.utilities.Device
|
import org.session.libsession.utilities.Device
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
@@ -49,8 +57,11 @@ class CreateGroupFragment : Fragment() {
|
|||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
binding = FragmentCreateGroupBinding.inflate(inflater)
|
return ComposeView(requireContext()).apply {
|
||||||
return binding.root
|
setContent {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
@@ -122,3 +133,14 @@ class CreateGroupFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MemberList(contacts: List<Contact>, modifier: Modifier = Modifier) {
|
||||||
|
Avatar
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun ClosedGroupPreview() {
|
||||||
|
MemberList(contacts = emptyList(), modifier = Modifier.fillMaxWidth())
|
||||||
|
}
|
@@ -144,7 +144,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
intent.putExtra(ConversationActivityV2.ADDRESS, Address.fromSerialized(address))
|
intent.putExtra(ConversationActivityV2.ADDRESS, Address.fromSerialized(address))
|
||||||
push(intent)
|
push(intent)
|
||||||
}
|
}
|
||||||
is GlobalSearchAdapter.Model.GroupConversation -> {
|
is GlobalSearchAdapter.Model.LegacyGroupConversation -> {
|
||||||
val groupAddress = Address.fromSerialized(model.groupRecord.encodedId)
|
val groupAddress = Address.fromSerialized(model.groupRecord.encodedId)
|
||||||
val threadId = threadDb.getThreadIdIfExistsFor(Recipient.from(this, groupAddress, false))
|
val threadId = threadDb.getThreadIdIfExistsFor(Recipient.from(this, groupAddress, false))
|
||||||
if (threadId >= 0) {
|
if (threadId >= 0) {
|
||||||
@@ -257,7 +257,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
globalSearchViewModel.result.collect { result ->
|
globalSearchViewModel.result.collect { result ->
|
||||||
val currentUserPublicKey = publicKey
|
val currentUserPublicKey = publicKey
|
||||||
val contactAndGroupList = result.contacts.map { GlobalSearchAdapter.Model.Contact(it) } +
|
val contactAndGroupList = result.contacts.map { GlobalSearchAdapter.Model.Contact(it) } +
|
||||||
result.threads.map { GlobalSearchAdapter.Model.GroupConversation(it) }
|
result.threads.map { GlobalSearchAdapter.Model.LegacyGroupConversation(it) }
|
||||||
|
|
||||||
val contactResults = contactAndGroupList.toMutableList()
|
val contactResults = contactAndGroupList.toMutableList()
|
||||||
|
|
||||||
@@ -642,14 +642,18 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
// Cancel any outstanding jobs
|
// Cancel any outstanding jobs
|
||||||
DatabaseComponent.get(context).sessionJobDatabase().cancelPendingMessageSendJobs(threadID)
|
DatabaseComponent.get(context).sessionJobDatabase().cancelPendingMessageSendJobs(threadID)
|
||||||
// Send a leave group message if this is an active closed group
|
// Send a leave group message if this is an active closed group
|
||||||
if (recipient.address.isClosedGroup && DatabaseComponent.get(context).groupDatabase().isActive(recipient.address.toGroupString())) {
|
if (recipient.address.isLegacyClosedGroup && DatabaseComponent.get(context).groupDatabase().isActive(recipient.address.toGroupString())) {
|
||||||
try {
|
try {
|
||||||
GroupUtil.doubleDecodeGroupID(recipient.address.toString()).toHexString()
|
GroupUtil.doubleDecodeGroupID(recipient.address.toString()).toHexString()
|
||||||
.takeIf(DatabaseComponent.get(context).lokiAPIDatabase()::isClosedGroup)
|
.takeIf(DatabaseComponent.get(context).lokiAPIDatabase()::isClosedGroup)
|
||||||
?.let { MessageSender.explicitLeave(it, false) }
|
?.let { MessageSender.explicitLeave(it, false) }
|
||||||
} catch (_: IOException) {
|
} catch (e: IOException) {
|
||||||
|
Log.e("Loki", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (recipient.address.isClosedGroup) {
|
||||||
|
TODO("Implement leaving / deleting a new closed group conversation")
|
||||||
|
}
|
||||||
// Delete the conversation
|
// Delete the conversation
|
||||||
val v2OpenGroup = DatabaseComponent.get(context).lokiThreadDatabase().getOpenGroupChat(threadID)
|
val v2OpenGroup = DatabaseComponent.get(context).lokiThreadDatabase().getOpenGroupChat(threadID)
|
||||||
if (v2OpenGroup != null) {
|
if (v2OpenGroup != null) {
|
||||||
|
@@ -9,9 +9,10 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ViewGlobalSearchHeaderBinding
|
import network.loki.messenger.databinding.ViewGlobalSearchHeaderBinding
|
||||||
import network.loki.messenger.databinding.ViewGlobalSearchResultBinding
|
import network.loki.messenger.databinding.ViewGlobalSearchResultBinding
|
||||||
|
import network.loki.messenger.libsession_util.util.GroupInfo
|
||||||
import org.session.libsession.utilities.GroupRecord
|
import org.session.libsession.utilities.GroupRecord
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import org.session.libsignal.utilities.SessionId
|
||||||
import org.thoughtcrime.securesms.search.model.MessageResult
|
import org.thoughtcrime.securesms.search.model.MessageResult
|
||||||
import java.security.InvalidParameterException
|
import java.security.InvalidParameterException
|
||||||
import org.session.libsession.messaging.contacts.Contact as ContactModel
|
import org.session.libsession.messaging.contacts.Contact as ContactModel
|
||||||
@@ -98,7 +99,7 @@ class GlobalSearchAdapter (private val modelCallback: (Model)->Unit): RecyclerVi
|
|||||||
fun bind(query: String, model: Model) {
|
fun bind(query: String, model: Model) {
|
||||||
binding.searchResultProfilePicture.recycle()
|
binding.searchResultProfilePicture.recycle()
|
||||||
when (model) {
|
when (model) {
|
||||||
is Model.GroupConversation -> bindModel(query, model)
|
is Model.LegacyGroupConversation -> bindModel(query, model)
|
||||||
is Model.Contact -> bindModel(query, model)
|
is Model.Contact -> bindModel(query, model)
|
||||||
is Model.Message -> bindModel(query, model)
|
is Model.Message -> bindModel(query, model)
|
||||||
is Model.SavedMessages -> bindModel(model)
|
is Model.SavedMessages -> bindModel(model)
|
||||||
@@ -119,7 +120,8 @@ class GlobalSearchAdapter (private val modelCallback: (Model)->Unit): RecyclerVi
|
|||||||
data class Header(@StringRes val title: Int) : Model()
|
data class Header(@StringRes val title: Int) : Model()
|
||||||
data class SavedMessages(val currentUserPublicKey: String): Model()
|
data class SavedMessages(val currentUserPublicKey: String): Model()
|
||||||
data class Contact(val contact: ContactModel) : Model()
|
data class Contact(val contact: ContactModel) : Model()
|
||||||
data class GroupConversation(val groupRecord: GroupRecord) : Model()
|
data class LegacyGroupConversation(val groupRecord: GroupRecord) : Model()
|
||||||
|
data class ClosedGroupConversation(val sessionId: SessionId)
|
||||||
data class Message(val messageResult: MessageResult, val unread: Int) : Model()
|
data class Message(val messageResult: MessageResult, val unread: Int) : Model()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@ import org.session.libsession.messaging.contacts.Contact
|
|||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.ContentView
|
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.ContentView
|
||||||
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.GroupConversation
|
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.LegacyGroupConversation
|
||||||
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.Header
|
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.Header
|
||||||
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.Message
|
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.Message
|
||||||
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.SavedMessages
|
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.SavedMessages
|
||||||
@@ -65,7 +65,7 @@ fun ContentView.bindQuery(query: String, model: GlobalSearchAdapter.Model) {
|
|||||||
binding.searchResultSubtitle.isVisible = true
|
binding.searchResultSubtitle.isVisible = true
|
||||||
binding.searchResultTitle.text = model.messageResult.conversationRecipient.toShortString()
|
binding.searchResultTitle.text = model.messageResult.conversationRecipient.toShortString()
|
||||||
}
|
}
|
||||||
is GroupConversation -> {
|
is LegacyGroupConversation -> {
|
||||||
binding.searchResultTitle.text = getHighlight(
|
binding.searchResultTitle.text = getHighlight(
|
||||||
query,
|
query,
|
||||||
model.groupRecord.title
|
model.groupRecord.title
|
||||||
@@ -86,10 +86,10 @@ private fun getHighlight(query: String?, toSearch: String): Spannable? {
|
|||||||
return SearchUtil.getHighlightedSpan(Locale.getDefault(), BoldStyleFactory, toSearch, query)
|
return SearchUtil.getHighlightedSpan(Locale.getDefault(), BoldStyleFactory, toSearch, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ContentView.bindModel(query: String?, model: GroupConversation) {
|
fun ContentView.bindModel(query: String?, model: LegacyGroupConversation) {
|
||||||
binding.searchResultProfilePicture.isVisible = true
|
binding.searchResultProfilePicture.isVisible = true
|
||||||
binding.searchResultSavedMessages.isVisible = false
|
binding.searchResultSavedMessages.isVisible = false
|
||||||
binding.searchResultSubtitle.isVisible = model.groupRecord.isClosedGroup
|
binding.searchResultSubtitle.isVisible = model.groupRecord.isLegacyClosedGroup
|
||||||
binding.searchResultTimestamp.isVisible = false
|
binding.searchResultTimestamp.isVisible = false
|
||||||
val threadRecipient = Recipient.from(binding.root.context, Address.fromSerialized(model.groupRecord.encodedId), false)
|
val threadRecipient = Recipient.from(binding.root.context, Address.fromSerialized(model.groupRecord.encodedId), false)
|
||||||
binding.searchResultProfilePicture.update(threadRecipient)
|
binding.searchResultProfilePicture.update(threadRecipient)
|
||||||
@@ -102,7 +102,7 @@ fun ContentView.bindModel(query: String?, model: GroupConversation) {
|
|||||||
val address = it.address.serialize()
|
val address = it.address.serialize()
|
||||||
it.name ?: "${address.take(4)}...${address.takeLast(4)}"
|
it.name ?: "${address.take(4)}...${address.takeLast(4)}"
|
||||||
}
|
}
|
||||||
if (model.groupRecord.isClosedGroup) {
|
if (model.groupRecord.isLegacyClosedGroup) {
|
||||||
binding.searchResultSubtitle.text = getHighlight(query, membersString)
|
binding.searchResultSubtitle.text = getHighlight(query, membersString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,11 +132,6 @@ fun ContentView.bindModel(query: String?, model: Message) {
|
|||||||
binding.searchResultProfilePicture.isVisible = true
|
binding.searchResultProfilePicture.isVisible = true
|
||||||
binding.searchResultSavedMessages.isVisible = false
|
binding.searchResultSavedMessages.isVisible = false
|
||||||
binding.searchResultTimestamp.isVisible = true
|
binding.searchResultTimestamp.isVisible = true
|
||||||
// val hasUnreads = model.unread > 0
|
|
||||||
// binding.unreadCountIndicator.isVisible = hasUnreads
|
|
||||||
// if (hasUnreads) {
|
|
||||||
// binding.unreadCountTextView.text = model.unread.toString()
|
|
||||||
// }
|
|
||||||
binding.searchResultTimestamp.text = DateUtils.getDisplayFormattedTimeSpanString(binding.root.context, Locale.getDefault(), model.messageResult.sentTimestampMs)
|
binding.searchResultTimestamp.text = DateUtils.getDisplayFormattedTimeSpanString(binding.root.context, Locale.getDefault(), model.messageResult.sentTimestampMs)
|
||||||
binding.searchResultProfilePicture.update(model.messageResult.conversationRecipient)
|
binding.searchResultProfilePicture.update(model.messageResult.conversationRecipient)
|
||||||
val textSpannable = SpannableStringBuilder()
|
val textSpannable = SpannableStringBuilder()
|
||||||
|
@@ -42,7 +42,6 @@ import com.goterl.lazysodium.utils.KeyPair;
|
|||||||
|
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup;
|
import org.session.libsession.messaging.open_groups.OpenGroup;
|
||||||
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
|
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
|
||||||
import org.session.libsession.messaging.utilities.SessionId;
|
|
||||||
import org.session.libsession.messaging.utilities.SodiumUtilities;
|
import org.session.libsession.messaging.utilities.SodiumUtilities;
|
||||||
import org.session.libsession.snode.SnodeAPI;
|
import org.session.libsession.snode.SnodeAPI;
|
||||||
import org.session.libsession.utilities.Address;
|
import org.session.libsession.utilities.Address;
|
||||||
@@ -52,6 +51,7 @@ import org.session.libsession.utilities.TextSecurePreferences;
|
|||||||
import org.session.libsession.utilities.recipients.Recipient;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.session.libsignal.utilities.IdPrefix;
|
import org.session.libsignal.utilities.IdPrefix;
|
||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
|
import org.session.libsignal.utilities.SessionId;
|
||||||
import org.session.libsignal.utilities.Util;
|
import org.session.libsignal.utilities.Util;
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.contacts.ContactUtil;
|
import org.thoughtcrime.securesms.contacts.ContactUtil;
|
||||||
@@ -555,7 +555,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
|
|||||||
if (openGroup != null && edKeyPair != null) {
|
if (openGroup != null && edKeyPair != null) {
|
||||||
KeyPair blindedKeyPair = SodiumUtilities.blindedKeyPair(openGroup.getPublicKey(), edKeyPair);
|
KeyPair blindedKeyPair = SodiumUtilities.blindedKeyPair(openGroup.getPublicKey(), edKeyPair);
|
||||||
if (blindedKeyPair != null) {
|
if (blindedKeyPair != null) {
|
||||||
return new SessionId(IdPrefix.BLINDED, blindedKeyPair.getPublicKey().getAsBytes()).getHexString();
|
return new SessionId(IdPrefix.BLINDED, blindedKeyPair.getPublicKey().getAsBytes()).hexString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@@ -9,11 +9,10 @@ import android.widget.TextView;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import org.session.libsession.messaging.utilities.SessionId;
|
import org.session.libsignal.utilities.SessionId;
|
||||||
import org.thoughtcrime.securesms.components.ProfilePictureView;
|
import org.thoughtcrime.securesms.components.ProfilePictureView;
|
||||||
import org.thoughtcrime.securesms.components.emoji.EmojiImageView;
|
import org.thoughtcrime.securesms.components.emoji.EmojiImageView;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageId;
|
import org.thoughtcrime.securesms.database.model.MessageId;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@@ -5,11 +5,11 @@ import network.loki.messenger.libsession_util.util.UserPic
|
|||||||
import org.session.libsession.messaging.contacts.Contact
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.messaging.jobs.JobQueue
|
import org.session.libsession.messaging.jobs.JobQueue
|
||||||
import org.session.libsession.messaging.jobs.RetrieveProfileAvatarJob
|
import org.session.libsession.messaging.jobs.RetrieveProfileAvatarJob
|
||||||
import org.session.libsession.messaging.utilities.SessionId
|
|
||||||
import org.session.libsession.utilities.SSKEnvironment
|
import org.session.libsession.utilities.SSKEnvironment
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.utilities.IdPrefix
|
import org.session.libsignal.utilities.IdPrefix
|
||||||
|
import org.session.libsignal.utilities.SessionId
|
||||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.util
|
package org.thoughtcrime.securesms.util
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.provider.Telephony.Sms.Conversations
|
||||||
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.ConversationVolatileConfig
|
||||||
@@ -26,6 +27,7 @@ import org.session.libsession.utilities.WindowDebouncer
|
|||||||
import org.session.libsignal.crypto.ecc.DjbECPublicKey
|
import org.session.libsignal.crypto.ecc.DjbECPublicKey
|
||||||
import org.session.libsignal.utilities.Hex
|
import org.session.libsignal.utilities.Hex
|
||||||
import org.session.libsignal.utilities.IdPrefix
|
import org.session.libsignal.utilities.IdPrefix
|
||||||
|
import org.session.libsignal.utilities.SessionId
|
||||||
import org.session.libsignal.utilities.toHexString
|
import org.session.libsignal.utilities.toHexString
|
||||||
import org.thoughtcrime.securesms.database.GroupDatabase
|
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||||
@@ -199,6 +201,11 @@ object ConfigurationMessageUtilities {
|
|||||||
convoConfig.getOrConstructCommunity(base, room, pubKey)
|
convoConfig.getOrConstructCommunity(base, room, pubKey)
|
||||||
}
|
}
|
||||||
recipient.isClosedGroupRecipient -> {
|
recipient.isClosedGroupRecipient -> {
|
||||||
|
// It's probably safe to assume there will never be a case where new closed groups will ever be there before a dump is created...
|
||||||
|
// but just in case...
|
||||||
|
convoConfig.getOrConstructClosedGroup(recipient.address.serialize())
|
||||||
|
}
|
||||||
|
recipient.isLegacyClosedGroupRecipient -> {
|
||||||
val groupPublicKey = GroupUtil.doubleDecodeGroupId(recipient.address.serialize())
|
val groupPublicKey = GroupUtil.doubleDecodeGroupId(recipient.address.serialize())
|
||||||
convoConfig.getOrConstructLegacyGroup(groupPublicKey)
|
convoConfig.getOrConstructLegacyGroup(groupPublicKey)
|
||||||
}
|
}
|
||||||
@@ -241,7 +248,7 @@ object ConfigurationMessageUtilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val allLgc = storage.getAllGroups(includeInactive = false).filter {
|
val allLgc = storage.getAllGroups(includeInactive = false).filter {
|
||||||
it.isClosedGroup && it.isActive && it.members.size > 1
|
it.isLegacyClosedGroup && it.isActive && it.members.size > 1
|
||||||
}.mapNotNull { group ->
|
}.mapNotNull { group ->
|
||||||
val groupAddress = Address.fromSerialized(group.encodedId)
|
val groupAddress = Address.fromSerialized(group.encodedId)
|
||||||
val groupPublicKey = GroupUtil.doubleDecodeGroupID(groupAddress.serialize()).toHexString()
|
val groupPublicKey = GroupUtil.doubleDecodeGroupID(groupAddress.serialize()).toHexString()
|
||||||
@@ -252,7 +259,7 @@ object ConfigurationMessageUtilities {
|
|||||||
val admins = group.admins.map { it.serialize() to true }.toMap()
|
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 members = group.members.filterNot { it.serialize() !in admins.keys }.map { it.serialize() to false }.toMap()
|
||||||
GroupInfo.LegacyGroupInfo(
|
GroupInfo.LegacyGroupInfo(
|
||||||
sessionId = groupPublicKey,
|
sessionId = SessionId.from(groupPublicKey),
|
||||||
name = group.title,
|
name = group.title,
|
||||||
members = admins + members,
|
members = admins + members,
|
||||||
priority = if (isPinned) ConfigBase.PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE,
|
priority = if (isPinned) ConfigBase.PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE,
|
||||||
|
@@ -13,6 +13,8 @@ fun ConversationVolatileConfig.getConversationUnread(thread: ThreadRecord): Bool
|
|||||||
&& recipient.address.serialize().startsWith(IdPrefix.STANDARD.value)) {
|
&& recipient.address.serialize().startsWith(IdPrefix.STANDARD.value)) {
|
||||||
return getOneToOne(recipient.address.serialize())?.unread == true
|
return getOneToOne(recipient.address.serialize())?.unread == true
|
||||||
} else if (recipient.isClosedGroupRecipient) {
|
} else if (recipient.isClosedGroupRecipient) {
|
||||||
|
return getClosedGroup(recipient.address.serialize())?.unread == true
|
||||||
|
} else if (recipient.isLegacyClosedGroupRecipient) {
|
||||||
return getLegacyClosedGroup(GroupUtil.doubleDecodeGroupId(recipient.address.toGroupString()))?.unread == true
|
return getLegacyClosedGroup(GroupUtil.doubleDecodeGroupId(recipient.address.toGroupString()))?.unread == true
|
||||||
} else if (recipient.isOpenGroupRecipient) {
|
} else if (recipient.isOpenGroupRecipient) {
|
||||||
val openGroup = MessagingModuleConfiguration.shared.storage.getOpenGroup(thread.threadId) ?: return false
|
val openGroup = MessagingModuleConfiguration.shared.storage.getOpenGroup(thread.threadId) ?: return false
|
||||||
|
@@ -601,7 +601,7 @@ class InstrumentedTests {
|
|||||||
assertEquals("New Group", infoConf.getName())
|
assertEquals("New Group", infoConf.getName())
|
||||||
infoConf.setCreated(System.currentTimeMillis())
|
infoConf.setCreated(System.currentTimeMillis())
|
||||||
assertThat(infoConf.getCreated(), notNullValue())
|
assertThat(infoConf.getCreated(), notNullValue())
|
||||||
val memberConf = GroupMemberConfig.newInstance(groupPublic, groupSecret)
|
val memberConf = GroupMembersConfig.newInstance(groupPublic, groupSecret)
|
||||||
memberConf.set(
|
memberConf.set(
|
||||||
GroupMember(
|
GroupMember(
|
||||||
sessionId = "05"+Hex.toStringCondensed(userCurve),
|
sessionId = "05"+Hex.toStringCondensed(userCurve),
|
||||||
@@ -637,7 +637,7 @@ class InstrumentedTests {
|
|||||||
assertEquals("New Group", infoConf.getName())
|
assertEquals("New Group", infoConf.getName())
|
||||||
infoConf.setCreated(System.currentTimeMillis())
|
infoConf.setCreated(System.currentTimeMillis())
|
||||||
assertThat(infoConf.getCreated(), notNullValue())
|
assertThat(infoConf.getCreated(), notNullValue())
|
||||||
val memberConf = GroupMemberConfig.newInstance(groupPublic, groupSecret)
|
val memberConf = GroupMembersConfig.newInstance(groupPublic, groupSecret)
|
||||||
memberConf.set(
|
memberConf.set(
|
||||||
GroupMember(
|
GroupMember(
|
||||||
sessionId = "05"+Hex.toStringCondensed(userCurve),
|
sessionId = "05"+Hex.toStringCondensed(userCurve),
|
||||||
|
@@ -177,3 +177,11 @@ Java_network_loki_messenger_libsession_1util_GroupInfoConfig_storageNamespace(JN
|
|||||||
auto group_info = ptrToInfo(env, thiz);
|
auto group_info = ptrToInfo(env, thiz);
|
||||||
return static_cast<jlong>(group_info->storage_namespace());
|
return static_cast<jlong>(group_info->storage_namespace());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jobject JNICALL
|
||||||
|
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_id(JNIEnv *env, jobject thiz) {
|
||||||
|
std::lock_guard guard{util::util_mutex_};
|
||||||
|
auto group_info = ptrToInfo(env, thiz);
|
||||||
|
return util::serialize_session_id(env, group_info->id);
|
||||||
|
}
|
@@ -65,6 +65,7 @@ Java_network_loki_messenger_libsession_1util_GroupKeysConfig_groupKeys(JNIEnv *e
|
|||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_loadKey(JNIEnv *env, jobject thiz,
|
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_loadKey(JNIEnv *env, jobject thiz,
|
||||||
|
jstring hash,
|
||||||
jbyteArray data,
|
jbyteArray data,
|
||||||
jbyteArray msg_id,
|
jbyteArray msg_id,
|
||||||
jlong timestamp_ms,
|
jlong timestamp_ms,
|
||||||
@@ -72,11 +73,13 @@ Java_network_loki_messenger_libsession_1util_GroupKeysConfig_loadKey(JNIEnv *env
|
|||||||
jobject members_jobject) {
|
jobject members_jobject) {
|
||||||
std::lock_guard lock{util::util_mutex_};
|
std::lock_guard lock{util::util_mutex_};
|
||||||
auto keys = ptrToKeys(env, thiz);
|
auto keys = ptrToKeys(env, thiz);
|
||||||
|
auto hash_bytes = env->GetStringUTFChars(hash, nullptr);
|
||||||
auto data_bytes = util::ustring_from_bytes(env, data);
|
auto data_bytes = util::ustring_from_bytes(env, data);
|
||||||
auto msg_bytes = util::ustring_from_bytes(env, msg_id);
|
auto msg_bytes = util::ustring_from_bytes(env, msg_id);
|
||||||
auto info = ptrToInfo(env, info_jobject);
|
auto info = ptrToInfo(env, info_jobject);
|
||||||
auto members = ptrToMembers(env, members_jobject);
|
auto members = ptrToMembers(env, members_jobject);
|
||||||
keys->load_key_message(data_bytes, timestamp_ms, *info, *members);
|
keys->load_key_message(hash_bytes, data_bytes, timestamp_ms, *info, *members);
|
||||||
|
env->ReleaseStringUTFChars(hash, hash_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jobject JNICALL
|
JNIEXPORT jobject JNICALL
|
||||||
Java_network_loki_messenger_libsession_1util_GroupMemberConfig_00024Companion_newInstance(
|
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_00024Companion_newInstance(
|
||||||
JNIEnv *env, jobject thiz, jbyteArray pub_key, jbyteArray secret_key,
|
JNIEnv *env, jobject thiz, jbyteArray pub_key, jbyteArray secret_key,
|
||||||
jbyteArray initial_dump) {
|
jbyteArray initial_dump) {
|
||||||
std::lock_guard lock{util::util_mutex_};
|
std::lock_guard lock{util::util_mutex_};
|
||||||
@@ -20,7 +20,7 @@ Java_network_loki_messenger_libsession_1util_GroupMemberConfig_00024Companion_ne
|
|||||||
|
|
||||||
auto* group_members = new session::config::groups::Members(pub_key_bytes, secret_key_optional, initial_dump_optional);
|
auto* group_members = new session::config::groups::Members(pub_key_bytes, secret_key_optional, initial_dump_optional);
|
||||||
|
|
||||||
jclass groupMemberClass = env->FindClass("network/loki/messenger/libsession_util/GroupMemberConfig");
|
jclass groupMemberClass = env->FindClass("network/loki/messenger/libsession_util/GroupMembersConfig");
|
||||||
jmethodID constructor = env->GetMethodID(groupMemberClass, "<init>", "(J)V");
|
jmethodID constructor = env->GetMethodID(groupMemberClass, "<init>", "(J)V");
|
||||||
jobject newConfig = env->NewObject(groupMemberClass, constructor, reinterpret_cast<jlong>(group_members));
|
jobject newConfig = env->NewObject(groupMemberClass, constructor, reinterpret_cast<jlong>(group_members));
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ Java_network_loki_messenger_libsession_1util_GroupMemberConfig_00024Companion_ne
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jobject JNICALL
|
JNIEXPORT jobject JNICALL
|
||||||
Java_network_loki_messenger_libsession_1util_GroupMemberConfig_all(JNIEnv *env, jobject thiz) {
|
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_all(JNIEnv *env, jobject thiz) {
|
||||||
std::lock_guard lock{util::util_mutex_};
|
std::lock_guard lock{util::util_mutex_};
|
||||||
auto config = ptrToMembers(env, thiz);
|
auto config = ptrToMembers(env, thiz);
|
||||||
jclass stack = env->FindClass("java/util/Stack");
|
jclass stack = env->FindClass("java/util/Stack");
|
||||||
@@ -45,7 +45,7 @@ Java_network_loki_messenger_libsession_1util_GroupMemberConfig_all(JNIEnv *env,
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
Java_network_loki_messenger_libsession_1util_GroupMemberConfig_erase(JNIEnv *env, jobject thiz,
|
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_erase(JNIEnv *env, jobject thiz,
|
||||||
jobject group_member) {
|
jobject group_member) {
|
||||||
auto config = ptrToMembers(env, thiz);
|
auto config = ptrToMembers(env, thiz);
|
||||||
auto member = util::deserialize_group_member(env, group_member);
|
auto member = util::deserialize_group_member(env, group_member);
|
||||||
@@ -54,7 +54,7 @@ Java_network_loki_messenger_libsession_1util_GroupMemberConfig_erase(JNIEnv *env
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jobject JNICALL
|
JNIEXPORT jobject JNICALL
|
||||||
Java_network_loki_messenger_libsession_1util_GroupMemberConfig_get(JNIEnv *env, jobject thiz,
|
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_get(JNIEnv *env, jobject thiz,
|
||||||
jstring pub_key_hex) {
|
jstring pub_key_hex) {
|
||||||
std::lock_guard lock{util::util_mutex_};
|
std::lock_guard lock{util::util_mutex_};
|
||||||
auto config = ptrToMembers(env, thiz);
|
auto config = ptrToMembers(env, thiz);
|
||||||
@@ -70,7 +70,7 @@ Java_network_loki_messenger_libsession_1util_GroupMemberConfig_get(JNIEnv *env,
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jobject JNICALL
|
JNIEXPORT jobject JNICALL
|
||||||
Java_network_loki_messenger_libsession_1util_GroupMemberConfig_getOrConstruct(JNIEnv *env,
|
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_getOrConstruct(JNIEnv *env,
|
||||||
jobject thiz,
|
jobject thiz,
|
||||||
jstring pub_key_hex) {
|
jstring pub_key_hex) {
|
||||||
std::lock_guard lock{util::util_mutex_};
|
std::lock_guard lock{util::util_mutex_};
|
||||||
@@ -84,7 +84,7 @@ Java_network_loki_messenger_libsession_1util_GroupMemberConfig_getOrConstruct(JN
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_network_loki_messenger_libsession_1util_GroupMemberConfig_set(JNIEnv *env, jobject thiz,
|
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_set(JNIEnv *env, jobject thiz,
|
||||||
jobject group_member) {
|
jobject group_member) {
|
||||||
std::lock_guard lock{util::util_mutex_};
|
std::lock_guard lock{util::util_mutex_};
|
||||||
auto config = ptrToMembers(env, thiz);
|
auto config = ptrToMembers(env, thiz);
|
||||||
|
@@ -10,6 +10,8 @@ import network.loki.messenger.libsession_util.util.UserPic
|
|||||||
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage.Kind
|
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage.Kind
|
||||||
import org.session.libsignal.utilities.IdPrefix
|
import org.session.libsignal.utilities.IdPrefix
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.session.libsignal.utilities.SessionId
|
||||||
|
import java.io.Closeable
|
||||||
import java.util.Stack
|
import java.util.Stack
|
||||||
|
|
||||||
|
|
||||||
@@ -27,7 +29,7 @@ sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
|
|||||||
is UserGroupsConfig -> Kind.GROUPS
|
is UserGroupsConfig -> Kind.GROUPS
|
||||||
is GroupInfoConfig -> Kind.CLOSED_GROUP_INFO
|
is GroupInfoConfig -> Kind.CLOSED_GROUP_INFO
|
||||||
is GroupKeysConfig -> Kind.ENCRYPTION_KEYS
|
is GroupKeysConfig -> Kind.ENCRYPTION_KEYS
|
||||||
is GroupMemberConfig -> Kind.CLOSED_GROUP_MEMBERS
|
is GroupMembersConfig -> Kind.CLOSED_GROUP_MEMBERS
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: time in future to activate (hardcoded to 1st jan 2024 for testing, change before release)
|
// TODO: time in future to activate (hardcoded to 1st jan 2024 for testing, change before release)
|
||||||
@@ -217,7 +219,7 @@ class UserGroupsConfig(pointer: Long): ConfigBase(pointer) {
|
|||||||
external fun createGroup(): GroupInfo.ClosedGroupInfo
|
external fun createGroup(): GroupInfo.ClosedGroupInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroupInfoConfig(pointer: Long): ConfigBase(pointer) {
|
class GroupInfoConfig(pointer: Long): ConfigBase(pointer), Closeable {
|
||||||
companion object {
|
companion object {
|
||||||
init {
|
init {
|
||||||
System.loadLibrary("session_util")
|
System.loadLibrary("session_util")
|
||||||
@@ -229,6 +231,7 @@ class GroupInfoConfig(pointer: Long): ConfigBase(pointer) {
|
|||||||
initialDump: ByteArray = byteArrayOf()
|
initialDump: ByteArray = byteArrayOf()
|
||||||
): GroupInfoConfig
|
): GroupInfoConfig
|
||||||
}
|
}
|
||||||
|
external fun id(): SessionId
|
||||||
external fun destroyGroup()
|
external fun destroyGroup()
|
||||||
external fun getCreated(): Long?
|
external fun getCreated(): Long?
|
||||||
external fun getDeleteAttachmentsBefore(): Long?
|
external fun getDeleteAttachmentsBefore(): Long?
|
||||||
@@ -244,9 +247,12 @@ class GroupInfoConfig(pointer: Long): ConfigBase(pointer) {
|
|||||||
external fun setName(newName: String)
|
external fun setName(newName: String)
|
||||||
external fun setProfilePic(newProfilePic: UserPic)
|
external fun setProfilePic(newProfilePic: UserPic)
|
||||||
external fun storageNamespace(): Long
|
external fun storageNamespace(): Long
|
||||||
|
override fun close() {
|
||||||
|
free()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroupMemberConfig(pointer: Long): ConfigBase(pointer) {
|
class GroupMembersConfig(pointer: Long): ConfigBase(pointer), Closeable {
|
||||||
companion object {
|
companion object {
|
||||||
init {
|
init {
|
||||||
System.loadLibrary("session_util")
|
System.loadLibrary("session_util")
|
||||||
@@ -255,16 +261,19 @@ class GroupMemberConfig(pointer: Long): ConfigBase(pointer) {
|
|||||||
pubKey: ByteArray,
|
pubKey: ByteArray,
|
||||||
secretKey: ByteArray = byteArrayOf(),
|
secretKey: ByteArray = byteArrayOf(),
|
||||||
initialDump: ByteArray = byteArrayOf()
|
initialDump: ByteArray = byteArrayOf()
|
||||||
): GroupMemberConfig
|
): GroupMembersConfig
|
||||||
}
|
}
|
||||||
external fun all(): Stack<GroupMember>
|
external fun all(): Stack<GroupMember>
|
||||||
external fun erase(groupMember: GroupMember): Boolean
|
external fun erase(groupMember: GroupMember): Boolean
|
||||||
external fun get(pubKeyHex: String): GroupMember?
|
external fun get(pubKeyHex: String): GroupMember?
|
||||||
external fun getOrConstruct(pubKeyHex: String): GroupMember
|
external fun getOrConstruct(pubKeyHex: String): GroupMember
|
||||||
external fun set(groupMember: GroupMember)
|
external fun set(groupMember: GroupMember)
|
||||||
|
override fun close() {
|
||||||
|
free()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroupKeysConfig(pointer: Long): ConfigBase(pointer) {
|
class GroupKeysConfig(pointer: Long): ConfigBase(pointer), Closeable {
|
||||||
companion object {
|
companion object {
|
||||||
init {
|
init {
|
||||||
System.loadLibrary("session_util")
|
System.loadLibrary("session_util")
|
||||||
@@ -275,17 +284,21 @@ class GroupKeysConfig(pointer: Long): ConfigBase(pointer) {
|
|||||||
groupSecretKey: ByteArray = byteArrayOf(),
|
groupSecretKey: ByteArray = byteArrayOf(),
|
||||||
initialDump: ByteArray = byteArrayOf(),
|
initialDump: ByteArray = byteArrayOf(),
|
||||||
info: GroupInfoConfig,
|
info: GroupInfoConfig,
|
||||||
members: GroupMemberConfig
|
members: GroupMembersConfig
|
||||||
): GroupKeysConfig
|
): GroupKeysConfig
|
||||||
}
|
}
|
||||||
external fun groupKeys(): Stack<ByteArray>
|
external fun groupKeys(): Stack<ByteArray>
|
||||||
external fun loadKey(data: ByteArray,
|
external fun loadKey(hash: String,
|
||||||
|
data: ByteArray,
|
||||||
msgId: ByteArray,
|
msgId: ByteArray,
|
||||||
timestampMs: Long,
|
timestampMs: Long,
|
||||||
info: GroupInfoConfig,
|
info: GroupInfoConfig,
|
||||||
members: GroupMemberConfig)
|
members: GroupMembersConfig)
|
||||||
external fun needsRekey(): Boolean
|
external fun needsRekey(): Boolean
|
||||||
external fun pendingKey(): ByteArray?
|
external fun pendingKey(): ByteArray?
|
||||||
external fun pendingPush(): ByteArray?
|
external fun pendingPush(): ByteArray?
|
||||||
external fun rekey(info: GroupInfoConfig, members: GroupMemberConfig): ByteArray
|
external fun rekey(info: GroupInfoConfig, members: GroupMembersConfig): ByteArray
|
||||||
|
override fun close() {
|
||||||
|
free()
|
||||||
|
}
|
||||||
}
|
}
|
@@ -154,7 +154,7 @@ interface StorageProtocol {
|
|||||||
fun setExpirationTimer(address: String, duration: Int)
|
fun setExpirationTimer(address: String, duration: Int)
|
||||||
|
|
||||||
// Closed Groups
|
// Closed Groups
|
||||||
fun getMembers(groupPublicKey: String): List<GroupMember>
|
fun getMembers(groupPublicKey: String): List<network.loki.messenger.libsession_util.util.GroupMember>
|
||||||
|
|
||||||
// Groups
|
// Groups
|
||||||
fun getAllGroups(includeInactive: Boolean): List<GroupRecord>
|
fun getAllGroups(includeInactive: Boolean): List<GroupRecord>
|
||||||
|
@@ -23,6 +23,8 @@ class Address private constructor(address: String) : Parcelable, Comparable<Addr
|
|||||||
get() = GroupUtil.isEncodedGroup(address) || address.startsWith(IdPrefix.GROUP.value)
|
get() = GroupUtil.isEncodedGroup(address) || address.startsWith(IdPrefix.GROUP.value)
|
||||||
val isLegacyClosedGroup: Boolean
|
val isLegacyClosedGroup: Boolean
|
||||||
get() = GroupUtil.isLegacyClosedGroup(address)
|
get() = GroupUtil.isLegacyClosedGroup(address)
|
||||||
|
val isClosedGroup: Boolean
|
||||||
|
get() = address.startsWith(IdPrefix.GROUP.value)
|
||||||
val isOpenGroup: Boolean
|
val isOpenGroup: Boolean
|
||||||
get() = GroupUtil.isOpenGroup(address)
|
get() = GroupUtil.isOpenGroup(address)
|
||||||
val isOpenGroupInbox: Boolean
|
val isOpenGroupInbox: Boolean
|
||||||
|
@@ -3,14 +3,23 @@ package org.session.libsession.utilities
|
|||||||
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.ConversationVolatileConfig
|
||||||
|
import network.loki.messenger.libsession_util.GroupInfoConfig
|
||||||
|
import network.loki.messenger.libsession_util.GroupKeysConfig
|
||||||
|
import network.loki.messenger.libsession_util.GroupMembersConfig
|
||||||
import network.loki.messenger.libsession_util.UserGroupsConfig
|
import network.loki.messenger.libsession_util.UserGroupsConfig
|
||||||
import network.loki.messenger.libsession_util.UserProfile
|
import network.loki.messenger.libsession_util.UserProfile
|
||||||
|
import org.session.libsignal.utilities.SessionId
|
||||||
|
|
||||||
interface ConfigFactoryProtocol {
|
interface ConfigFactoryProtocol {
|
||||||
val user: UserProfile?
|
val user: UserProfile?
|
||||||
val contacts: Contacts?
|
val contacts: Contacts?
|
||||||
val convoVolatile: ConversationVolatileConfig?
|
val convoVolatile: ConversationVolatileConfig?
|
||||||
val userGroups: UserGroupsConfig?
|
val userGroups: UserGroupsConfig?
|
||||||
|
|
||||||
|
fun groupInfoConfig(groupSessionId: SessionId): GroupInfoConfig?
|
||||||
|
fun groupKeysConfig(groupSessionId: SessionId): GroupKeysConfig?
|
||||||
|
fun groupMemberConfig(groupSessionId: SessionId): GroupMembersConfig?
|
||||||
|
|
||||||
fun getUserConfigs(): List<ConfigBase>
|
fun getUserConfigs(): List<ConfigBase>
|
||||||
fun persist(forConfigObject: ConfigBase, timestamp: Long)
|
fun persist(forConfigObject: ConfigBase, timestamp: Long)
|
||||||
|
|
||||||
|
@@ -476,6 +476,10 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
return address.isLegacyClosedGroup();
|
return address.isLegacyClosedGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClosedGroupRecipient() {
|
||||||
|
return address.isClosedGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean isPushGroupRecipient() {
|
public boolean isPushGroupRecipient() {
|
||||||
|
Reference in New Issue
Block a user