mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-25 12:07:43 +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 -> {
|
||||
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 -> {
|
||||
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.GroupInfoConfig
|
||||
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.UserProfile
|
||||
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 java.security.MessageDigest
|
||||
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,
|
||||
ThreadDatabase.ConversationThreadUpdateListener {
|
||||
@@ -460,9 +461,9 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
is Contacts -> updateContacts(forConfigObject)
|
||||
is ConversationVolatileConfig -> updateConvoVolatile(forConfigObject)
|
||||
is UserGroupsConfig -> updateUserGroups(forConfigObject)
|
||||
is GroupInfoConfig -> TODO()
|
||||
is GroupKeysConfig -> TODO()
|
||||
is GroupMemberConfig -> TODO()
|
||||
is GroupInfoConfig -> updateGroupInfo(forConfigObject)
|
||||
is GroupKeysConfig -> updateGroupKeys(forConfigObject)
|
||||
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) {
|
||||
val extracted = contacts.all().toList()
|
||||
addLibSessionContacts(extracted)
|
||||
@@ -1030,10 +1044,8 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMembers(groupPublicKey: String): List<GroupMember> {
|
||||
val groups = configFactory.userGroups ?: return emptyList()
|
||||
TODO("Add group specific configs")
|
||||
}
|
||||
override fun getMembers(groupPublicKey: String): List<LibSessionGroupMember> =
|
||||
configFactory.groupMemberConfig(SessionId.from(groupPublicKey))?.all()?.toList() ?: emptyList()
|
||||
|
||||
override fun setServerCapabilities(server: String, capabilities: List<String>) {
|
||||
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 ->
|
||||
val sessionId = SessionId(contact.sessionID)
|
||||
if (sessionId.prefix == IdPrefix.STANDARD && SodiumUtilities.sessionId(sessionId.hexString, blindedId, serverPublicKey)) {
|
||||
val contactMapping = mapping.copy(sessionId = sessionId.hexString)
|
||||
if (sessionId.prefix == IdPrefix.STANDARD && SodiumUtilities.sessionId(sessionId.hexString(), blindedId, serverPublicKey)) {
|
||||
val contactMapping = mapping.copy(sessionId = sessionId.hexString())
|
||||
db.addBlindedIdMapping(contactMapping)
|
||||
return contactMapping
|
||||
}
|
||||
|
@@ -5,6 +5,9 @@ import android.os.Trace
|
||||
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.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.UserProfile
|
||||
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.TextSecurePreferences
|
||||
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage
|
||||
import org.session.libsignal.utilities.Hex
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
import org.thoughtcrime.securesms.database.ConfigDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
@@ -61,7 +66,7 @@ class ConfigFactory(
|
||||
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")
|
||||
val result = synchronized(lock) {
|
||||
body()
|
||||
@@ -72,7 +77,11 @@ class ConfigFactory(
|
||||
|
||||
override val user: UserProfile?
|
||||
get() = synchronizedWithLog(userLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
|
||||
if (!ConfigBase.isNewConfigEnabled(
|
||||
isConfigForcedOn,
|
||||
SnodeAPI.nowWithOffset
|
||||
)
|
||||
) return null
|
||||
if (_userConfig == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
||||
val userDump = configDatabase.retrieveConfigAndHashes(
|
||||
@@ -92,7 +101,11 @@ class ConfigFactory(
|
||||
|
||||
override val contacts: Contacts?
|
||||
get() = synchronizedWithLog(contactsLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
|
||||
if (!ConfigBase.isNewConfigEnabled(
|
||||
isConfigForcedOn,
|
||||
SnodeAPI.nowWithOffset
|
||||
)
|
||||
) return null
|
||||
if (_contacts == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
||||
val contactsDump = configDatabase.retrieveConfigAndHashes(
|
||||
@@ -112,7 +125,11 @@ class ConfigFactory(
|
||||
|
||||
override val convoVolatile: ConversationVolatileConfig?
|
||||
get() = synchronizedWithLog(convoVolatileLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
|
||||
if (!ConfigBase.isNewConfigEnabled(
|
||||
isConfigForcedOn,
|
||||
SnodeAPI.nowWithOffset
|
||||
)
|
||||
) return null
|
||||
if (_convoVolatileConfig == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
||||
val convoDump = configDatabase.retrieveConfigAndHashes(
|
||||
@@ -133,7 +150,11 @@ class ConfigFactory(
|
||||
|
||||
override val userGroups: UserGroupsConfig?
|
||||
get() = synchronizedWithLog(userGroupsLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
|
||||
if (!ConfigBase.isNewConfigEnabled(
|
||||
isConfigForcedOn,
|
||||
SnodeAPI.nowWithOffset
|
||||
)
|
||||
) return null
|
||||
if (_userGroups == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
|
||||
val userGroupsDump = configDatabase.retrieveConfigAndHashes(
|
||||
@@ -151,6 +172,61 @@ class ConfigFactory(
|
||||
_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> =
|
||||
listOfNotNull(user, contacts, convoVolatile, userGroups)
|
||||
|
||||
@@ -158,13 +234,23 @@ class ConfigFactory(
|
||||
private fun persistUserConfigDump(timestamp: Long) = synchronized(userLock) {
|
||||
val dumped = user?.dump() ?: 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) {
|
||||
val dumped = contacts?.dump() ?: 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) {
|
||||
@@ -181,7 +267,12 @@ class ConfigFactory(
|
||||
private fun persistUserGroupsConfigDump(timestamp: Long) = synchronized(userGroupsLock) {
|
||||
val dumped = userGroups?.dump() ?: 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) {
|
||||
@@ -214,23 +305,21 @@ class ConfigFactory(
|
||||
if (openGroupId != null) {
|
||||
val userGroups = userGroups ?: return false
|
||||
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
|
||||
return (userGroups.getCommunityInfo(openGroup.server, openGroup.room) != null)
|
||||
}
|
||||
else if (groupPublicKey != null) {
|
||||
} else if (groupPublicKey != null) {
|
||||
val userGroups = userGroups ?: return false
|
||||
|
||||
// Not handling the `hidden` behaviour for legacy groups so just indicate the existence
|
||||
return (userGroups.getLegacyGroupInfo(groupPublicKey) != null)
|
||||
}
|
||||
else if (publicKey == userPublicKey) {
|
||||
} else if (publicKey == userPublicKey) {
|
||||
val user = user ?: return false
|
||||
|
||||
return (!visibleOnly || user.getNtsPriority() != ConfigBase.PRIORITY_HIDDEN)
|
||||
}
|
||||
else if (publicKey != null) {
|
||||
} else if (publicKey != null) {
|
||||
val contacts = contacts ?: return false
|
||||
val targetContact = contacts.get(publicKey) ?: return false
|
||||
|
||||
@@ -240,12 +329,18 @@ class ConfigFactory(
|
||||
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
|
||||
|
||||
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)
|
||||
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) {
|
||||
val groups = userGroups ?: return
|
||||
if (!group.isClosedGroup) return
|
||||
if (!group.isLegacyClosedGroup) return
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val threadId = storage.getThreadId(group.encodedId) ?: return
|
||||
val groupPublicKey = GroupUtil.doubleEncodeGroupID(group.getId())
|
||||
|
@@ -7,6 +7,13 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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.view.isVisible
|
||||
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.groupSizeLimit
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.Contact
|
||||
import org.session.libsession.utilities.Device
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
@@ -49,8 +57,11 @@ class CreateGroupFragment : Fragment() {
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentCreateGroupBinding.inflate(inflater)
|
||||
return binding.root
|
||||
return ComposeView(requireContext()).apply {
|
||||
setContent {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
push(intent)
|
||||
}
|
||||
is GlobalSearchAdapter.Model.GroupConversation -> {
|
||||
is GlobalSearchAdapter.Model.LegacyGroupConversation -> {
|
||||
val groupAddress = Address.fromSerialized(model.groupRecord.encodedId)
|
||||
val threadId = threadDb.getThreadIdIfExistsFor(Recipient.from(this, groupAddress, false))
|
||||
if (threadId >= 0) {
|
||||
@@ -257,7 +257,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
globalSearchViewModel.result.collect { result ->
|
||||
val currentUserPublicKey = publicKey
|
||||
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()
|
||||
|
||||
@@ -642,14 +642,18 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
// Cancel any outstanding jobs
|
||||
DatabaseComponent.get(context).sessionJobDatabase().cancelPendingMessageSendJobs(threadID)
|
||||
// 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 {
|
||||
GroupUtil.doubleDecodeGroupID(recipient.address.toString()).toHexString()
|
||||
.takeIf(DatabaseComponent.get(context).lokiAPIDatabase()::isClosedGroup)
|
||||
?.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
|
||||
val v2OpenGroup = DatabaseComponent.get(context).lokiThreadDatabase().getOpenGroupChat(threadID)
|
||||
if (v2OpenGroup != null) {
|
||||
|
@@ -9,9 +9,10 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import network.loki.messenger.R
|
||||
import network.loki.messenger.databinding.ViewGlobalSearchHeaderBinding
|
||||
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.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
import org.thoughtcrime.securesms.search.model.MessageResult
|
||||
import java.security.InvalidParameterException
|
||||
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) {
|
||||
binding.searchResultProfilePicture.recycle()
|
||||
when (model) {
|
||||
is Model.GroupConversation -> bindModel(query, model)
|
||||
is Model.LegacyGroupConversation -> bindModel(query, model)
|
||||
is Model.Contact -> bindModel(query, model)
|
||||
is Model.Message -> bindModel(query, 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 SavedMessages(val currentUserPublicKey: String): 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()
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,7 @@ import org.session.libsession.messaging.contacts.Contact
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
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.Message
|
||||
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.searchResultTitle.text = model.messageResult.conversationRecipient.toShortString()
|
||||
}
|
||||
is GroupConversation -> {
|
||||
is LegacyGroupConversation -> {
|
||||
binding.searchResultTitle.text = getHighlight(
|
||||
query,
|
||||
model.groupRecord.title
|
||||
@@ -86,10 +86,10 @@ private fun getHighlight(query: String?, toSearch: String): Spannable? {
|
||||
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.searchResultSavedMessages.isVisible = false
|
||||
binding.searchResultSubtitle.isVisible = model.groupRecord.isClosedGroup
|
||||
binding.searchResultSubtitle.isVisible = model.groupRecord.isLegacyClosedGroup
|
||||
binding.searchResultTimestamp.isVisible = false
|
||||
val threadRecipient = Recipient.from(binding.root.context, Address.fromSerialized(model.groupRecord.encodedId), false)
|
||||
binding.searchResultProfilePicture.update(threadRecipient)
|
||||
@@ -102,7 +102,7 @@ fun ContentView.bindModel(query: String?, model: GroupConversation) {
|
||||
val address = it.address.serialize()
|
||||
it.name ?: "${address.take(4)}...${address.takeLast(4)}"
|
||||
}
|
||||
if (model.groupRecord.isClosedGroup) {
|
||||
if (model.groupRecord.isLegacyClosedGroup) {
|
||||
binding.searchResultSubtitle.text = getHighlight(query, membersString)
|
||||
}
|
||||
}
|
||||
@@ -132,11 +132,6 @@ fun ContentView.bindModel(query: String?, model: Message) {
|
||||
binding.searchResultProfilePicture.isVisible = true
|
||||
binding.searchResultSavedMessages.isVisible = false
|
||||
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.searchResultProfilePicture.update(model.messageResult.conversationRecipient)
|
||||
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.sending_receiving.notifications.MessageNotifier;
|
||||
import org.session.libsession.messaging.utilities.SessionId;
|
||||
import org.session.libsession.messaging.utilities.SodiumUtilities;
|
||||
import org.session.libsession.snode.SnodeAPI;
|
||||
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.libsignal.utilities.IdPrefix;
|
||||
import org.session.libsignal.utilities.Log;
|
||||
import org.session.libsignal.utilities.SessionId;
|
||||
import org.session.libsignal.utilities.Util;
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.contacts.ContactUtil;
|
||||
@@ -555,7 +555,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
|
||||
if (openGroup != null && edKeyPair != null) {
|
||||
KeyPair blindedKeyPair = SodiumUtilities.blindedKeyPair(openGroup.getPublicKey(), edKeyPair);
|
||||
if (blindedKeyPair != null) {
|
||||
return new SessionId(IdPrefix.BLINDED, blindedKeyPair.getPublicKey().getAsBytes()).getHexString();
|
||||
return new SessionId(IdPrefix.BLINDED, blindedKeyPair.getPublicKey().getAsBytes()).hexString();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@@ -9,11 +9,10 @@ import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
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.emoji.EmojiImageView;
|
||||
import org.thoughtcrime.securesms.database.model.MessageId;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
|
||||
import java.util.Collections;
|
||||
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.jobs.JobQueue
|
||||
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.TextSecurePreferences
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package org.thoughtcrime.securesms.util
|
||||
|
||||
import android.content.Context
|
||||
import android.provider.Telephony.Sms.Conversations
|
||||
import network.loki.messenger.libsession_util.ConfigBase
|
||||
import network.loki.messenger.libsession_util.Contacts
|
||||
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.utilities.Hex
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
import org.session.libsignal.utilities.toHexString
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
@@ -199,6 +201,11 @@ object ConfigurationMessageUtilities {
|
||||
convoConfig.getOrConstructCommunity(base, room, pubKey)
|
||||
}
|
||||
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())
|
||||
convoConfig.getOrConstructLegacyGroup(groupPublicKey)
|
||||
}
|
||||
@@ -241,7 +248,7 @@ object ConfigurationMessageUtilities {
|
||||
}
|
||||
|
||||
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 ->
|
||||
val groupAddress = Address.fromSerialized(group.encodedId)
|
||||
val groupPublicKey = GroupUtil.doubleDecodeGroupID(groupAddress.serialize()).toHexString()
|
||||
@@ -252,7 +259,7 @@ object ConfigurationMessageUtilities {
|
||||
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()
|
||||
GroupInfo.LegacyGroupInfo(
|
||||
sessionId = groupPublicKey,
|
||||
sessionId = SessionId.from(groupPublicKey),
|
||||
name = group.title,
|
||||
members = admins + members,
|
||||
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)) {
|
||||
return getOneToOne(recipient.address.serialize())?.unread == true
|
||||
} else if (recipient.isClosedGroupRecipient) {
|
||||
return getClosedGroup(recipient.address.serialize())?.unread == true
|
||||
} else if (recipient.isLegacyClosedGroupRecipient) {
|
||||
return getLegacyClosedGroup(GroupUtil.doubleDecodeGroupId(recipient.address.toGroupString()))?.unread == true
|
||||
} else if (recipient.isOpenGroupRecipient) {
|
||||
val openGroup = MessagingModuleConfiguration.shared.storage.getOpenGroup(thread.threadId) ?: return false
|
||||
|
@@ -601,7 +601,7 @@ class InstrumentedTests {
|
||||
assertEquals("New Group", infoConf.getName())
|
||||
infoConf.setCreated(System.currentTimeMillis())
|
||||
assertThat(infoConf.getCreated(), notNullValue())
|
||||
val memberConf = GroupMemberConfig.newInstance(groupPublic, groupSecret)
|
||||
val memberConf = GroupMembersConfig.newInstance(groupPublic, groupSecret)
|
||||
memberConf.set(
|
||||
GroupMember(
|
||||
sessionId = "05"+Hex.toStringCondensed(userCurve),
|
||||
@@ -637,7 +637,7 @@ class InstrumentedTests {
|
||||
assertEquals("New Group", infoConf.getName())
|
||||
infoConf.setCreated(System.currentTimeMillis())
|
||||
assertThat(infoConf.getCreated(), notNullValue())
|
||||
val memberConf = GroupMemberConfig.newInstance(groupPublic, groupSecret)
|
||||
val memberConf = GroupMembersConfig.newInstance(groupPublic, groupSecret)
|
||||
memberConf.set(
|
||||
GroupMember(
|
||||
sessionId = "05"+Hex.toStringCondensed(userCurve),
|
||||
|
@@ -177,3 +177,11 @@ Java_network_loki_messenger_libsession_1util_GroupInfoConfig_storageNamespace(JN
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
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"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_loadKey(JNIEnv *env, jobject thiz,
|
||||
jstring hash,
|
||||
jbyteArray data,
|
||||
jbyteArray msg_id,
|
||||
jlong timestamp_ms,
|
||||
@@ -72,11 +73,13 @@ Java_network_loki_messenger_libsession_1util_GroupKeysConfig_loadKey(JNIEnv *env
|
||||
jobject members_jobject) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
auto hash_bytes = env->GetStringUTFChars(hash, nullptr);
|
||||
auto data_bytes = util::ustring_from_bytes(env, data);
|
||||
auto msg_bytes = util::ustring_from_bytes(env, msg_id);
|
||||
auto info = ptrToInfo(env, info_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"
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
extern "C"
|
||||
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,
|
||||
jbyteArray initial_dump) {
|
||||
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);
|
||||
|
||||
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");
|
||||
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"
|
||||
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_};
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
@@ -45,8 +45,8 @@ Java_network_loki_messenger_libsession_1util_GroupMemberConfig_all(JNIEnv *env,
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMemberConfig_erase(JNIEnv *env, jobject thiz,
|
||||
jobject group_member) {
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_erase(JNIEnv *env, jobject thiz,
|
||||
jobject group_member) {
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
auto member = util::deserialize_group_member(env, group_member);
|
||||
return config->erase(member.session_id);
|
||||
@@ -54,8 +54,8 @@ Java_network_loki_messenger_libsession_1util_GroupMemberConfig_erase(JNIEnv *env
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMemberConfig_get(JNIEnv *env, jobject thiz,
|
||||
jstring pub_key_hex) {
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_get(JNIEnv *env, jobject thiz,
|
||||
jstring pub_key_hex) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
auto pub_key_bytes = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
@@ -70,9 +70,9 @@ Java_network_loki_messenger_libsession_1util_GroupMemberConfig_get(JNIEnv *env,
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMemberConfig_getOrConstruct(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring pub_key_hex) {
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_getOrConstruct(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring pub_key_hex) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
auto pub_key_bytes = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
@@ -84,8 +84,8 @@ Java_network_loki_messenger_libsession_1util_GroupMemberConfig_getOrConstruct(JN
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMemberConfig_set(JNIEnv *env, jobject thiz,
|
||||
jobject group_member) {
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_set(JNIEnv *env, jobject thiz,
|
||||
jobject group_member) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
auto deserialized = util::deserialize_group_member(env, group_member);
|
||||
|
@@ -10,6 +10,8 @@ import network.loki.messenger.libsession_util.util.UserPic
|
||||
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage.Kind
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
import java.io.Closeable
|
||||
import java.util.Stack
|
||||
|
||||
|
||||
@@ -27,7 +29,7 @@ sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
|
||||
is UserGroupsConfig -> Kind.GROUPS
|
||||
is GroupInfoConfig -> Kind.CLOSED_GROUP_INFO
|
||||
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)
|
||||
@@ -217,7 +219,7 @@ class UserGroupsConfig(pointer: Long): ConfigBase(pointer) {
|
||||
external fun createGroup(): GroupInfo.ClosedGroupInfo
|
||||
}
|
||||
|
||||
class GroupInfoConfig(pointer: Long): ConfigBase(pointer) {
|
||||
class GroupInfoConfig(pointer: Long): ConfigBase(pointer), Closeable {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
@@ -229,6 +231,7 @@ class GroupInfoConfig(pointer: Long): ConfigBase(pointer) {
|
||||
initialDump: ByteArray = byteArrayOf()
|
||||
): GroupInfoConfig
|
||||
}
|
||||
external fun id(): SessionId
|
||||
external fun destroyGroup()
|
||||
external fun getCreated(): Long?
|
||||
external fun getDeleteAttachmentsBefore(): Long?
|
||||
@@ -244,9 +247,12 @@ class GroupInfoConfig(pointer: Long): ConfigBase(pointer) {
|
||||
external fun setName(newName: String)
|
||||
external fun setProfilePic(newProfilePic: UserPic)
|
||||
external fun storageNamespace(): Long
|
||||
override fun close() {
|
||||
free()
|
||||
}
|
||||
}
|
||||
|
||||
class GroupMemberConfig(pointer: Long): ConfigBase(pointer) {
|
||||
class GroupMembersConfig(pointer: Long): ConfigBase(pointer), Closeable {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
@@ -255,16 +261,19 @@ class GroupMemberConfig(pointer: Long): ConfigBase(pointer) {
|
||||
pubKey: ByteArray,
|
||||
secretKey: ByteArray = byteArrayOf(),
|
||||
initialDump: ByteArray = byteArrayOf()
|
||||
): GroupMemberConfig
|
||||
): GroupMembersConfig
|
||||
}
|
||||
external fun all(): Stack<GroupMember>
|
||||
external fun erase(groupMember: GroupMember): Boolean
|
||||
external fun get(pubKeyHex: String): GroupMember?
|
||||
external fun getOrConstruct(pubKeyHex: String): 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 {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
@@ -275,17 +284,21 @@ class GroupKeysConfig(pointer: Long): ConfigBase(pointer) {
|
||||
groupSecretKey: ByteArray = byteArrayOf(),
|
||||
initialDump: ByteArray = byteArrayOf(),
|
||||
info: GroupInfoConfig,
|
||||
members: GroupMemberConfig
|
||||
members: GroupMembersConfig
|
||||
): GroupKeysConfig
|
||||
}
|
||||
external fun groupKeys(): Stack<ByteArray>
|
||||
external fun loadKey(data: ByteArray,
|
||||
external fun loadKey(hash: String,
|
||||
data: ByteArray,
|
||||
msgId: ByteArray,
|
||||
timestampMs: Long,
|
||||
info: GroupInfoConfig,
|
||||
members: GroupMemberConfig)
|
||||
members: GroupMembersConfig)
|
||||
external fun needsRekey(): Boolean
|
||||
external fun pendingKey(): 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)
|
||||
|
||||
// Closed Groups
|
||||
fun getMembers(groupPublicKey: String): List<GroupMember>
|
||||
fun getMembers(groupPublicKey: String): List<network.loki.messenger.libsession_util.util.GroupMember>
|
||||
|
||||
// Groups
|
||||
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)
|
||||
val isLegacyClosedGroup: Boolean
|
||||
get() = GroupUtil.isLegacyClosedGroup(address)
|
||||
val isClosedGroup: Boolean
|
||||
get() = address.startsWith(IdPrefix.GROUP.value)
|
||||
val isOpenGroup: Boolean
|
||||
get() = GroupUtil.isOpenGroup(address)
|
||||
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.Contacts
|
||||
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.UserProfile
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
|
||||
interface ConfigFactoryProtocol {
|
||||
val user: UserProfile?
|
||||
val contacts: Contacts?
|
||||
val convoVolatile: ConversationVolatileConfig?
|
||||
val userGroups: UserGroupsConfig?
|
||||
|
||||
fun groupInfoConfig(groupSessionId: SessionId): GroupInfoConfig?
|
||||
fun groupKeysConfig(groupSessionId: SessionId): GroupKeysConfig?
|
||||
fun groupMemberConfig(groupSessionId: SessionId): GroupMembersConfig?
|
||||
|
||||
fun getUserConfigs(): List<ConfigBase>
|
||||
fun persist(forConfigObject: ConfigBase, timestamp: Long)
|
||||
|
||||
|
@@ -476,6 +476,10 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return address.isLegacyClosedGroup();
|
||||
}
|
||||
|
||||
public boolean isClosedGroupRecipient() {
|
||||
return address.isClosedGroup();
|
||||
}
|
||||
|
||||
|
||||
@Deprecated
|
||||
public boolean isPushGroupRecipient() {
|
||||
|
Reference in New Issue
Block a user