mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-25 11:05:25 +00:00
fix: fix the placeholder rendering on new messages, add in extra context logging for adding contacts and preventing new thread creation on new messages of various types
This commit is contained in:
parent
2ebd6ebf64
commit
3528afa2fb
@ -3,22 +3,34 @@ package org.thoughtcrime.securesms.conversation.v2
|
|||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.animation.FloatEvaluator
|
import android.animation.FloatEvaluator
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.content.*
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.content.Intent
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.*
|
import android.os.AsyncTask
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.text.SpannableString
|
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.SpannedString
|
import android.text.SpannedString
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.text.style.StyleSpan
|
import android.text.style.StyleSpan
|
||||||
import android.util.Pair
|
import android.util.Pair
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.*
|
import android.view.ActionMode
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@ -72,8 +84,12 @@ import org.session.libsession.messaging.sending_receiving.link_preview.LinkPrevi
|
|||||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||||
import org.session.libsession.messaging.utilities.SessionId
|
import org.session.libsession.messaging.utilities.SessionId
|
||||||
import org.session.libsession.snode.SnodeAPI
|
import org.session.libsession.snode.SnodeAPI
|
||||||
import org.session.libsession.utilities.*
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.Address.Companion.fromSerialized
|
import org.session.libsession.utilities.Address.Companion.fromSerialized
|
||||||
|
import org.session.libsession.utilities.GroupUtil
|
||||||
|
import org.session.libsession.utilities.MediaTypes
|
||||||
|
import org.session.libsession.utilities.Stub
|
||||||
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsession.utilities.concurrent.SimpleTask
|
import org.session.libsession.utilities.concurrent.SimpleTask
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsession.utilities.recipients.RecipientModifiedListener
|
import org.session.libsession.utilities.recipients.RecipientModifiedListener
|
||||||
@ -106,10 +122,25 @@ import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageView
|
|||||||
import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageViewDelegate
|
import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageViewDelegate
|
||||||
import org.thoughtcrime.securesms.conversation.v2.search.SearchBottomBar
|
import org.thoughtcrime.securesms.conversation.v2.search.SearchBottomBar
|
||||||
import org.thoughtcrime.securesms.conversation.v2.search.SearchViewModel
|
import org.thoughtcrime.securesms.conversation.v2.search.SearchViewModel
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.*
|
import org.thoughtcrime.securesms.conversation.v2.utilities.AttachmentManager
|
||||||
|
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
||||||
|
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
|
||||||
|
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
|
||||||
|
import org.thoughtcrime.securesms.conversation.v2.utilities.ResendMessageUtilities
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||||
import org.thoughtcrime.securesms.crypto.MnemonicUtilities
|
import org.thoughtcrime.securesms.crypto.MnemonicUtilities
|
||||||
import org.thoughtcrime.securesms.database.*
|
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.LokiAPIDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.LokiMessageDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.LokiThreadDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.MmsDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.MmsSmsDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.ReactionDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.SessionContactDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.SmsDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.Storage
|
||||||
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||||
import org.thoughtcrime.securesms.database.model.MessageId
|
import org.thoughtcrime.securesms.database.model.MessageId
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||||
@ -122,13 +153,26 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel
|
|||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel.LinkPreviewState
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel.LinkPreviewState
|
||||||
import org.thoughtcrime.securesms.mediasend.Media
|
import org.thoughtcrime.securesms.mediasend.Media
|
||||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivity
|
import org.thoughtcrime.securesms.mediasend.MediaSendActivity
|
||||||
import org.thoughtcrime.securesms.mms.*
|
import org.thoughtcrime.securesms.mms.AudioSlide
|
||||||
|
import org.thoughtcrime.securesms.mms.GifSlide
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
|
import org.thoughtcrime.securesms.mms.ImageSlide
|
||||||
|
import org.thoughtcrime.securesms.mms.MediaConstraints
|
||||||
|
import org.thoughtcrime.securesms.mms.Slide
|
||||||
|
import org.thoughtcrime.securesms.mms.SlideDeck
|
||||||
|
import org.thoughtcrime.securesms.mms.VideoSlide
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
import org.thoughtcrime.securesms.permissions.Permissions
|
||||||
import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
|
import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
|
||||||
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
|
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
|
||||||
import org.thoughtcrime.securesms.util.*
|
import org.thoughtcrime.securesms.util.ActivityDispatcher
|
||||||
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
|
import org.thoughtcrime.securesms.util.MediaUtil
|
||||||
|
import org.thoughtcrime.securesms.util.SaveAttachmentTask
|
||||||
|
import org.thoughtcrime.securesms.util.push
|
||||||
|
import org.thoughtcrime.securesms.util.toPx
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
import java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
@ -455,6 +499,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
// TODO: buffer this
|
// TODO: buffer this
|
||||||
bufferedLastSeenChannel.trySend(Unit)
|
bufferedLastSeenChannel.trySend(Unit)
|
||||||
}
|
}
|
||||||
|
updatePlaceholder()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLoaderReset(cursor: Loader<Cursor>) {
|
override fun onLoaderReset(cursor: Loader<Cursor>) {
|
||||||
|
@ -154,18 +154,14 @@ public class RecipientDatabase extends Database {
|
|||||||
|
|
||||||
public Optional<RecipientSettings> getRecipientSettings(@NonNull Address address) {
|
public Optional<RecipientSettings> getRecipientSettings(@NonNull Address address) {
|
||||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||||
Cursor cursor = null;
|
|
||||||
|
|
||||||
try {
|
try (Cursor cursor = database.query(TABLE_NAME, null, ADDRESS + " = ?", new String[]{address.serialize()}, null, null, null)) {
|
||||||
cursor = database.query(TABLE_NAME, null, ADDRESS + " = ?", new String[] {address.serialize()}, null, null, null);
|
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToNext()) {
|
if (cursor != null && cursor.moveToNext()) {
|
||||||
return getRecipientSettings(cursor);
|
return getRecipientSettings(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
} finally {
|
|
||||||
if (cursor != null) cursor.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +248,16 @@ public class RecipientDatabase extends Database {
|
|||||||
notifyRecipientListeners();
|
notifyRecipientListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getApproved(@NonNull Address address) {
|
||||||
|
SQLiteDatabase db = getReadableDatabase();
|
||||||
|
try (Cursor cursor = db.query(TABLE_NAME, new String[]{APPROVED}, ADDRESS + " = ?", new String[]{address.serialize()}, null, null, null)) {
|
||||||
|
if (cursor != null && cursor.moveToNext()) {
|
||||||
|
return cursor.getInt(cursor.getColumnIndexOrThrow(APPROVED)) == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void setApproved(@NonNull Recipient recipient, boolean approved) {
|
public void setApproved(@NonNull Recipient recipient, boolean approved) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(APPROVED, approved ? 1 : 0);
|
values.put(APPROVED, approved ? 1 : 0);
|
||||||
|
@ -98,6 +98,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
|||||||
|
|
||||||
// TODO: maybe add time here from formation / creation message
|
// TODO: maybe add time here from formation / creation message
|
||||||
override fun threadCreated(address: Address, threadId: Long) {
|
override fun threadCreated(address: Address, threadId: Long) {
|
||||||
|
if (!getRecipientApproved(address)) return // don't store unapproved / message requests
|
||||||
Log.d("Loki-DBG", "creating thread for $address\nExecution context:\n${Thread.currentThread().stackTrace.joinToString("\n")}")
|
Log.d("Loki-DBG", "creating thread for $address\nExecution context:\n${Thread.currentThread().stackTrace.joinToString("\n")}")
|
||||||
|
|
||||||
val volatile = configFactory.convoVolatile ?: return
|
val volatile = configFactory.convoVolatile ?: return
|
||||||
@ -1037,6 +1038,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
|||||||
|
|
||||||
override fun setContact(contact: Contact) {
|
override fun setContact(contact: Contact) {
|
||||||
DatabaseComponent.get(context).sessionContactDatabase().setContact(contact)
|
DatabaseComponent.get(context).sessionContactDatabase().setContact(contact)
|
||||||
|
if (!getRecipientApproved(Address.fromSerialized(contact.sessionID))) return
|
||||||
SSKEnvironment.shared.profileManager.contactUpdatedInternal(contact)
|
SSKEnvironment.shared.profileManager.contactUpdatedInternal(contact)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1050,6 +1052,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun addLibSessionContacts(contacts: List<LibSessionContact>) {
|
override fun addLibSessionContacts(contacts: List<LibSessionContact>) {
|
||||||
|
Log.d("Loki-DBG", "Adding contacts from execution context:\n${Thread.currentThread().stackTrace.joinToString("\n")}")
|
||||||
val mappingDb = DatabaseComponent.get(context).blindedIdMappingDatabase()
|
val mappingDb = DatabaseComponent.get(context).blindedIdMappingDatabase()
|
||||||
val moreContacts = contacts.filter { contact ->
|
val moreContacts = contacts.filter { contact ->
|
||||||
val id = SessionId(contact.id)
|
val id = SessionId(contact.id)
|
||||||
@ -1197,7 +1200,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
|||||||
Log.d("Loki-DBG", "Deleting conversation for ${recipient.address}")
|
Log.d("Loki-DBG", "Deleting conversation for ${recipient.address}")
|
||||||
if (recipient.isContactRecipient) {
|
if (recipient.isContactRecipient) {
|
||||||
if (recipient.isLocalNumber) return
|
if (recipient.isLocalNumber) return
|
||||||
// TODO: handle contact
|
|
||||||
val contacts = configFactory.contacts ?: return
|
val contacts = configFactory.contacts ?: return
|
||||||
contacts.upsertContact(recipient.address.serialize()) {
|
contacts.upsertContact(recipient.address.serialize()) {
|
||||||
this.priority = ConfigBase.PRIORITY_HIDDEN
|
this.priority = ConfigBase.PRIORITY_HIDDEN
|
||||||
@ -1351,6 +1353,10 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getRecipientApproved(address: Address): Boolean {
|
||||||
|
return DatabaseComponent.get(context).recipientDatabase().getApproved(address)
|
||||||
|
}
|
||||||
|
|
||||||
override fun setRecipientApproved(recipient: Recipient, approved: Boolean) {
|
override fun setRecipientApproved(recipient: Recipient, approved: Boolean) {
|
||||||
DatabaseComponent.get(context).recipientDatabase().setApproved(recipient, approved)
|
DatabaseComponent.get(context).recipientDatabase().setApproved(recipient, approved)
|
||||||
if (recipient.isLocalNumber || !recipient.isContactRecipient) return
|
if (recipient.isLocalNumber || !recipient.isContactRecipient) return
|
||||||
|
@ -193,6 +193,7 @@ interface StorageProtocol {
|
|||||||
fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, sentTimestamp: Long)
|
fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, sentTimestamp: Long)
|
||||||
fun insertMessageRequestResponse(response: MessageRequestResponse)
|
fun insertMessageRequestResponse(response: MessageRequestResponse)
|
||||||
fun setRecipientApproved(recipient: Recipient, approved: Boolean)
|
fun setRecipientApproved(recipient: Recipient, approved: Boolean)
|
||||||
|
fun getRecipientApproved(address: Address): Boolean
|
||||||
fun setRecipientApprovedMe(recipient: Recipient, approvedMe: Boolean)
|
fun setRecipientApprovedMe(recipient: Recipient, approvedMe: Boolean)
|
||||||
fun insertCallMessage(senderPublicKey: String, callMessageType: CallMessageType, sentTimestamp: Long)
|
fun insertCallMessage(senderPublicKey: String, callMessageType: CallMessageType, sentTimestamp: Long)
|
||||||
fun conversationHasOutgoing(userPublicKey: String): Boolean
|
fun conversationHasOutgoing(userPublicKey: String): Boolean
|
||||||
|
@ -10,8 +10,15 @@ import nl.komponents.kovenant.task
|
|||||||
import org.session.libsession.database.StorageProtocol
|
import org.session.libsession.database.StorageProtocol
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.messages.Message
|
import org.session.libsession.messaging.messages.Message
|
||||||
|
import org.session.libsession.messaging.messages.control.CallMessage
|
||||||
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage
|
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage
|
||||||
|
import org.session.libsession.messaging.messages.control.ConfigurationMessage
|
||||||
|
import org.session.libsession.messaging.messages.control.DataExtractionNotification
|
||||||
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
|
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
|
||||||
|
import org.session.libsession.messaging.messages.control.MessageRequestResponse
|
||||||
|
import org.session.libsession.messaging.messages.control.ReadReceipt
|
||||||
|
import org.session.libsession.messaging.messages.control.SharedConfigurationMessage
|
||||||
|
import org.session.libsession.messaging.messages.control.TypingIndicator
|
||||||
import org.session.libsession.messaging.messages.control.UnsendRequest
|
import org.session.libsession.messaging.messages.control.UnsendRequest
|
||||||
import org.session.libsession.messaging.messages.visible.ParsedMessage
|
import org.session.libsession.messaging.messages.visible.ParsedMessage
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
||||||
@ -54,6 +61,9 @@ class BatchMessageReceiveJob(
|
|||||||
|
|
||||||
const val BATCH_DEFAULT_NUMBER = 512
|
const val BATCH_DEFAULT_NUMBER = 512
|
||||||
|
|
||||||
|
// used for processing messages that don't have a thread and shouldn't create one
|
||||||
|
const val NO_THREAD_MAPPING = -1L
|
||||||
|
|
||||||
// Keys used for database storage
|
// Keys used for database storage
|
||||||
private val NUM_MESSAGES_KEY = "numMessages"
|
private val NUM_MESSAGES_KEY = "numMessages"
|
||||||
private val DATA_KEY = "data"
|
private val DATA_KEY = "data"
|
||||||
@ -64,18 +74,22 @@ class BatchMessageReceiveJob(
|
|||||||
|
|
||||||
private fun shouldCreateThread(parsedMessage: ParsedMessage): Boolean {
|
private fun shouldCreateThread(parsedMessage: ParsedMessage): Boolean {
|
||||||
val message = parsedMessage.message
|
val message = parsedMessage.message
|
||||||
return message is VisibleMessage
|
if (message is VisibleMessage) return true
|
||||||
|| !message.isSenderSelf
|
else { // message is control message otherwise
|
||||||
// TODO: sort out which messages should create threads: message requests? group creation threads? visible messages? others? calls?
|
return when(message) {
|
||||||
|
is SharedConfigurationMessage -> false
|
||||||
// || (message is ClosedGroupControlMessage && message.kind is ClosedGroupControlMessage.Kind.New) // this was creating threads for self send messages (i.e. synced group creation)
|
is ClosedGroupControlMessage -> message.kind is ClosedGroupControlMessage.Kind.New
|
||||||
// if (message is ClosedGroupControlMessage && message.kind is ClosedGroupControlMessage.Kind.New) {
|
is DataExtractionNotification -> false
|
||||||
// return true
|
is MessageRequestResponse -> false
|
||||||
// }
|
is ExpirationTimerUpdate -> false
|
||||||
// if (parsedMessage.message.isSenderSelf ) {
|
is ConfigurationMessage -> false
|
||||||
// // all the cases where we should add a self send creating the thread, i.e. group invite? visible message?
|
is TypingIndicator -> false
|
||||||
// }
|
is UnsendRequest -> false
|
||||||
// !parsedMessage.message.isSenderSelf || parsedMessage.message is VisibleMessage
|
is ReadReceipt -> false
|
||||||
|
is CallMessage -> false // TODO: maybe
|
||||||
|
else -> false // shouldn't happen, or I guess would be Visible
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getThreadId(message: Message, storage: StorageProtocol, shouldCreateThread: Boolean): Long? {
|
private fun getThreadId(message: Message, storage: StorageProtocol, shouldCreateThread: Boolean): Long? {
|
||||||
@ -106,8 +120,8 @@ class BatchMessageReceiveJob(
|
|||||||
val (message, proto) = MessageReceiver.parse(data, openGroupMessageServerID, openGroupPublicKey = serverPublicKey)
|
val (message, proto) = MessageReceiver.parse(data, openGroupMessageServerID, openGroupPublicKey = serverPublicKey)
|
||||||
message.serverHash = serverHash
|
message.serverHash = serverHash
|
||||||
val parsedParams = ParsedMessage(messageParameters, message, proto)
|
val parsedParams = ParsedMessage(messageParameters, message, proto)
|
||||||
val threadID = getThreadId(message, storage, shouldCreateThread(parsedParams))
|
val threadID = getThreadId(message, storage, shouldCreateThread(parsedParams)) ?: NO_THREAD_MAPPING
|
||||||
if (threadID != null && !threadMap.containsKey(threadID)) {
|
if (!threadMap.containsKey(threadID)) {
|
||||||
threadMap[threadID] = mutableListOf(parsedParams)
|
threadMap[threadID] = mutableListOf(parsedParams)
|
||||||
} else {
|
} else {
|
||||||
threadMap[threadID]!! += parsedParams
|
threadMap[threadID]!! += parsedParams
|
||||||
@ -136,8 +150,8 @@ class BatchMessageReceiveJob(
|
|||||||
|
|
||||||
// iterate over threads and persist them (persistence is the longest constant in the batch process operation)
|
// iterate over threads and persist them (persistence is the longest constant in the batch process operation)
|
||||||
runBlocking(Dispatchers.IO) {
|
runBlocking(Dispatchers.IO) {
|
||||||
val deferredThreadMap = threadMap.entries.map { (threadId, messages) ->
|
|
||||||
async {
|
fun processMessages(threadId: Long, messages: List<ParsedMessage>) = async {
|
||||||
// The LinkedHashMap should preserve insertion order
|
// The LinkedHashMap should preserve insertion order
|
||||||
val messageIds = linkedMapOf<Long, Pair<Boolean, Boolean>>()
|
val messageIds = linkedMapOf<Long, Pair<Boolean, Boolean>>()
|
||||||
val myLastSeen = storage.getLastSeen(threadId)
|
val myLastSeen = storage.getLastSeen(threadId)
|
||||||
@ -146,12 +160,22 @@ class BatchMessageReceiveJob(
|
|||||||
try {
|
try {
|
||||||
when (message) {
|
when (message) {
|
||||||
is VisibleMessage -> {
|
is VisibleMessage -> {
|
||||||
val isUserBlindedSender = message.sender == serverPublicKey?.let { SodiumUtilities.blindedKeyPair(it, MessagingModuleConfiguration.shared.getUserED25519KeyPair()!!) }?.let { SessionId(
|
val isUserBlindedSender =
|
||||||
IdPrefix.BLINDED, it.publicKey.asBytes).hexString }
|
message.sender == serverPublicKey?.let {
|
||||||
|
SodiumUtilities.blindedKeyPair(
|
||||||
|
it,
|
||||||
|
MessagingModuleConfiguration.shared.getUserED25519KeyPair()!!
|
||||||
|
)
|
||||||
|
}?.let {
|
||||||
|
SessionId(
|
||||||
|
IdPrefix.BLINDED, it.publicKey.asBytes
|
||||||
|
).hexString
|
||||||
|
}
|
||||||
val sentTimestamp = message.sentTimestamp!!
|
val sentTimestamp = message.sentTimestamp!!
|
||||||
if (message.sender == localUserPublicKey || isUserBlindedSender) {
|
if (message.sender == localUserPublicKey || isUserBlindedSender) {
|
||||||
if (sentTimestamp > newLastSeen) {
|
if (sentTimestamp > newLastSeen) {
|
||||||
newLastSeen = sentTimestamp // use sent timestamp here since that is technically the last one we have
|
newLastSeen =
|
||||||
|
sentTimestamp // use sent timestamp here since that is technically the last one we have
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val messageId = MessageReceiver.handleVisibleMessage(
|
val messageId = MessageReceiver.handleVisibleMessage(
|
||||||
@ -167,12 +191,17 @@ class BatchMessageReceiveJob(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
parameters.openGroupMessageServerID?.let {
|
parameters.openGroupMessageServerID?.let {
|
||||||
MessageReceiver.handleOpenGroupReactions(threadId, it, parameters.reactions)
|
MessageReceiver.handleOpenGroupReactions(
|
||||||
|
threadId,
|
||||||
|
it,
|
||||||
|
parameters.reactions
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is UnsendRequest -> {
|
is UnsendRequest -> {
|
||||||
val deletedMessageId = MessageReceiver.handleUnsendRequest(message)
|
val deletedMessageId =
|
||||||
|
MessageReceiver.handleUnsendRequest(message)
|
||||||
|
|
||||||
// If we removed a message then ensure it isn't in the 'messageIds'
|
// If we removed a message then ensure it isn't in the 'messageIds'
|
||||||
if (deletedMessageId != null) {
|
if (deletedMessageId != null) {
|
||||||
@ -203,9 +232,15 @@ class BatchMessageReceiveJob(
|
|||||||
storage.updateThread(threadId, true)
|
storage.updateThread(threadId, true)
|
||||||
SSKEnvironment.shared.notificationManager.updateNotification(context, threadId)
|
SSKEnvironment.shared.notificationManager.updateNotification(context, threadId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val withoutDefault = threadMap.entries.filter { it.key != NO_THREAD_MAPPING }
|
||||||
|
val noThreadMessages = threadMap[NO_THREAD_MAPPING] ?: listOf()
|
||||||
|
val deferredThreadMap = withoutDefault.map { (threadId, messages) ->
|
||||||
|
processMessages(threadId, messages)
|
||||||
}
|
}
|
||||||
// await all thread processing
|
// await all thread processing
|
||||||
deferredThreadMap.awaitAll()
|
deferredThreadMap.awaitAll()
|
||||||
|
processMessages(NO_THREAD_MAPPING, noThreadMessages)
|
||||||
}
|
}
|
||||||
if (failures.isEmpty()) {
|
if (failures.isEmpty()) {
|
||||||
handleSuccess(dispatcherName)
|
handleSuccess(dispatcherName)
|
||||||
|
Loading…
Reference in New Issue
Block a user