feat: adding support for new closed groups, moving closed groups to be legacy throughout app
This commit is contained in:
parent
4e0d043a8c
commit
eaddc44de1
|
@ -20,7 +20,6 @@ import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -34,9 +33,7 @@ import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.view.ActionMode;
|
import androidx.appcompat.view.ActionMode;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
@ -53,7 +50,6 @@ import androidx.viewpager.widget.ViewPager;
|
||||||
|
|
||||||
import com.google.android.material.tabs.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
|
||||||
import org.session.libsession.database.StorageProtocol;
|
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration;
|
import org.session.libsession.messaging.MessagingModuleConfiguration;
|
||||||
import org.session.libsession.messaging.messages.control.DataExtractionNotification;
|
import org.session.libsession.messaging.messages.control.DataExtractionNotification;
|
||||||
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||||
|
@ -65,7 +61,6 @@ import org.session.libsession.utilities.Util;
|
||||||
import org.session.libsession.utilities.ViewUtil;
|
import org.session.libsession.utilities.ViewUtil;
|
||||||
import org.session.libsession.utilities.recipients.Recipient;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.session.libsession.utilities.task.ProgressDialogAsyncTask;
|
import org.session.libsession.utilities.task.ProgressDialogAsyncTask;
|
||||||
import org.thoughtcrime.securesms.conversation.settings.ClearAllMediaDialog;
|
|
||||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||||
import org.thoughtcrime.securesms.database.MediaDatabase;
|
import org.thoughtcrime.securesms.database.MediaDatabase;
|
||||||
import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader;
|
import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader;
|
||||||
|
|
|
@ -54,7 +54,7 @@ class ProfilePictureView @JvmOverloads constructor(
|
||||||
return contact?.displayName(Contact.ContactContext.REGULAR) ?: publicKey
|
return contact?.displayName(Contact.ContactContext.REGULAR) ?: publicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recipient.isClosedGroupRecipient) {
|
if (recipient.isLegacyClosedGroupRecipient) {
|
||||||
val members = DatabaseComponent.get(context).groupDatabase()
|
val members = DatabaseComponent.get(context).groupDatabase()
|
||||||
.getGroupMemberAddresses(recipient.address.toGroupString(), true)
|
.getGroupMemberAddresses(recipient.address.toGroupString(), true)
|
||||||
.sorted()
|
.sorted()
|
||||||
|
|
|
@ -52,7 +52,7 @@ class ContactSelectionListLoader(context: Context, val mode: Int, val filter: St
|
||||||
|
|
||||||
private fun getClosedGroups(contacts: List<Recipient>): List<ContactSelectionListItem> {
|
private fun getClosedGroups(contacts: List<Recipient>): List<ContactSelectionListItem> {
|
||||||
return getItems(contacts, context.getString(R.string.fragment_contact_selection_closed_groups_title)) {
|
return getItems(contacts, context.getString(R.string.fragment_contact_selection_closed_groups_title)) {
|
||||||
it.address.isClosedGroup
|
it.address.isLegacyClosedGroup || it.address.isClosedGroup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,6 @@ class ConversationSettingsActivity: PassphraseRequiredActionBarActivity(), View.
|
||||||
super.onCreate(savedInstanceState, ready)
|
super.onCreate(savedInstanceState, ready)
|
||||||
binding = ActivityConversationSettingsBinding.inflate(layoutInflater)
|
binding = ActivityConversationSettingsBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
binding.profilePictureView.root.glide = GlideApp.with(this)
|
|
||||||
updateRecipientDisplay()
|
updateRecipientDisplay()
|
||||||
binding.searchConversation.setOnClickListener(this)
|
binding.searchConversation.setOnClickListener(this)
|
||||||
binding.clearMessages.setOnClickListener(this)
|
binding.clearMessages.setOnClickListener(this)
|
||||||
|
@ -91,7 +90,7 @@ class ConversationSettingsActivity: PassphraseRequiredActionBarActivity(), View.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle group-specific settings
|
// Toggle group-specific settings
|
||||||
val areGroupOptionsVisible = recipient.isClosedGroupRecipient
|
val areGroupOptionsVisible = recipient.isClosedGroupRecipient || recipient.isLegacyClosedGroupRecipient
|
||||||
groupOptions.forEach { v ->
|
groupOptions.forEach { v ->
|
||||||
v.isVisible = areGroupOptionsVisible
|
v.isVisible = areGroupOptionsVisible
|
||||||
}
|
}
|
||||||
|
@ -164,7 +163,7 @@ class ConversationSettingsActivity: PassphraseRequiredActionBarActivity(), View.
|
||||||
}
|
}
|
||||||
v === binding.editGroup -> {
|
v === binding.editGroup -> {
|
||||||
val recipient = viewModel.recipient ?: return
|
val recipient = viewModel.recipient ?: return
|
||||||
if (!recipient.isClosedGroupRecipient) return
|
if (!recipient.isClosedGroupRecipient || !recipient.isLegacyClosedGroupRecipient) return
|
||||||
val intent = Intent(this, EditClosedGroupActivity::class.java)
|
val intent = Intent(this, EditClosedGroupActivity::class.java)
|
||||||
val groupID: String = recipient.address.toGroupString()
|
val groupID: String = recipient.address.toGroupString()
|
||||||
intent.putExtra(EditClosedGroupActivity.groupIDKey, groupID)
|
intent.putExtra(EditClosedGroupActivity.groupIDKey, groupID)
|
||||||
|
|
|
@ -18,11 +18,11 @@ class ConversationSettingsViewModel(
|
||||||
|
|
||||||
val recipient get() = storage.getRecipientForThread(threadId)
|
val recipient get() = storage.getRecipientForThread(threadId)
|
||||||
|
|
||||||
fun isPinned() = storage.isThreadPinned(threadId)
|
fun isPinned() = storage.isPinned(threadId)
|
||||||
|
|
||||||
fun togglePin() = viewModelScope.launch {
|
fun togglePin() = viewModelScope.launch {
|
||||||
val isPinned = storage.isThreadPinned(threadId)
|
val isPinned = storage.isPinned(threadId)
|
||||||
storage.setThreadPinned(threadId, !isPinned)
|
storage.setPinned(threadId, !isPinned)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun autoDownloadAttachments() = recipient?.let { recipient -> storage.shouldAutoDownloadAttachments(recipient) } ?: false
|
fun autoDownloadAttachments() = recipient?.let { recipient -> storage.shouldAutoDownloadAttachments(recipient) } ?: false
|
||||||
|
@ -32,7 +32,7 @@ class ConversationSettingsViewModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isUserGroupAdmin(): Boolean = recipient?.let { recipient ->
|
fun isUserGroupAdmin(): Boolean = recipient?.let { recipient ->
|
||||||
if (!recipient.isClosedGroupRecipient) return@let false
|
if (!recipient.isLegacyClosedGroupRecipient || !recipient.isClosedGroupRecipient) return@let false
|
||||||
val localUserAddress = prefs.getLocalNumber() ?: return@let false
|
val localUserAddress = prefs.getLocalNumber() ?: return@let false
|
||||||
val group = storage.getGroup(recipient.address.toGroupString())
|
val group = storage.getGroup(recipient.address.toGroupString())
|
||||||
group?.admins?.contains(Address.fromSerialized(localUserAddress)) ?: false // this will have to be replaced for new closed groups
|
group?.admins?.contains(Address.fromSerialized(localUserAddress)) ?: false // this will have to be replaced for new closed groups
|
||||||
|
|
|
@ -592,7 +592,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||||
recipient.isLocalNumber -> getString(R.string.note_to_self)
|
recipient.isLocalNumber -> getString(R.string.note_to_self)
|
||||||
else -> recipient.toShortString()
|
else -> recipient.toShortString()
|
||||||
}
|
}
|
||||||
@DimenRes val sizeID: Int = if (viewModel.recipient?.isClosedGroupRecipient == true) {
|
@DimenRes val sizeID: Int = if (viewModel.recipient?.isLegacyClosedGroupRecipient == true) {
|
||||||
R.dimen.medium_profile_picture_size
|
R.dimen.medium_profile_picture_size
|
||||||
} else {
|
} else {
|
||||||
R.dimen.small_profile_picture_size
|
R.dimen.small_profile_picture_size
|
||||||
|
@ -823,8 +823,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showOrHideInputIfNeeded() {
|
private fun showOrHideInputIfNeeded() {
|
||||||
val recipient = viewModel.recipient
|
val recipient = viewModel.recipient ?: return
|
||||||
if (recipient != null && recipient.isClosedGroupRecipient) {
|
if (recipient.isLegacyClosedGroupRecipient) {
|
||||||
val group = groupDb.getGroup(recipient.address.toGroupString()).orNull()
|
val group = groupDb.getGroup(recipient.address.toGroupString()).orNull()
|
||||||
val isActive = (group?.isActive == true)
|
val isActive = (group?.isActive == true)
|
||||||
binding?.inputBar?.showInput = isActive
|
binding?.inputBar?.showInput = isActive
|
||||||
|
@ -1157,7 +1157,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(v: View?) {
|
override fun onClick(v: View?) {
|
||||||
if (v === binding?.toolbarContent?.profilePictureView?.root) {
|
if (v === binding?.toolbarContent?.profilePictureView) {
|
||||||
// open conversation settings
|
// open conversation settings
|
||||||
conversationSettingsCallback.launch(viewModel.threadId)
|
conversationSettingsCallback.launch(viewModel.threadId)
|
||||||
}
|
}
|
||||||
|
@ -1197,8 +1197,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||||
Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: don't need to allow new closed group check here, removed in new disappearing messages
|
||||||
override fun showExpiringMessagesDialog(thread: Recipient) {
|
override fun showExpiringMessagesDialog(thread: Recipient) {
|
||||||
if (thread.isClosedGroupRecipient) {
|
if (thread.isLegacyClosedGroupRecipient) {
|
||||||
val group = groupDb.getGroup(thread.address.toGroupString()).orNull()
|
val group = groupDb.getGroup(thread.address.toGroupString()).orNull()
|
||||||
if (group?.isActive == false) { return }
|
if (group?.isActive == false) { return }
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ class DeleteOptionsBottomSheet : BottomSheetDialogFragment(), View.OnClickListen
|
||||||
binding.deleteForEveryoneTextView.text =
|
binding.deleteForEveryoneTextView.text =
|
||||||
resources.getString(R.string.delete_message_for_me_and_recipient, contact)
|
resources.getString(R.string.delete_message_for_me_and_recipient, contact)
|
||||||
}
|
}
|
||||||
binding.deleteForEveryoneTextView.isVisible = !recipient.isClosedGroupRecipient
|
binding.deleteForEveryoneTextView.isVisible = !recipient.isLegacyClosedGroupRecipient
|
||||||
binding.deleteForMeTextView.setOnClickListener(this)
|
binding.deleteForMeTextView.setOnClickListener(this)
|
||||||
binding.deleteForEveryoneTextView.setOnClickListener(this)
|
binding.deleteForEveryoneTextView.setOnClickListener(this)
|
||||||
binding.cancelTextView.setOnClickListener(this)
|
binding.cancelTextView.setOnClickListener(this)
|
||||||
|
|
|
@ -55,6 +55,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ViewVisibleMessageContentBinding
|
import network.loki.messenger.databinding.ViewVisibleMessageContentBinding
|
||||||
|
import org.session.libsession.database.StorageProtocol
|
||||||
import org.thoughtcrime.securesms.MediaPreviewActivity.getPreviewIntent
|
import org.thoughtcrime.securesms.MediaPreviewActivity.getPreviewIntent
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.database.Storage
|
import org.thoughtcrime.securesms.database.Storage
|
||||||
|
|
|
@ -9,7 +9,6 @@ import android.text.style.StyleSpan
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.DialogDownloadBinding
|
|
||||||
import org.session.libsession.database.StorageProtocol
|
import org.session.libsession.database.StorageProtocol
|
||||||
import org.session.libsession.messaging.contacts.Contact
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||||
|
@ -31,20 +30,21 @@ class AutoDownloadDialog(private val threadRecipient: Recipient,
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
||||||
val threadId = storage.getThreadId(threadRecipient) ?: run {
|
val threadId = storage.getThreadId(threadRecipient) ?: run {
|
||||||
dismiss()
|
dismiss()
|
||||||
return
|
return@createSessionDialog
|
||||||
}
|
}
|
||||||
|
|
||||||
val displayName = when {
|
val displayName = when {
|
||||||
threadRecipient.isOpenGroupRecipient -> storage.getOpenGroup(threadId)?.name ?: "UNKNOWN"
|
threadRecipient.isOpenGroupRecipient -> storage.getOpenGroup(threadId)?.name ?: "UNKNOWN"
|
||||||
threadRecipient.isClosedGroupRecipient -> storage.getGroup(threadRecipient.address.toGroupString())?.title ?: "UNKNOWN"
|
threadRecipient.isLegacyClosedGroupRecipient -> storage.getGroup(threadRecipient.address.toGroupString())?.title ?: "UNKNOWN"
|
||||||
|
// TODO: threadRecipient.isClosedGroupRecipient -> storage.getLibSessionGroup(threadRecipient.address.serialize())?.groupName ?: "UNKNOWN" or something
|
||||||
else -> storage.getContactWithSessionID(threadRecipient.address.serialize())?.displayName(Contact.ContactContext.REGULAR) ?: "UNKNOWN"
|
else -> storage.getContactWithSessionID(threadRecipient.address.serialize())?.displayName(Contact.ContactContext.REGULAR) ?: "UNKNOWN"
|
||||||
}
|
}
|
||||||
title(resources.getString(R.string.dialog_auto_download_title))
|
title(resources.getString(R.string.dialog_auto_download_title))
|
||||||
|
|
||||||
val explanation = resources.getString(R.string.dialog_auto_download_explanation, displayName)
|
val explanation = resources.getString(R.string.dialog_auto_download_explanation, displayName)
|
||||||
val spannable = SpannableStringBuilder(explanation)
|
val spannable = SpannableStringBuilder(explanation)
|
||||||
val startIndex = explanation.indexOf(name)
|
val startIndex = explanation.indexOf(displayName)
|
||||||
spannable.setSpan(StyleSpan(Typeface.BOLD), startIndex, startIndex + name.count(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
spannable.setSpan(StyleSpan(Typeface.BOLD), startIndex, startIndex + displayName.count(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
text(spannable)
|
text(spannable)
|
||||||
|
|
||||||
button(R.string.dialog_download_button_title, R.string.AccessibilityId_download_media) {
|
button(R.string.dialog_download_button_title, R.string.AccessibilityId_download_media) {
|
||||||
|
|
|
@ -63,7 +63,7 @@ object ConversationMenuHelper {
|
||||||
// Base menu (options that should always be present)
|
// Base menu (options that should always be present)
|
||||||
inflater.inflate(R.menu.menu_conversation, menu)
|
inflater.inflate(R.menu.menu_conversation, menu)
|
||||||
// Expiring messages
|
// Expiring messages
|
||||||
if (!isOpenGroup && (thread.hasApprovedMe() || thread.isClosedGroupRecipient) && !thread.isBlocked) {
|
if (!isOpenGroup && (thread.hasApprovedMe() || thread.isLegacyClosedGroupRecipient) && !thread.isBlocked) {
|
||||||
if (thread.expireMessages > 0) {
|
if (thread.expireMessages > 0) {
|
||||||
inflater.inflate(R.menu.menu_conversation_expiration_on, menu)
|
inflater.inflate(R.menu.menu_conversation_expiration_on, menu)
|
||||||
val item = menu.findItem(R.id.menu_expiring_messages)
|
val item = menu.findItem(R.id.menu_expiring_messages)
|
||||||
|
@ -92,7 +92,7 @@ object ConversationMenuHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Closed group menu (options that should only be present in closed groups)
|
// Closed group menu (options that should only be present in closed groups)
|
||||||
if (thread.isClosedGroupRecipient) {
|
if (thread.isLegacyClosedGroupRecipient) {
|
||||||
inflater.inflate(R.menu.menu_conversation_closed_group, menu)
|
inflater.inflate(R.menu.menu_conversation_closed_group, menu)
|
||||||
}
|
}
|
||||||
// Open group menu
|
// Open group menu
|
||||||
|
@ -280,7 +280,7 @@ object ConversationMenuHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun editClosedGroup(context: Context, thread: Recipient) {
|
private fun editClosedGroup(context: Context, thread: Recipient) {
|
||||||
if (!thread.isClosedGroupRecipient) { return }
|
if (!thread.isLegacyClosedGroupRecipient) { return }
|
||||||
val intent = Intent(context, EditClosedGroupActivity::class.java)
|
val intent = Intent(context, EditClosedGroupActivity::class.java)
|
||||||
val groupID: String = thread.address.toGroupString()
|
val groupID: String = thread.address.toGroupString()
|
||||||
intent.putExtra(groupIDKey, groupID)
|
intent.putExtra(groupIDKey, groupID)
|
||||||
|
@ -288,7 +288,7 @@ object ConversationMenuHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun leaveClosedGroup(context: Context, thread: Recipient) {
|
private fun leaveClosedGroup(context: Context, thread: Recipient) {
|
||||||
if (!thread.isClosedGroupRecipient) { return }
|
if (!thread.isLegacyClosedGroupRecipient) { return }
|
||||||
|
|
||||||
val group = DatabaseComponent.get(context).groupDatabase().getGroup(thread.address.toGroupString()).orNull()
|
val group = DatabaseComponent.get(context).groupDatabase().getGroup(thread.address.toGroupString()).orNull()
|
||||||
val admins = group.admins
|
val admins = group.admins
|
||||||
|
|
|
@ -64,7 +64,6 @@ class VisibleMessageContentView : ConstraintLayout {
|
||||||
glide: GlideRequests = GlideApp.with(this),
|
glide: GlideRequests = GlideApp.with(this),
|
||||||
thread: Recipient,
|
thread: Recipient,
|
||||||
searchQuery: String? = null,
|
searchQuery: String? = null,
|
||||||
contactIsTrusted: Boolean = true,
|
|
||||||
onAttachmentNeedsDownload: (Long, Long) -> Unit,
|
onAttachmentNeedsDownload: (Long, Long) -> Unit,
|
||||||
suppressThumbnails: Boolean = false
|
suppressThumbnails: Boolean = false
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -11,23 +11,29 @@ object MentionManagerUtilities {
|
||||||
fun populateUserPublicKeyCacheIfNeeded(threadID: Long, context: Context) {
|
fun populateUserPublicKeyCacheIfNeeded(threadID: Long, context: Context) {
|
||||||
val result = mutableSetOf<String>()
|
val result = mutableSetOf<String>()
|
||||||
val recipient = DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(threadID) ?: return
|
val recipient = DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(threadID) ?: return
|
||||||
if (recipient.address.isClosedGroup) {
|
when {
|
||||||
val members = DatabaseComponent.get(context).groupDatabase().getGroupMembers(recipient.address.toGroupString(), false).map { it.address.serialize() }
|
recipient.address.isLegacyClosedGroup -> {
|
||||||
result.addAll(members)
|
val members = DatabaseComponent.get(context).groupDatabase().getGroupMembers(recipient.address.toGroupString(), false).map { it.address.serialize() }
|
||||||
} else {
|
result.addAll(members)
|
||||||
val messageDatabase = DatabaseComponent.get(context).mmsSmsDatabase()
|
}
|
||||||
val reader = messageDatabase.readerFor(messageDatabase.getConversation(threadID, true, 0, 200))
|
recipient.address.isClosedGroup -> {
|
||||||
var record: MessageRecord? = reader.next
|
TODO("get members from libsession via storage")
|
||||||
while (record != null) {
|
}
|
||||||
result.add(record.individualRecipient.address.serialize())
|
recipient.address.isOpenGroup -> {
|
||||||
try {
|
val messageDatabase = DatabaseComponent.get(context).mmsSmsDatabase()
|
||||||
record = reader.next
|
val reader = messageDatabase.readerFor(messageDatabase.getConversation(threadID, true, 0, 200))
|
||||||
} catch (exception: Exception) {
|
var record: MessageRecord? = reader.next
|
||||||
record = null
|
while (record != null) {
|
||||||
}
|
result.add(record.individualRecipient.address.serialize())
|
||||||
|
try {
|
||||||
|
record = reader.next
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
record = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.close()
|
||||||
|
result.add(TextSecurePreferences.getLocalNumber(context)!!)
|
||||||
}
|
}
|
||||||
reader.close()
|
|
||||||
result.add(TextSecurePreferences.getLocalNumber(context)!!)
|
|
||||||
}
|
}
|
||||||
MentionsManager.userPublicKeyCache[threadID] = result
|
MentionsManager.userPublicKeyCache[threadID] = result
|
||||||
}
|
}
|
||||||
|
|
|
@ -932,7 +932,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||||
cursor?.close()
|
cursor?.close()
|
||||||
}
|
}
|
||||||
val threadDb = get(context).threadDatabase()
|
val threadDb = get(context).threadDatabase()
|
||||||
threadDb.update(threadId, false)
|
threadDb.update(threadId, false, false)
|
||||||
notifyConversationListeners(threadId)
|
notifyConversationListeners(threadId)
|
||||||
notifyStickerListeners()
|
notifyStickerListeners()
|
||||||
notifyStickerPackListeners()
|
notifyStickerPackListeners()
|
||||||
|
@ -959,7 +959,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||||
cursor?.close()
|
cursor?.close()
|
||||||
}
|
}
|
||||||
val threadDb = get(context).threadDatabase()
|
val threadDb = get(context).threadDatabase()
|
||||||
threadDb.update(threadId, false)
|
threadDb.update(threadId, false, true)
|
||||||
notifyConversationListeners(threadId)
|
notifyConversationListeners(threadId)
|
||||||
notifyStickerListeners()
|
notifyStickerListeners()
|
||||||
notifyStickerPackListeners()
|
notifyStickerPackListeners()
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.net.Uri
|
||||||
import network.loki.messenger.libsession_util.ConfigBase
|
import network.loki.messenger.libsession_util.ConfigBase
|
||||||
import network.loki.messenger.libsession_util.ConfigBase.Companion.PRIORITY_HIDDEN
|
import network.loki.messenger.libsession_util.ConfigBase.Companion.PRIORITY_HIDDEN
|
||||||
import network.loki.messenger.libsession_util.ConfigBase.Companion.PRIORITY_PINNED
|
import network.loki.messenger.libsession_util.ConfigBase.Companion.PRIORITY_PINNED
|
||||||
|
import network.loki.messenger.libsession_util.ConfigBase.Companion.PRIORITY_VISIBLE
|
||||||
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.UserGroupsConfig
|
import network.loki.messenger.libsession_util.UserGroupsConfig
|
||||||
|
@ -101,20 +102,26 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||||
val volatile = configFactory.convoVolatile ?: return
|
val volatile = configFactory.convoVolatile ?: return
|
||||||
if (address.isGroup) {
|
if (address.isGroup) {
|
||||||
val groups = configFactory.userGroups ?: return
|
val groups = configFactory.userGroups ?: return
|
||||||
if (address.isClosedGroup) {
|
when {
|
||||||
val sessionId = GroupUtil.doubleDecodeGroupId(address.serialize())
|
address.isLegacyClosedGroup -> {
|
||||||
val closedGroup = getGroup(address.toGroupString())
|
val sessionId = GroupUtil.doubleDecodeGroupId(address.serialize())
|
||||||
if (closedGroup != null && closedGroup.isActive) {
|
val closedGroup = getGroup(address.toGroupString())
|
||||||
val legacyGroup = groups.getOrConstructLegacyGroupInfo(sessionId)
|
if (closedGroup != null && closedGroup.isActive) {
|
||||||
groups.set(legacyGroup)
|
val legacyGroup = groups.getOrConstructLegacyGroupInfo(sessionId)
|
||||||
val newVolatileParams = volatile.getOrConstructLegacyGroup(sessionId).copy(
|
groups.set(legacyGroup)
|
||||||
lastRead = SnodeAPI.nowWithOffset,
|
val newVolatileParams = volatile.getOrConstructLegacyGroup(sessionId).copy(
|
||||||
)
|
lastRead = SnodeAPI.nowWithOffset,
|
||||||
volatile.set(newVolatileParams)
|
)
|
||||||
|
volatile.set(newVolatileParams)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
address.isClosedGroup -> {
|
||||||
|
Log.w("Loki", "Thread created called for new closed group address, not adding any extra information")
|
||||||
|
}
|
||||||
|
address.isOpenGroup -> {
|
||||||
|
// these should be added on the group join / group info fetch
|
||||||
|
Log.w("Loki", "Thread created called for open group address, not adding any extra information")
|
||||||
}
|
}
|
||||||
} else if (address.isOpenGroup) {
|
|
||||||
// these should be added on the group join / group info fetch
|
|
||||||
Log.w("Loki", "Thread created called for open group address, not adding any extra information")
|
|
||||||
}
|
}
|
||||||
} else if (address.isContact) {
|
} else if (address.isContact) {
|
||||||
// non-standard contact prefixes: 15, 00 etc shouldn't be stored in config
|
// non-standard contact prefixes: 15, 00 etc shouldn't be stored in config
|
||||||
|
@ -123,11 +130,11 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||||
if (getUserPublicKey() != address.serialize()) {
|
if (getUserPublicKey() != address.serialize()) {
|
||||||
val contacts = configFactory.contacts ?: return
|
val contacts = configFactory.contacts ?: return
|
||||||
contacts.upsertContact(address.serialize()) {
|
contacts.upsertContact(address.serialize()) {
|
||||||
priority = ConfigBase.PRIORITY_VISIBLE
|
priority = PRIORITY_VISIBLE
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val userProfile = configFactory.user ?: return
|
val userProfile = configFactory.user ?: return
|
||||||
userProfile.setNtsPriority(ConfigBase.PRIORITY_VISIBLE)
|
userProfile.setNtsPriority(PRIORITY_VISIBLE)
|
||||||
DatabaseComponent.get(context).threadDatabase().setHasSent(threadId, true)
|
DatabaseComponent.get(context).threadDatabase().setHasSent(threadId, true)
|
||||||
}
|
}
|
||||||
val newVolatileParams = volatile.getOrConstructOneToOne(address.serialize())
|
val newVolatileParams = volatile.getOrConstructOneToOne(address.serialize())
|
||||||
|
@ -241,7 +248,8 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||||
configFactory.convoVolatile?.let { config ->
|
configFactory.convoVolatile?.let { config ->
|
||||||
val convo = when {
|
val convo = when {
|
||||||
// recipient closed group
|
// recipient closed group
|
||||||
recipient.isClosedGroupRecipient -> config.getOrConstructLegacyGroup(GroupUtil.doubleDecodeGroupId(recipient.address.serialize()))
|
recipient.isLegacyClosedGroupRecipient -> config.getOrConstructLegacyGroup(GroupUtil.doubleDecodeGroupId(recipient.address.serialize()))
|
||||||
|
recipient.isClosedGroupRecipient -> config.getOrConstructGroup(recipient.address.serialize())
|
||||||
// recipient is open group
|
// recipient is open group
|
||||||
recipient.isOpenGroupRecipient -> {
|
recipient.isOpenGroupRecipient -> {
|
||||||
val openGroupJoinUrl = getOpenGroup(threadId)?.joinURL ?: return
|
val openGroupJoinUrl = getOpenGroup(threadId)?.joinURL ?: return
|
||||||
|
@ -848,7 +856,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||||
sessionId = groupPublicKey,
|
sessionId = groupPublicKey,
|
||||||
name = name,
|
name = name,
|
||||||
members = members,
|
members = members,
|
||||||
priority = ConfigBase.PRIORITY_VISIBLE,
|
priority = PRIORITY_VISIBLE,
|
||||||
encPubKey = (encryptionKeyPair.publicKey as DjbECPublicKey).publicKey, // 'serialize()' inserts an extra byte
|
encPubKey = (encryptionKeyPair.publicKey as DjbECPublicKey).publicKey, // 'serialize()' inserts an extra byte
|
||||||
encSecKey = encryptionKeyPair.privateKey.serialize(),
|
encSecKey = encryptionKeyPair.privateKey.serialize(),
|
||||||
disappearingTimer = 0L,
|
disappearingTimer = 0L,
|
||||||
|
@ -884,7 +892,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||||
members = membersMap,
|
members = membersMap,
|
||||||
encPubKey = (latestKeyPair.publicKey as DjbECPublicKey).publicKey, // 'serialize()' inserts an extra byte
|
encPubKey = (latestKeyPair.publicKey as DjbECPublicKey).publicKey, // 'serialize()' inserts an extra byte
|
||||||
encSecKey = latestKeyPair.privateKey.serialize(),
|
encSecKey = latestKeyPair.privateKey.serialize(),
|
||||||
priority = if (isPinned(threadID)) PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE,
|
priority = if (isPinned(threadID)) PRIORITY_PINNED else PRIORITY_VISIBLE,
|
||||||
disappearingTimer = recipientSettings.expireMessages.toLong(),
|
disappearingTimer = recipientSettings.expireMessages.toLong(),
|
||||||
joinedAt = (existingGroup.formationTimestamp / 1000L)
|
joinedAt = (existingGroup.formationTimestamp / 1000L)
|
||||||
)
|
)
|
||||||
|
@ -1264,27 +1272,36 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||||
val threadRecipient = getRecipientForThread(threadID) ?: return
|
val threadRecipient = getRecipientForThread(threadID) ?: return
|
||||||
if (threadRecipient.isLocalNumber) {
|
if (threadRecipient.isLocalNumber) {
|
||||||
val user = configFactory.user ?: return
|
val user = configFactory.user ?: return
|
||||||
user.setNtsPriority(if (isPinned) PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE)
|
user.setNtsPriority(if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE)
|
||||||
} else if (threadRecipient.isContactRecipient) {
|
} else if (threadRecipient.isContactRecipient) {
|
||||||
val contacts = configFactory.contacts ?: return
|
val contacts = configFactory.contacts ?: return
|
||||||
contacts.upsertContact(threadRecipient.address.serialize()) {
|
contacts.upsertContact(threadRecipient.address.serialize()) {
|
||||||
priority = if (isPinned) PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE
|
priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE
|
||||||
}
|
}
|
||||||
} else if (threadRecipient.isGroupRecipient) {
|
} else if (threadRecipient.isGroupRecipient) {
|
||||||
val groups = configFactory.userGroups ?: return
|
val groups = configFactory.userGroups ?: return
|
||||||
if (threadRecipient.isClosedGroupRecipient) {
|
when {
|
||||||
val sessionId = GroupUtil.doubleDecodeGroupId(threadRecipient.address.serialize())
|
threadRecipient.isLegacyClosedGroupRecipient -> {
|
||||||
val newGroupInfo = groups.getOrConstructLegacyGroupInfo(sessionId).copy (
|
val sessionId = GroupUtil.doubleDecodeGroupId(threadRecipient.address.serialize())
|
||||||
priority = if (isPinned) PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE
|
val newGroupInfo = groups.getOrConstructLegacyGroupInfo(sessionId).copy (
|
||||||
)
|
priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE
|
||||||
groups.set(newGroupInfo)
|
)
|
||||||
} else if (threadRecipient.isOpenGroupRecipient) {
|
groups.set(newGroupInfo)
|
||||||
val openGroup = getOpenGroup(threadID) ?: return
|
}
|
||||||
val (baseUrl, room, pubKeyHex) = BaseCommunityInfo.parseFullUrl(openGroup.joinURL) ?: return
|
threadRecipient.isClosedGroupRecipient -> {
|
||||||
val newGroupInfo = groups.getOrConstructCommunityInfo(baseUrl, room, Hex.toStringCondensed(pubKeyHex)).copy (
|
val newGroupInfo = groups.getGroupInfo(threadRecipient.address.serialize()).copy (
|
||||||
priority = if (isPinned) PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE
|
priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE
|
||||||
)
|
)
|
||||||
groups.set(newGroupInfo)
|
groups.set(newGroupInfo)
|
||||||
|
}
|
||||||
|
threadRecipient.isOpenGroupRecipient -> {
|
||||||
|
val openGroup = getOpenGroup(threadID) ?: return
|
||||||
|
val (baseUrl, room, pubKeyHex) = BaseCommunityInfo.parseFullUrl(openGroup.joinURL) ?: return
|
||||||
|
val newGroupInfo = groups.getOrConstructCommunityInfo(baseUrl, room, Hex.toStringCondensed(pubKeyHex)).copy (
|
||||||
|
priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE
|
||||||
|
)
|
||||||
|
groups.set(newGroupInfo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
|
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
|
||||||
|
@ -1341,7 +1358,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||||
} else {
|
} else {
|
||||||
smsDb.deleteMessagesFrom(threadID, fromUser.serialize())
|
smsDb.deleteMessagesFrom(threadID, fromUser.serialize())
|
||||||
mmsDb.deleteMessagesFrom(threadID, fromUser.serialize())
|
mmsDb.deleteMessagesFrom(threadID, fromUser.serialize())
|
||||||
threadDb.update(threadID, false)
|
threadDb.update(threadID, false, true)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
package org.thoughtcrime.securesms.database;
|
package org.thoughtcrime.securesms.database;
|
||||||
|
|
||||||
import static org.session.libsession.utilities.GroupUtil.CLOSED_GROUP_PREFIX;
|
import static org.session.libsession.utilities.GroupUtil.LEGACY_CLOSED_GROUP_PREFIX;
|
||||||
import static org.session.libsession.utilities.GroupUtil.OPEN_GROUP_PREFIX;
|
import static org.session.libsession.utilities.GroupUtil.OPEN_GROUP_PREFIX;
|
||||||
import static org.thoughtcrime.securesms.database.GroupDatabase.GROUP_ID;
|
import static org.thoughtcrime.securesms.database.GroupDatabase.GROUP_ID;
|
||||||
|
|
||||||
|
@ -503,7 +503,7 @@ public class ThreadDatabase extends Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor getApprovedConversationList() {
|
public Cursor getApprovedConversationList() {
|
||||||
String where = "((" + HAS_SENT + " = 1 OR " + RecipientDatabase.APPROVED + " = 1 OR "+ GroupDatabase.TABLE_NAME +"."+GROUP_ID+" LIKE '"+CLOSED_GROUP_PREFIX+"%') OR " + GroupDatabase.TABLE_NAME + "." + GROUP_ID + " LIKE '" + OPEN_GROUP_PREFIX + "%') " +
|
String where = "((" + HAS_SENT + " = 1 OR " + RecipientDatabase.APPROVED + " = 1 OR "+ GroupDatabase.TABLE_NAME +"."+GROUP_ID+" LIKE '"+ LEGACY_CLOSED_GROUP_PREFIX +"%') OR " + GroupDatabase.TABLE_NAME + "." + GROUP_ID + " LIKE '" + OPEN_GROUP_PREFIX + "%') " +
|
||||||
"AND " + ARCHIVED + " = 0 ";
|
"AND " + ARCHIVED + " = 0 ";
|
||||||
return getConversationList(where);
|
return getConversationList(where);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.thoughtcrime.securesms.dependencies
|
||||||
|
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import org.session.libsession.database.StorageProtocol
|
||||||
|
import org.thoughtcrime.securesms.database.Storage
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
abstract class DatabaseBindings {
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindStorageProtocol(storage: Storage): StorageProtocol
|
||||||
|
|
||||||
|
}
|
|
@ -42,7 +42,7 @@ interface DatabaseComponent {
|
||||||
fun sessionContactDatabase(): SessionContactDatabase
|
fun sessionContactDatabase(): SessionContactDatabase
|
||||||
fun reactionDatabase(): ReactionDatabase
|
fun reactionDatabase(): ReactionDatabase
|
||||||
fun emojiSearchDatabase(): EmojiSearchDatabase
|
fun emojiSearchDatabase(): EmojiSearchDatabase
|
||||||
fun storage(): StorageProtocol
|
fun storage(): Storage
|
||||||
fun attachmentProvider(): MessageDataProvider
|
fun attachmentProvider(): MessageDataProvider
|
||||||
fun blindedIdMappingDatabase(): BlindedIdMappingDatabase
|
fun blindedIdMappingDatabase(): BlindedIdMappingDatabase
|
||||||
fun groupMemberDatabase(): GroupMemberDatabase
|
fun groupMemberDatabase(): GroupMemberDatabase
|
||||||
|
|
|
@ -273,13 +273,13 @@ object ConfigurationMessageUtilities {
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val DELETE_INACTIVE_GROUPS: String = """
|
val DELETE_INACTIVE_GROUPS: String = """
|
||||||
DELETE FROM ${GroupDatabase.TABLE_NAME} WHERE ${GroupDatabase.GROUP_ID} IN (SELECT ${ThreadDatabase.ADDRESS} FROM ${ThreadDatabase.TABLE_NAME} WHERE ${ThreadDatabase.MESSAGE_COUNT} <= 0 AND ${ThreadDatabase.ADDRESS} LIKE '${GroupUtil.CLOSED_GROUP_PREFIX}%');
|
DELETE FROM ${GroupDatabase.TABLE_NAME} WHERE ${GroupDatabase.GROUP_ID} IN (SELECT ${ThreadDatabase.ADDRESS} FROM ${ThreadDatabase.TABLE_NAME} WHERE ${ThreadDatabase.MESSAGE_COUNT} <= 0 AND ${ThreadDatabase.ADDRESS} LIKE '${GroupUtil.LEGACY_CLOSED_GROUP_PREFIX}%');
|
||||||
DELETE FROM ${ThreadDatabase.TABLE_NAME} WHERE ${ThreadDatabase.ADDRESS} IN (SELECT ${ThreadDatabase.ADDRESS} FROM ${ThreadDatabase.TABLE_NAME} WHERE ${ThreadDatabase.MESSAGE_COUNT} <= 0 AND ${ThreadDatabase.ADDRESS} LIKE '${GroupUtil.CLOSED_GROUP_PREFIX}%');
|
DELETE FROM ${ThreadDatabase.TABLE_NAME} WHERE ${ThreadDatabase.ADDRESS} IN (SELECT ${ThreadDatabase.ADDRESS} FROM ${ThreadDatabase.TABLE_NAME} WHERE ${ThreadDatabase.MESSAGE_COUNT} <= 0 AND ${ThreadDatabase.ADDRESS} LIKE '${GroupUtil.LEGACY_CLOSED_GROUP_PREFIX}%');
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val DELETE_INACTIVE_ONE_TO_ONES: String = """
|
val DELETE_INACTIVE_ONE_TO_ONES: String = """
|
||||||
DELETE FROM ${ThreadDatabase.TABLE_NAME} WHERE ${ThreadDatabase.MESSAGE_COUNT} <= 0 AND ${ThreadDatabase.ADDRESS} NOT LIKE '${GroupUtil.CLOSED_GROUP_PREFIX}%' AND ${ThreadDatabase.ADDRESS} NOT LIKE '${GroupUtil.OPEN_GROUP_PREFIX}%' AND ${ThreadDatabase.ADDRESS} NOT LIKE '${GroupUtil.OPEN_GROUP_INBOX_PREFIX}%';
|
DELETE FROM ${ThreadDatabase.TABLE_NAME} WHERE ${ThreadDatabase.MESSAGE_COUNT} <= 0 AND ${ThreadDatabase.ADDRESS} NOT LIKE '${GroupUtil.LEGACY_CLOSED_GROUP_PREFIX}%' AND ${ThreadDatabase.ADDRESS} NOT LIKE '${GroupUtil.OPEN_GROUP_PREFIX}%' AND ${ThreadDatabase.ADDRESS} NOT LIKE '${GroupUtil.OPEN_GROUP_INBOX_PREFIX}%';
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
}
|
}
|
|
@ -157,14 +157,14 @@ data class ConfigurationSyncJob(val destination: Destination): Job {
|
||||||
|
|
||||||
fun Destination.destinationPublicKey(): String = when (this) {
|
fun Destination.destinationPublicKey(): String = when (this) {
|
||||||
is Destination.Contact -> publicKey
|
is Destination.Contact -> publicKey
|
||||||
is Destination.ClosedGroup -> groupPublicKey
|
is Destination.ClosedGroup -> publicKey
|
||||||
else -> throw NullPointerException("Not public key for this destination")
|
else -> throw NullPointerException("Not public key for this destination")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serialize(): Data {
|
override fun serialize(): Data {
|
||||||
val (type, address) = when (destination) {
|
val (type, address) = when (destination) {
|
||||||
is Destination.Contact -> CONTACT_TYPE to destination.publicKey
|
is Destination.Contact -> CONTACT_TYPE to destination.publicKey
|
||||||
is Destination.ClosedGroup -> GROUP_TYPE to destination.groupPublicKey
|
is Destination.ClosedGroup -> GROUP_TYPE to destination.publicKey
|
||||||
else -> return Data.EMPTY
|
else -> return Data.EMPTY
|
||||||
}
|
}
|
||||||
return Data.Builder()
|
return Data.Builder()
|
||||||
|
|
|
@ -10,12 +10,15 @@ sealed class Destination {
|
||||||
data class Contact(var publicKey: String) : Destination() {
|
data class Contact(var publicKey: String) : Destination() {
|
||||||
internal constructor(): this("")
|
internal constructor(): this("")
|
||||||
}
|
}
|
||||||
data class ClosedGroup(var groupPublicKey: String) : Destination() {
|
data class LegacyClosedGroup(var groupPublicKey: String) : Destination() {
|
||||||
internal constructor(): this("")
|
internal constructor(): this("")
|
||||||
}
|
}
|
||||||
data class LegacyOpenGroup(var roomToken: String, var server: String) : Destination() {
|
data class LegacyOpenGroup(var roomToken: String, var server: String) : Destination() {
|
||||||
internal constructor(): this("", "")
|
internal constructor(): this("", "")
|
||||||
}
|
}
|
||||||
|
data class ClosedGroup(var publicKey: String): Destination() {
|
||||||
|
internal constructor(): this("")
|
||||||
|
}
|
||||||
|
|
||||||
class OpenGroup(
|
class OpenGroup(
|
||||||
var roomToken: String = "",
|
var roomToken: String = "",
|
||||||
|
@ -38,10 +41,10 @@ sealed class Destination {
|
||||||
address.isContact -> {
|
address.isContact -> {
|
||||||
Contact(address.contactIdentifier())
|
Contact(address.contactIdentifier())
|
||||||
}
|
}
|
||||||
address.isClosedGroup -> {
|
address.isLegacyClosedGroup -> {
|
||||||
val groupID = address.toGroupString()
|
val groupID = address.toGroupString()
|
||||||
val groupPublicKey = GroupUtil.doubleDecodeGroupID(groupID).toHexString()
|
val groupPublicKey = GroupUtil.doubleDecodeGroupID(groupID).toHexString()
|
||||||
ClosedGroup(groupPublicKey)
|
LegacyClosedGroup(groupPublicKey)
|
||||||
}
|
}
|
||||||
address.isOpenGroup -> {
|
address.isOpenGroup -> {
|
||||||
val storage = MessagingModuleConfiguration.shared.storage
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
|
|
|
@ -124,7 +124,7 @@ class ConfigurationMessage(var closedGroups: List<ClosedGroup>, var openGroups:
|
||||||
val profileKey = ProfileKeyUtil.getProfileKey(context)
|
val profileKey = ProfileKeyUtil.getProfileKey(context)
|
||||||
val groups = storage.getAllGroups(includeInactive = false)
|
val groups = storage.getAllGroups(includeInactive = false)
|
||||||
for (group in groups) {
|
for (group in groups) {
|
||||||
if (group.isClosedGroup && group.isActive) {
|
if (group.isLegacyClosedGroup && group.isActive) {
|
||||||
if (!group.members.contains(Address.fromSerialized(storage.getUserPublicKey()!!))) continue
|
if (!group.members.contains(Address.fromSerialized(storage.getUserPublicKey()!!))) continue
|
||||||
val groupPublicKey = GroupUtil.doubleDecodeGroupID(group.encodedId).toHexString()
|
val groupPublicKey = GroupUtil.doubleDecodeGroupID(group.encodedId).toHexString()
|
||||||
val encryptionKeyPair = storage.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) ?: continue
|
val encryptionKeyPair = storage.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) ?: continue
|
||||||
|
|
|
@ -87,7 +87,7 @@ object MessageSender {
|
||||||
|
|
||||||
when (destination) {
|
when (destination) {
|
||||||
is Destination.Contact -> message.recipient = destination.publicKey
|
is Destination.Contact -> message.recipient = destination.publicKey
|
||||||
is Destination.ClosedGroup -> message.recipient = destination.groupPublicKey
|
is Destination.LegacyClosedGroup -> message.recipient = destination.groupPublicKey
|
||||||
else -> throw IllegalStateException("Destination should not be an open group.")
|
else -> throw IllegalStateException("Destination should not be an open group.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ object MessageSender {
|
||||||
// Encrypt the serialized protobuf
|
// Encrypt the serialized protobuf
|
||||||
val ciphertext = when (destination) {
|
val ciphertext = when (destination) {
|
||||||
is Destination.Contact -> MessageEncrypter.encrypt(plaintext, destination.publicKey)
|
is Destination.Contact -> MessageEncrypter.encrypt(plaintext, destination.publicKey)
|
||||||
is Destination.ClosedGroup -> {
|
is Destination.LegacyClosedGroup -> {
|
||||||
val encryptionKeyPair =
|
val encryptionKeyPair =
|
||||||
MessagingModuleConfiguration.shared.storage.getLatestClosedGroupEncryptionKeyPair(
|
MessagingModuleConfiguration.shared.storage.getLatestClosedGroupEncryptionKeyPair(
|
||||||
destination.groupPublicKey
|
destination.groupPublicKey
|
||||||
|
@ -143,7 +143,7 @@ object MessageSender {
|
||||||
kind = SignalServiceProtos.Envelope.Type.SESSION_MESSAGE
|
kind = SignalServiceProtos.Envelope.Type.SESSION_MESSAGE
|
||||||
senderPublicKey = ""
|
senderPublicKey = ""
|
||||||
}
|
}
|
||||||
is Destination.ClosedGroup -> {
|
is Destination.LegacyClosedGroup -> {
|
||||||
kind = SignalServiceProtos.Envelope.Type.CLOSED_GROUP_MESSAGE
|
kind = SignalServiceProtos.Envelope.Type.CLOSED_GROUP_MESSAGE
|
||||||
senderPublicKey = destination.groupPublicKey
|
senderPublicKey = destination.groupPublicKey
|
||||||
}
|
}
|
||||||
|
@ -183,9 +183,9 @@ object MessageSender {
|
||||||
// TODO: this might change in future for config messages
|
// TODO: this might change in future for config messages
|
||||||
val forkInfo = SnodeAPI.forkInfo
|
val forkInfo = SnodeAPI.forkInfo
|
||||||
val namespaces: List<Int> = when {
|
val namespaces: List<Int> = when {
|
||||||
destination is Destination.ClosedGroup
|
destination is Destination.LegacyClosedGroup
|
||||||
&& forkInfo.defaultRequiresAuth() -> listOf(Namespace.UNAUTHENTICATED_CLOSED_GROUP)
|
&& forkInfo.defaultRequiresAuth() -> listOf(Namespace.UNAUTHENTICATED_CLOSED_GROUP)
|
||||||
destination is Destination.ClosedGroup
|
destination is Destination.LegacyClosedGroup
|
||||||
&& forkInfo.hasNamespaces() -> listOf(Namespace.UNAUTHENTICATED_CLOSED_GROUP, Namespace.DEFAULT)
|
&& forkInfo.hasNamespaces() -> listOf(Namespace.UNAUTHENTICATED_CLOSED_GROUP, Namespace.DEFAULT)
|
||||||
else -> listOf(Namespace.DEFAULT)
|
else -> listOf(Namespace.DEFAULT)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ class Address private constructor(address: String) : Parcelable, Comparable<Addr
|
||||||
constructor(`in`: Parcel) : this(`in`.readString()!!) {}
|
constructor(`in`: Parcel) : this(`in`.readString()!!) {}
|
||||||
|
|
||||||
val isGroup: Boolean
|
val isGroup: Boolean
|
||||||
get() = GroupUtil.isEncodedGroup(address)
|
get() = GroupUtil.isEncodedGroup(address) || address.startsWith(IdPrefix.GROUP.value)
|
||||||
val isClosedGroup: Boolean
|
val isLegacyClosedGroup: Boolean
|
||||||
get() = GroupUtil.isClosedGroup(address)
|
get() = GroupUtil.isLegacyClosedGroup(address)
|
||||||
val isOpenGroup: Boolean
|
val isOpenGroup: Boolean
|
||||||
get() = GroupUtil.isOpenGroup(address)
|
get() = GroupUtil.isOpenGroup(address)
|
||||||
val isOpenGroupInbox: Boolean
|
val isOpenGroupInbox: Boolean
|
||||||
|
|
|
@ -23,8 +23,8 @@ class GroupRecord(
|
||||||
|
|
||||||
val isOpenGroup: Boolean
|
val isOpenGroup: Boolean
|
||||||
get() = Address.fromSerialized(encodedId).isOpenGroup
|
get() = Address.fromSerialized(encodedId).isOpenGroup
|
||||||
val isClosedGroup: Boolean
|
val isLegacyClosedGroup: Boolean
|
||||||
get() = Address.fromSerialized(encodedId).isClosedGroup
|
get() = Address.fromSerialized(encodedId).isLegacyClosedGroup
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (!TextUtils.isEmpty(members)) {
|
if (!TextUtils.isEmpty(members)) {
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package org.session.libsession.utilities
|
package org.session.libsession.utilities
|
||||||
|
|
||||||
import network.loki.messenger.libsession_util.util.GroupInfo
|
|
||||||
import org.session.libsignal.messages.SignalServiceGroup
|
import org.session.libsignal.messages.SignalServiceGroup
|
||||||
import org.session.libsignal.utilities.Hex
|
import org.session.libsignal.utilities.Hex
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
object GroupUtil {
|
object GroupUtil {
|
||||||
const val CLOSED_GROUP_PREFIX = "__textsecure_group__!"
|
const val LEGACY_CLOSED_GROUP_PREFIX = "__textsecure_group__!"
|
||||||
const val OPEN_GROUP_PREFIX = "__loki_public_chat_group__!"
|
const val OPEN_GROUP_PREFIX = "__loki_public_chat_group__!"
|
||||||
const val OPEN_GROUP_INBOX_PREFIX = "__open_group_inbox__!"
|
const val OPEN_GROUP_INBOX_PREFIX = "__open_group_inbox__!"
|
||||||
|
|
||||||
|
@ -22,7 +21,7 @@ object GroupUtil {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getEncodedClosedGroupID(groupID: ByteArray): String {
|
fun getEncodedClosedGroupID(groupID: ByteArray): String {
|
||||||
return CLOSED_GROUP_PREFIX + Hex.toStringCondensed(groupID)
|
return LEGACY_CLOSED_GROUP_PREFIX + Hex.toStringCondensed(groupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -61,7 +60,7 @@ object GroupUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isEncodedGroup(groupId: String): Boolean {
|
fun isEncodedGroup(groupId: String): Boolean {
|
||||||
return groupId.startsWith(CLOSED_GROUP_PREFIX) || groupId.startsWith(OPEN_GROUP_PREFIX)
|
return groupId.startsWith(LEGACY_CLOSED_GROUP_PREFIX) || groupId.startsWith(OPEN_GROUP_PREFIX)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -75,8 +74,8 @@ object GroupUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isClosedGroup(groupId: String): Boolean {
|
fun isLegacyClosedGroup(groupId: String): Boolean {
|
||||||
return groupId.startsWith(CLOSED_GROUP_PREFIX)
|
return groupId.startsWith(LEGACY_CLOSED_GROUP_PREFIX)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Signal group ID handling is weird. The ID is double encoded in the database, but not in a `GroupContext`.
|
// NOTE: Signal group ID handling is weird. The ID is double encoded in the database, but not in a `GroupContext`.
|
||||||
|
|
|
@ -455,10 +455,11 @@ public class Recipient implements RecipientModifiedListener {
|
||||||
return address.isOpenGroupInbox();
|
return address.isOpenGroupInbox();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isClosedGroupRecipient() {
|
public boolean isLegacyClosedGroupRecipient() {
|
||||||
return address.isClosedGroup();
|
return address.isLegacyClosedGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean isPushGroupRecipient() {
|
public boolean isPushGroupRecipient() {
|
||||||
return address.isGroup();
|
return address.isGroup();
|
||||||
|
|
Loading…
Reference in New Issue