Batch conversation updates

This commit is contained in:
Niels Andriesse 2021-05-27 15:00:16 +10:00
parent ad51bbb847
commit 85120b57ea
9 changed files with 60 additions and 42 deletions

View File

@ -21,6 +21,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
@ -47,7 +48,6 @@ import org.session.libsignal.utilities.ThreadUtils;
import org.signal.aesgcmprovider.AesGcmProvider;
import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
import org.thoughtcrime.securesms.jobmanager.DependencyInjector;
@ -120,14 +120,12 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
private ProfileManager profileManager;
private ObjectGraph objectGraph;
private PersistentLogger persistentLogger;
// Loki
public MessageNotifier messageNotifier = null;
public Poller poller = null;
public Broadcaster broadcaster = null;
public SignalCommunicationModule communicationModule;
private Job firebaseInstanceIdJob;
private Handler threadNotificationHandler;
private Handler conversationListNotificationHandler;
private volatile boolean isAppVisible;
@ -135,8 +133,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
return (ApplicationContext) context.getApplicationContext();
}
public Handler getThreadNotificationHandler() {
return this.threadNotificationHandler;
public Handler getConversationListNotificationHandler() {
return this.conversationListNotificationHandler;
}
@Override
@ -153,7 +151,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
AppContext.INSTANCE.configureKovenant();
messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
broadcaster = new Broadcaster(this);
threadNotificationHandler = new Handler(Looper.getMainLooper());
conversationListNotificationHandler = new Handler(Looper.getMainLooper());
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
MessagingModuleConfiguration.Companion.configure(this,
DatabaseFactory.getStorage(this),

View File

@ -0,0 +1,37 @@
package org.thoughtcrime.securesms.database
import android.annotation.SuppressLint
import android.content.Context
import android.os.Handler
import android.os.Looper
import org.session.libsession.utilities.Debouncer
import org.thoughtcrime.securesms.ApplicationContext
class ConversationNotificationDebouncer(private val context: Context) {
private val threadIDs = mutableSetOf<Long>()
private val handler = Handler(Looper.getMainLooper())
private val debouncer = Debouncer(handler, 250);
companion object {
@SuppressLint("StaticFieldLeak")
lateinit var shared: ConversationNotificationDebouncer
fun get(context: Context): ConversationNotificationDebouncer {
if (::shared.isInitialized) { return shared }
shared = ConversationNotificationDebouncer(context)
return shared
}
}
fun notify(threadID: Long) {
threadIDs.add(threadID)
debouncer.publish { publish() }
}
private fun publish() {
for (threadID in threadIDs) {
context.contentResolver.notifyChange(DatabaseContentProviders.Conversation.getUriForThread(threadID), null)
}
threadIDs.clear()
}
}

View File

@ -35,13 +35,13 @@ public abstract class Database {
protected SQLCipherOpenHelper databaseHelper;
protected final Context context;
private final Debouncer threadNotificationDebouncer;
private final Debouncer conversationListNotificationDebouncer;
@SuppressLint("WrongConstant")
public Database(Context context, SQLCipherOpenHelper databaseHelper) {
this.context = context;
this.context = context;
this.databaseHelper = databaseHelper;
this.threadNotificationDebouncer = new Debouncer(ApplicationContext.getInstance(context).getThreadNotificationHandler(), 250);
this.conversationListNotificationDebouncer = new Debouncer(ApplicationContext.getInstance(context).getConversationListNotificationHandler(), 250);
}
protected void notifyConversationListeners(Set<Long> threadIds) {
@ -50,11 +50,11 @@ public abstract class Database {
}
protected void notifyConversationListeners(long threadId) {
context.getContentResolver().notifyChange(DatabaseContentProviders.Conversation.getUriForThread(threadId), null);
ConversationNotificationDebouncer.Companion.get(context).notify(threadId);
}
protected void notifyConversationListListeners() {
threadNotificationDebouncer.publish(()->context.getContentResolver().notifyChange(DatabaseContentProviders.ConversationList.CONTENT_URI, null));
conversationListNotificationDebouncer.publish(()->context.getContentResolver().notifyChange(DatabaseContentProviders.ConversationList.CONTENT_URI, null));
}
protected void notifyStickerListeners() {

View File

@ -3,8 +3,8 @@ package org.thoughtcrime.securesms.database
import android.content.Context
import android.net.Uri
import org.session.libsession.database.StorageProtocol
import org.session.libsession.messaging.jobs.*
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.jobs.*
import org.session.libsession.messaging.messages.control.ConfigurationMessage
import org.session.libsession.messaging.messages.signal.*
import org.session.libsession.messaging.messages.signal.IncomingTextMessage
@ -16,20 +16,15 @@ import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAt
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.Address.Companion.fromSerialized
import org.session.libsession.utilities.GroupRecord
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.messaging.utilities.UpdateMessageData
import org.session.libsession.utilities.GroupUtil
import org.session.libsession.utilities.IdentityKeyUtil
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.ProfileKeyUtil
import org.session.libsession.utilities.*
import org.session.libsession.utilities.Address.Companion.fromSerialized
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.crypto.ecc.ECKeyPair
import org.session.libsignal.utilities.KeyHelper
import org.session.libsignal.utilities.guava.Optional
import org.session.libsignal.messages.SignalServiceAttachmentPointer
import org.session.libsignal.messages.SignalServiceGroup
import org.session.libsignal.utilities.KeyHelper
import org.session.libsignal.utilities.guava.Optional
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
@ -100,7 +95,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
override fun persist(message: VisibleMessage, quotes: QuoteModel?, linkPreview: List<LinkPreview?>, groupPublicKey: String?, openGroupID: String?, attachments: List<Attachment>): Long? {
var messageID: Long? = null
val senderAddress = Address.fromSerialized(message.sender!!)
val isUserSender = message.sender!! == getUserPublicKey()
val isUserSender = (message.sender!! == getUserPublicKey())
val group: Optional<SignalServiceGroup> = when {
openGroupID != null -> Optional.of(SignalServiceGroup(openGroupID.toByteArray(), SignalServiceGroup.GroupType.PUBLIC_CHAT))
groupPublicKey != null -> {
@ -120,7 +115,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
senderAddress
}
val targetRecipient = Recipient.from(context, targetAddress, false)
if (message.isMediaMessage() || attachments.isNotEmpty()) {
val quote: Optional<QuoteModel> = if (quotes != null) Optional.of(quotes) else Optional.absent()
val linkPreviews: Optional<List<LinkPreview>> = if (linkPreview.isEmpty()) Optional.absent() else Optional.of(linkPreview.mapNotNull { it!! })

View File

@ -51,17 +51,12 @@ import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.mms.GlideRequests
import java.io.IOException
class HomeActivity : PassphraseRequiredActionBarActivity(),
ConversationClickListener,
SeedReminderViewDelegate,
NewConversationButtonSetViewDelegate {
class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickListener, SeedReminderViewDelegate, NewConversationButtonSetViewDelegate {
private lateinit var glide: GlideRequests
private var broadcastReceiver: BroadcastReceiver? = null
private val publicKey: String
get() {
return TextSecurePreferences.getLocalNumber(this)!!
}
get() = TextSecurePreferences.getLocalNumber(this)!!
// region Lifecycle
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {

View File

@ -35,13 +35,8 @@ class ConversationView : LinearLayout {
setUpViewHierarchy()
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {
setUpViewHierarchy()
}
private fun setUpViewHierarchy() {
LayoutInflater.from(context)
.inflate(R.layout.view_conversation, this)
LayoutInflater.from(context).inflate(R.layout.view_conversation, this)
}
// endregion
@ -75,7 +70,7 @@ class ConversationView : LinearLayout {
typingIndicatorView.visibility = if (isTyping) View.VISIBLE else View.GONE
statusIndicatorImageView.visibility = View.VISIBLE
when {
!thread.isOutgoing || thread.isVerificationStatusChange -> statusIndicatorImageView.visibility = View.GONE
!thread.isOutgoing -> statusIndicatorImageView.visibility = View.GONE
thread.isFailed -> statusIndicatorImageView.setImageResource(R.drawable.ic_error)
thread.isPending -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_dot_dot_dot)
thread.isRemoteRead -> statusIndicatorImageView.setImageResource(R.drawable.ic_filled_circle_check)

View File

@ -12,8 +12,8 @@ import org.session.libsession.messaging.messages.visible.Attachment
import org.session.libsession.messaging.messages.visible.VisibleMessage
import org.session.libsession.messaging.open_groups.OpenGroupV2
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
import org.session.libsession.utilities.Address

View File

@ -234,7 +234,7 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage, proto: SignalS
}
// Cancel any typing indicators if needed
cancelTypingIndicatorsIfNeeded(message.sender!!)
//Notify the user if needed
// Notify the user if needed
SSKEnvironment.shared.notificationManager.updateNotification(context, threadID)
}
//endregion

View File

@ -12,7 +12,6 @@ import android.os.Handler;
* See http://rxmarbles.com/#debounce
*/
public class Debouncer {
private final Handler handler;
private final long threshold;