From 18d8261e33a57314d61ce8e11a385c8f373eb8fd Mon Sep 17 00:00:00 2001 From: Harris Date: Tue, 27 Jul 2021 15:26:10 +1000 Subject: [PATCH 01/10] refactor: move resource heavy functions into launch lifecycle scope --- .../org/thoughtcrime/securesms/home/HomeActivity.kt | 12 ++---------- app/src/main/res/drawable/home_activity_gradient.xml | 1 + 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index 6d42d80de8..49e859fd1a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -10,9 +10,7 @@ import android.os.Bundle import android.text.Spannable import android.text.SpannableString import android.text.style.ForegroundColorSpan -import android.util.DisplayMetrics import android.view.View -import android.widget.RelativeLayout import android.widget.Toast import androidx.lifecycle.Observer import androidx.lifecycle.lifecycleScope @@ -75,7 +73,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis glide = GlideApp.with(this) // Set up toolbar buttons profileButton.glide = glide - updateProfileButton() profileButton.setOnClickListener { openSettings() } pathStatusViewContainer.disableClipping() pathStatusViewContainer.setOnClickListener { showPath() } @@ -117,12 +114,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis homeAdapter.changeCursor(null) } }) - // Set up gradient view - val gradientViewLayoutParams = gradientView.layoutParams as RelativeLayout.LayoutParams - val displayMetrics = DisplayMetrics() - windowManager.defaultDisplay.getMetrics(displayMetrics) - val height = displayMetrics.heightPixels - gradientViewLayoutParams.topMargin = (0.15 * height.toFloat()).toInt() // Set up new conversation button set newConversationButtonSet.delegate = this // Set up typing observer @@ -137,7 +128,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis OpenGroupManager.startPolling() JobQueue.shared.resumePendingJobs() } - IP2Country.configureIfNeeded(this) application.registerForFCMIfNeeded(false) // Observe blocked contacts changed events val broadcastReceiver = object : BroadcastReceiver() { @@ -150,6 +140,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, IntentFilter("blockedContactsChanged")) lifecycleScope.launch { // update things based on TextSecurePrefs (profile info etc) + updateProfileButton() + IP2Country.configureIfNeeded(this@HomeActivity) TextSecurePreferences.events.filter { it == TextSecurePreferences.PROFILE_NAME_PREF }.collect { updateProfileButton() } diff --git a/app/src/main/res/drawable/home_activity_gradient.xml b/app/src/main/res/drawable/home_activity_gradient.xml index b160d68fee..d85e4873f7 100644 --- a/app/src/main/res/drawable/home_activity_gradient.xml +++ b/app/src/main/res/drawable/home_activity_gradient.xml @@ -4,6 +4,7 @@ android:shape="rectangle"> From 9d9f543c3befce469bc33796ec811634f40fedef Mon Sep 17 00:00:00 2001 From: Harris Date: Thu, 29 Jul 2021 08:56:34 +1000 Subject: [PATCH 02/10] feat: trying upgrade DB for perf and reducing retry interval to congest threads --- app/build.gradle | 3 +- .../database/helpers/SQLCipherOpenHelper.java | 5 ++-- .../securesms/home/HomeActivity.kt | 28 +++++++++---------- .../securesms/home/HomeAdapter.kt | 2 +- .../sending_receiving/pollers/Poller.kt | 2 +- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 31e14eac69..df68180146 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -96,7 +96,7 @@ dependencies { } implementation 'com.codewaves.stickyheadergrid:stickyheadergrid:0.9.4' implementation 'com.github.dmytrodanylyk.circular-progress-button:library:1.1.3-S2' - implementation 'org.signal:android-database-sqlcipher:3.5.9-S3' + implementation 'net.zetetic:android-database-sqlcipher:4.4.3' implementation ('com.googlecode.ez-vcard:ez-vcard:0.9.11') { exclude group: 'com.fasterxml.jackson.core' exclude group: 'org.freemarker' @@ -214,6 +214,7 @@ android { buildTypes { release { + debuggable true minifyEnabled false } debug { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 01c7f105bd..62a5e85575 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -143,11 +143,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { } @Override - public void onConfigure(SQLiteDatabase db) { - super.onConfigure(db); + public void onOpen(SQLiteDatabase db) { + super.onOpen(db); // Loki - Enable write ahead logging mode and increase the cache size. // This should be disabled if we ever run into serious race condition bugs. - db.enableWriteAheadLogging(); db.execSQL("PRAGMA cache_size = 10000"); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index 49e859fd1a..e03d25d270 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -116,19 +116,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis }) // Set up new conversation button set newConversationButtonSet.delegate = this - // Set up typing observer - ApplicationContext.getInstance(this).typingStatusRepository.typingThreads.observe(this, Observer> { threadIDs -> - val adapter = recyclerView.adapter as HomeAdapter - adapter.typingThreadIDs = threadIDs ?: setOf() - }) - // Set up remaining components if needed - val application = ApplicationContext.getInstance(this) - val userPublicKey = TextSecurePreferences.getLocalNumber(this) - if (userPublicKey != null) { - OpenGroupManager.startPolling() - JobQueue.shared.resumePendingJobs() - } - application.registerForFCMIfNeeded(false) // Observe blocked contacts changed events val broadcastReceiver = object : BroadcastReceiver() { @@ -138,8 +125,21 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis } this.broadcastReceiver = broadcastReceiver LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, IntentFilter("blockedContactsChanged")) - lifecycleScope.launch { + lifecycleScope.launchWhenResumed { // update things based on TextSecurePrefs (profile info etc) + // Set up typing observer + ApplicationContext.getInstance(this@HomeActivity).typingStatusRepository.typingThreads.observe(this@HomeActivity, Observer> { threadIDs -> + val adapter = recyclerView.adapter as HomeAdapter + adapter.typingThreadIDs = threadIDs ?: setOf() + }) + // Set up remaining components if needed + val application = ApplicationContext.getInstance(this@HomeActivity) + application.registerForFCMIfNeeded(false) + val userPublicKey = TextSecurePreferences.getLocalNumber(this@HomeActivity) + if (userPublicKey != null) { + OpenGroupManager.startPolling() + JobQueue.shared.resumePendingJobs() + } updateProfileButton() IP2Country.configureIfNeeded(this@HomeActivity) TextSecurePreferences.events.filter { it == TextSecurePreferences.PROFILE_NAME_PREF }.collect { diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeAdapter.kt index ba718d355f..11ae410a9d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeAdapter.kt @@ -9,7 +9,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.model.ThreadRecord import org.thoughtcrime.securesms.mms.GlideRequests -class HomeAdapter(context: Context, cursor: Cursor) : CursorRecyclerViewAdapter(context, cursor) { +class HomeAdapter(context: Context, cursor: Cursor?) : CursorRecyclerViewAdapter(context, cursor) { private val threadDatabase = DatabaseFactory.getThreadDatabase(context) lateinit var glide: GlideRequests var typingThreadIDs = setOf() diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt index bbf2620f97..e077835e5f 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt @@ -22,7 +22,7 @@ class Poller { // region Settings companion object { - private val retryInterval: Long = 1 * 1000 + private val retryInterval: Long = 3 * 1000 } // endregion From 0ed7b28b6b1c42686c09ba872231c1cb12210f0f Mon Sep 17 00:00:00 2001 From: jubb Date: Thu, 29 Jul 2021 17:02:58 +1000 Subject: [PATCH 03/10] refactor: performance experiments --- app/build.gradle | 4 +- .../securesms/ApplicationContext.java | 17 +++-- .../conversation/v2/ConversationActivityV2.kt | 2 +- .../conversation/v2/messages/QuoteView.kt | 3 +- .../v2/messages/VisibleMessageContentView.kt | 2 +- .../v2/utilities/MentionUtilities.kt | 11 ++- .../securesms/home/ConversationView.kt | 2 +- .../securesms/home/HomeActivity.kt | 67 +++++++++++-------- .../longmessage/LongMessageActivity.java | 2 +- .../notifications/DefaultMessageNotifier.java | 6 +- app/src/main/res/layout/activity_home.xml | 7 +- .../main/res/layout/seed_reminder_stub.xml | 6 ++ 12 files changed, 72 insertions(+), 57 deletions(-) create mode 100644 app/src/main/res/layout/seed_reminder_stub.xml diff --git a/app/build.gradle b/app/build.gradle index df68180146..9a9d61e97f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,7 +35,6 @@ dependencies { implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'androidx.exifinterface:exifinterface:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.1' - implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-common-java8:2.3.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' @@ -96,7 +95,7 @@ dependencies { } implementation 'com.codewaves.stickyheadergrid:stickyheadergrid:0.9.4' implementation 'com.github.dmytrodanylyk.circular-progress-button:library:1.1.3-S2' - implementation 'net.zetetic:android-database-sqlcipher:4.4.3' + implementation 'org.signal:android-database-sqlcipher:3.5.9-S3' implementation ('com.googlecode.ez-vcard:ez-vcard:0.9.11') { exclude group: 'com.fasterxml.jackson.core' exclude group: 'org.freemarker' @@ -214,7 +213,6 @@ android { buildTypes { release { - debuggable true minifyEnabled false } debug { diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index e2c82814e3..363343696c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -15,6 +15,7 @@ */ package org.thoughtcrime.securesms; +import android.app.Application; import android.content.Context; import android.content.Intent; import android.os.AsyncTask; @@ -26,7 +27,6 @@ import androidx.annotation.NonNull; import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.ProcessLifecycleOwner; -import androidx.multidex.MultiDexApplication; import org.conscrypt.Conscrypt; import org.session.libsession.avatars.AvatarHelper; @@ -104,7 +104,7 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant; * * @author Moxie Marlinspike */ -public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver { +public class ApplicationContext extends Application implements DependencyInjector, DefaultLifecycleObserver { public static final String PREFERENCES_NAME = "SecureSMS-Preferences"; @@ -180,12 +180,15 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc Log.i(TAG, "App is now visible."); KeyCachingService.onAppForegrounded(this); - if (poller != null) { - poller.setCaughtUp(false); - } - startPollingIfNeeded(); + ThreadUtils.queue(()->{ + if (poller != null) { + poller.setCaughtUp(false); + } - OpenGroupManager.INSTANCE.startPolling(); + startPollingIfNeeded(); + + OpenGroupManager.INSTANCE.startPolling(); + }); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 656da5fd66..f09b7cdf64 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -1206,7 +1206,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe val sortedMessages = messages.sortedBy { it.dateSent } val builder = StringBuilder() for (message in sortedMessages) { - val body = MentionUtilities.highlightMentions(message.body, message.threadId, this) + val body = MentionUtilities.highlightMentions(message.body, this) if (TextUtils.isEmpty(body)) { continue } val formattedTimestamp = DateUtils.getDisplayFormattedTimeSpanString(this, Locale.getDefault(), message.timestamp) builder.append("$formattedTimestamp: $body").append('\n') diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt index 1798b07f0a..aa649743ea 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt @@ -10,7 +10,6 @@ import androidx.annotation.ColorInt import androidx.core.content.res.ResourcesCompat import androidx.core.text.toSpannable import androidx.core.view.isVisible -import kotlinx.android.synthetic.main.view_link_preview.view.* import kotlinx.android.synthetic.main.view_quote.view.* import network.loki.messenger.R import org.session.libsession.messaging.contacts.Contact @@ -120,7 +119,7 @@ class QuoteView : LinearLayout { } quoteViewAuthorTextView.isVisible = thread.isGroupRecipient // Body - quoteViewBodyTextView.text = if (isOpenGroupInvitation) resources.getString(R.string.open_group_invitation_view__open_group_invitation) else MentionUtilities.highlightMentions((body ?: "").toSpannable(), threadID, context); + quoteViewBodyTextView.text = if (isOpenGroupInvitation) resources.getString(R.string.open_group_invitation_view__open_group_invitation) else MentionUtilities.highlightMentions((body ?: "").toSpannable(), context); quoteViewBodyTextView.setTextColor(getTextColor(isOutgoingMessage)) // Accent line / attachment preview val hasAttachments = (attachments != null && attachments.asAttachments().isNotEmpty()) && !isOriginalMissing diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt index ec55af5427..26d7b0905f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt @@ -223,7 +223,7 @@ class VisibleMessageContentView : LinearLayout { body.setSpan(replacementSpan, start, end, flags) } - body = MentionUtilities.highlightMentions(body, message.isOutgoing, message.threadId, context) + body = MentionUtilities.highlightMentions(body, message.isOutgoing, context) body = SearchUtil.getHighlightedSpan(Locale.getDefault(), StyleFactory { BackgroundColorSpan(Color.WHITE) }, body, searchQuery) body = SearchUtil.getHighlightedSpan(Locale.getDefault(), StyleFactory { ForegroundColorSpan(Color.BLACK) }, body, searchQuery) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt index 3a0c6e7c15..614414b88b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt @@ -19,15 +19,13 @@ import java.util.regex.Pattern object MentionUtilities { @JvmStatic - fun highlightMentions(text: CharSequence, threadID: Long, context: Context): String { - return highlightMentions(text, false, threadID, context).toString() // isOutgoingMessage is irrelevant + fun highlightMentions(text: CharSequence, context: Context): String { + return highlightMentions(text, false, context).toString() // isOutgoingMessage is irrelevant } @JvmStatic - fun highlightMentions(text: CharSequence, isOutgoingMessage: Boolean, threadID: Long, context: Context): SpannableString { + fun highlightMentions(text: CharSequence, isOutgoingMessage: Boolean, context: Context): SpannableString { @Suppress("NAME_SHADOWING") var text = text - val threadDB = DatabaseFactory.getThreadDatabase(context) - val isOpenGroup = threadDB.getRecipientForThreadId(threadID)?.isOpenGroupRecipient ?: false val pattern = Pattern.compile("@[0-9a-fA-F]*") var matcher = pattern.matcher(text) val mentions = mutableListOf, String>>() @@ -40,8 +38,7 @@ object MentionUtilities { TextSecurePreferences.getProfileName(context) } else { val contact = DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(publicKey) - @Suppress("NAME_SHADOWING") val context = if (isOpenGroup) Contact.ContactContext.OPEN_GROUP else Contact.ContactContext.REGULAR - contact?.displayName(context) + contact?.displayName(Contact.ContactContext.REGULAR) } if (userDisplayName != null) { text = text.subSequence(0, matcher.start()).toString() + "@" + userDisplayName + text.subSequence(matcher.end(), text.length) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt index 9454070e77..a5d4c1d87d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt @@ -69,7 +69,7 @@ class ConversationView : LinearLayout { } muteIndicatorImageView.setImageResource(drawableRes) val rawSnippet = thread.getDisplayBody(context) - val snippet = highlightMentions(rawSnippet, thread.threadId, context) + val snippet = highlightMentions(rawSnippet, context) snippetTextView.text = snippet snippetTextView.typeface = if (unreadCount > 0) Typeface.DEFAULT_BOLD else Typeface.DEFAULT snippetTextView.visibility = if (isTyping) View.GONE else View.VISIBLE diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index e03d25d270..80e91a85db 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -12,6 +12,7 @@ import android.text.SpannableString import android.text.style.ForegroundColorSpan import android.view.View import android.widget.Toast +import androidx.core.view.isVisible import androidx.lifecycle.Observer import androidx.lifecycle.lifecycleScope import androidx.loader.app.LoaderManager @@ -19,9 +20,11 @@ import androidx.loader.content.Loader import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.activity_home.* +import kotlinx.android.synthetic.main.seed_reminder_stub.view.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import network.loki.messenger.R import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe @@ -63,8 +66,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis // region Lifecycle override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) { super.onCreate(savedInstanceState, isReady) - // Double check that the long poller is up - (applicationContext as ApplicationContext).startPollingIfNeeded() // Set content view setContentView(R.layout.activity_home) // Set custom toolbar @@ -79,14 +80,18 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis // Set up seed reminder view val hasViewedSeed = TextSecurePreferences.getHasViewedSeed(this) if (!hasViewedSeed) { - val seedReminderViewTitle = SpannableString("You're almost finished! 80%") // Intentionally not yet translated - seedReminderViewTitle.setSpan(ForegroundColorSpan(resources.getColorWithID(R.color.accent, theme)), 24, 27, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - seedReminderView.title = seedReminderViewTitle - seedReminderView.subtitle = resources.getString(R.string.view_seed_reminder_subtitle_1) - seedReminderView.setProgress(80, false) - seedReminderView.delegate = this + seedReminderStub.isVisible = true + seedReminderStub.apply { + val seedReminderView = this.seedReminderView + val seedReminderViewTitle = SpannableString("You're almost finished! 80%") // Intentionally not yet translated + seedReminderViewTitle.setSpan(ForegroundColorSpan(resources.getColorWithID(R.color.accent, theme)), 24, 27, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + seedReminderView.title = seedReminderViewTitle + seedReminderView.subtitle = resources.getString(R.string.view_seed_reminder_subtitle_1) + seedReminderView.setProgress(80, false) + seedReminderView.delegate = this@HomeActivity + } } else { - seedReminderView.visibility = View.GONE + seedReminderStub.isVisible = false } // Set up recycler view val cursor = DatabaseFactory.getThreadDatabase(this).conversationList @@ -126,24 +131,30 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis this.broadcastReceiver = broadcastReceiver LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, IntentFilter("blockedContactsChanged")) lifecycleScope.launchWhenResumed { - // update things based on TextSecurePrefs (profile info etc) - // Set up typing observer - ApplicationContext.getInstance(this@HomeActivity).typingStatusRepository.typingThreads.observe(this@HomeActivity, Observer> { threadIDs -> - val adapter = recyclerView.adapter as HomeAdapter - adapter.typingThreadIDs = threadIDs ?: setOf() - }) - // Set up remaining components if needed - val application = ApplicationContext.getInstance(this@HomeActivity) - application.registerForFCMIfNeeded(false) - val userPublicKey = TextSecurePreferences.getLocalNumber(this@HomeActivity) - if (userPublicKey != null) { - OpenGroupManager.startPolling() - JobQueue.shared.resumePendingJobs() - } - updateProfileButton() - IP2Country.configureIfNeeded(this@HomeActivity) - TextSecurePreferences.events.filter { it == TextSecurePreferences.PROFILE_NAME_PREF }.collect { - updateProfileButton() + launch(Dispatchers.IO) { + // Double check that the long poller is up + (applicationContext as ApplicationContext).startPollingIfNeeded() + // update things based on TextSecurePrefs (profile info etc) + // Set up typing observer + withContext(Dispatchers.Main) { + ApplicationContext.getInstance(this@HomeActivity).typingStatusRepository.typingThreads.observe(this@HomeActivity, Observer> { threadIDs -> + val adapter = recyclerView.adapter as HomeAdapter + adapter.typingThreadIDs = threadIDs ?: setOf() + }) + updateProfileButton() + TextSecurePreferences.events.filter { it == TextSecurePreferences.PROFILE_NAME_PREF }.collect { + updateProfileButton() + } + } + // Set up remaining components if needed + val application = ApplicationContext.getInstance(this@HomeActivity) + application.registerForFCMIfNeeded(false) + val userPublicKey = TextSecurePreferences.getLocalNumber(this@HomeActivity) + if (userPublicKey != null) { + OpenGroupManager.startPolling() + JobQueue.shared.resumePendingJobs() + } + IP2Country.configureIfNeeded(this@HomeActivity) } } EventBus.getDefault().register(this@HomeActivity) @@ -158,7 +169,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis profileButton.update() val hasViewedSeed = TextSecurePreferences.getHasViewedSeed(this) if (hasViewedSeed) { - seedReminderView.visibility = View.GONE + seedReminderStub.visibility = View.GONE } if (TextSecurePreferences.getConfigurationMessageSynced(this)) { lifecycleScope.launch(Dispatchers.IO) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/longmessage/LongMessageActivity.java b/app/src/main/java/org/thoughtcrime/securesms/longmessage/LongMessageActivity.java index 04edf1194a..49fc990500 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/longmessage/LongMessageActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/longmessage/LongMessageActivity.java @@ -83,7 +83,7 @@ public class LongMessageActivity extends PassphraseRequiredActionBarActivity { } String trimmedBody = getTrimmedBody(message.get().getFullBody()); - String mentionBody = MentionUtilities.highlightMentions(trimmedBody, message.get().getMessageRecord().getThreadId(), this); + String mentionBody = MentionUtilities.highlightMentions(trimmedBody, this); textBody.setText(mentionBody); textBody.setMovementMethod(LinkMovementMethod.getInstance()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java index bdcf916dd4..a08eb1a79f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java @@ -324,7 +324,7 @@ public class DefaultMessageNotifier implements MessageNotifier { builder.setThread(notifications.get(0).getRecipient()); builder.setMessageCount(notificationState.getMessageCount()); builder.setPrimaryMessageBody(recipient, notifications.get(0).getIndividualRecipient(), - MentionUtilities.highlightMentions(notifications.get(0).getText(), notifications.get(0).getThreadId(), context), + MentionUtilities.highlightMentions(notifications.get(0).getText(), context), notifications.get(0).getSlideDeck()); builder.setContentIntent(notifications.get(0).getPendingIntent(context)); builder.setDeleteIntent(notificationState.getDeleteIntent(context)); @@ -400,13 +400,13 @@ public class DefaultMessageNotifier implements MessageNotifier { while(iterator.hasPrevious()) { NotificationItem item = iterator.previous(); builder.addMessageBody(item.getIndividualRecipient(), item.getRecipient(), - MentionUtilities.highlightMentions(item.getText(), item.getThreadId(), context)); + MentionUtilities.highlightMentions(item.getText(), context)); } if (signal) { builder.setAlarms(notificationState.getRingtone(context), notificationState.getVibrate()); builder.setTicker(notifications.get(0).getIndividualRecipient(), - MentionUtilities.highlightMentions(notifications.get(0).getText(), notifications.get(0).getThreadId(), context)); + MentionUtilities.highlightMentions(notifications.get(0).getText(), context)); } Notification notification = builder.build(); diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index 4a3e300d94..87bd87eb2d 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -70,10 +70,11 @@ android:background="?android:dividerHorizontal" android:elevation="1dp" /> - + android:layout_height="wrap_content"/> diff --git a/app/src/main/res/layout/seed_reminder_stub.xml b/app/src/main/res/layout/seed_reminder_stub.xml new file mode 100644 index 0000000000..39a84ac86a --- /dev/null +++ b/app/src/main/res/layout/seed_reminder_stub.xml @@ -0,0 +1,6 @@ + + \ No newline at end of file From 2a2d97be4ce1a00d4673802d9ad376a239048773 Mon Sep 17 00:00:00 2001 From: jubb Date: Fri, 30 Jul 2021 09:54:16 +1000 Subject: [PATCH 04/10] fix: revert simplified sendSingleThreadNotification that wasn't bundling properly, add mentions properly resolving by adding cache call --- .../notifications/DefaultMessageNotifier.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java index a08eb1a79f..d83c00dbe8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java @@ -49,6 +49,7 @@ import org.session.libsignal.utilities.Util; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.contactshare.ContactUtil; import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2; +import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities; import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo; @@ -273,9 +274,13 @@ public class DefaultMessageNotifier implements MessageNotifier { lastAudibleNotification = System.currentTimeMillis(); } - boolean hasMultipleThreads = notificationState.hasMultipleThreads(); - for (long threadId : notificationState.getThreads()) { - sendSingleThreadNotification(context, new NotificationState(notificationState.getNotificationsForThread(threadId)), signal, hasMultipleThreads); + if (notificationState.hasMultipleThreads()) { + for (long threadId : notificationState.getThreads()) { + sendSingleThreadNotification(context, new NotificationState(notificationState.getNotificationsForThread(threadId)), false, true); + } + sendMultipleThreadNotification(context, notificationState, signal); + } else if (notificationState.getMessageCount() > 0){ + sendSingleThreadNotification(context, notificationState, signal, false); } cancelOrphanedNotifications(context, notificationState); @@ -323,6 +328,7 @@ public class DefaultMessageNotifier implements MessageNotifier { builder.setThread(notifications.get(0).getRecipient()); builder.setMessageCount(notificationState.getMessageCount()); + MentionManagerUtilities.INSTANCE.populateUserPublicKeyCacheIfNeeded(notifications.get(0).getThreadId(),context); builder.setPrimaryMessageBody(recipient, notifications.get(0).getIndividualRecipient(), MentionUtilities.highlightMentions(notifications.get(0).getText(), context), notifications.get(0).getSlideDeck()); From 270af061d645d6cb424e8fe5df4e9fc98a155c3b Mon Sep 17 00:00:00 2001 From: jubb Date: Fri, 30 Jul 2021 10:05:07 +1000 Subject: [PATCH 05/10] fix: link preview works properly from new intent or draft --- .../securesms/conversation/v2/ConversationActivityV2.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index f09b7cdf64..76cbdd194c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -230,6 +230,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe setUpRecyclerView() setUpToolBar() setUpInputBar() + setUpLinkPreviewObserver() restoreDraftIfNeeded() addOpenGroupGuidelinesIfNeeded() scrollToBottomButton.setOnClickListener { conversationRecyclerView.smoothScrollToPosition(0) } @@ -240,7 +241,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe updateSubtitle() getLatestOpenGroupInfoIfNeeded() setUpBlockedBanner() - setUpLinkPreviewObserver() searchBottomBar.setEventListener(this) setUpSearchResultObserver() scrollToFirstUnreadMessageIfNeeded() From 7bf3b7a0333ba6ec0c2e142b32bb10c75b749e8d Mon Sep 17 00:00:00 2001 From: jubb Date: Fri, 30 Jul 2021 10:30:04 +1000 Subject: [PATCH 06/10] refactor: quotes also render for mention only notification style, fix mention manager not having public keys for conversations on load --- .../conversation/v2/ConversationActivityV2.kt | 6 ++---- .../notifications/DefaultMessageNotifier.java | 13 ++++++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 76cbdd194c..165fbbeaf2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -87,10 +87,7 @@ import org.thoughtcrime.securesms.conversation.v2.menus.ConversationMenuHelper import org.thoughtcrime.securesms.conversation.v2.messages.* import org.thoughtcrime.securesms.conversation.v2.search.SearchBottomBar import org.thoughtcrime.securesms.conversation.v2.search.SearchViewModel -import org.thoughtcrime.securesms.conversation.v2.utilities.AttachmentManager -import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog -import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities -import org.thoughtcrime.securesms.conversation.v2.utilities.ResendMessageUtilities +import org.thoughtcrime.securesms.conversation.v2.utilities.* import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.crypto.MnemonicUtilities import org.thoughtcrime.securesms.database.DatabaseFactory @@ -322,6 +319,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe val size = resources.getDimension(sizeID).roundToInt() profilePictureView.layoutParams = LinearLayout.LayoutParams(size, size) profilePictureView.glide = glide + MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded(threadID, this) profilePictureView.update(thread, threadID) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java index d83c00dbe8..e4002b4bb3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java @@ -40,6 +40,7 @@ import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier; +import org.session.libsession.utilities.Address; import org.session.libsession.utilities.Contact; import org.session.libsession.utilities.ServiceUtil; import org.session.libsession.utilities.TextSecurePreferences; @@ -59,6 +60,7 @@ import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MmsMessageRecord; +import org.thoughtcrime.securesms.database.model.Quote; import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.util.SessionMetaProtocol; @@ -67,6 +69,7 @@ import org.thoughtcrime.securesms.util.SpanUtil; import java.util.HashSet; import java.util.List; import java.util.ListIterator; +import java.util.Objects; import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -503,7 +506,15 @@ public class DefaultMessageNotifier implements MessageNotifier { if (threadRecipients == null || !threadRecipients.isMuted()) { if (threadRecipients != null && threadRecipients.notifyType == RecipientDatabase.NOTIFY_TYPE_MENTIONS) { // check if mentioned here - if (body.toString().contains("@"+TextSecurePreferences.getLocalNumber(context))) { + boolean isQuoteMentioned = false; + if (record instanceof MmsMessageRecord) { + Quote quote = ((MmsMessageRecord) record).getQuote(); + Address quoteAddress = quote != null ? quote.getAuthor() : null; + String serializedAddress = quoteAddress != null ? quoteAddress.serialize() : null; + isQuoteMentioned = serializedAddress != null && Objects.equals(TextSecurePreferences.getLocalNumber(context), serializedAddress); + } + if (body.toString().contains("@"+TextSecurePreferences.getLocalNumber(context)) + || isQuoteMentioned) { notificationState.addNotification(new NotificationItem(id, mms, recipient, conversationRecipient, threadRecipients, threadId, body, timestamp, slideDeck)); } } else if (threadRecipients != null && threadRecipients.notifyType == RecipientDatabase.NOTIFY_TYPE_NONE) { From 7890f5bd44cab63746be87c73e30ea1eb7186852 Mon Sep 17 00:00:00 2001 From: jubb Date: Fri, 30 Jul 2021 10:50:58 +1000 Subject: [PATCH 07/10] refactor: revert DB change experimentation from latest version --- .../securesms/database/helpers/SQLCipherOpenHelper.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 62a5e85575..106528ee25 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -143,10 +143,11 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { } @Override - public void onOpen(SQLiteDatabase db) { - super.onOpen(db); + public void onConfigure(SQLiteDatabase db) { + super.onConfigure(db); // Loki - Enable write ahead logging mode and increase the cache size. // This should be disabled if we ever run into serious race condition bugs. + db.enableWriteAheadLogging(); db.execSQL("PRAGMA cache_size = 10000"); } @@ -191,7 +192,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { if (oldVersion < lokiV14_BACKUP_FILES) { db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand()); } - + if (oldVersion < lokiV16) { db.execSQL(LokiAPIDatabase.getCreateOpenGroupProfilePictureTableCommand()); } From 3911f51ae531373909a0f41d36989a267072bc29 Mon Sep 17 00:00:00 2001 From: jubb Date: Fri, 30 Jul 2021 10:58:13 +1000 Subject: [PATCH 08/10] refactor: revert retry interval --- .../libsession/messaging/sending_receiving/pollers/Poller.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt index e077835e5f..bbf2620f97 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt @@ -22,7 +22,7 @@ class Poller { // region Settings companion object { - private val retryInterval: Long = 3 * 1000 + private val retryInterval: Long = 1 * 1000 } // endregion From 22905787f6b7a5c574ad046af337a033b875d5d2 Mon Sep 17 00:00:00 2001 From: jubb Date: Fri, 30 Jul 2021 11:00:53 +1000 Subject: [PATCH 09/10] refactor: move when resumed to started --- .../main/java/org/thoughtcrime/securesms/home/HomeActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index 80e91a85db..abeb3b2038 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -130,7 +130,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis } this.broadcastReceiver = broadcastReceiver LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, IntentFilter("blockedContactsChanged")) - lifecycleScope.launchWhenResumed { + lifecycleScope.launchWhenStarted { launch(Dispatchers.IO) { // Double check that the long poller is up (applicationContext as ApplicationContext).startPollingIfNeeded() From 072ea41b46ff81f3a35b8b568567b51351d2441e Mon Sep 17 00:00:00 2001 From: jubb Date: Fri, 30 Jul 2021 13:42:39 +1000 Subject: [PATCH 10/10] refactor: re-add thread ID for mentions, fix path resolver call refactor: re-add thread ID for mentions, fix path resolver call --- .../conversation/v2/ConversationActivityV2.kt | 2 +- .../securesms/conversation/v2/messages/QuoteView.kt | 2 +- .../v2/messages/VisibleMessageContentView.kt | 2 +- .../conversation/v2/utilities/MentionUtilities.kt | 11 +++++++---- .../thoughtcrime/securesms/home/ConversationView.kt | 2 +- .../org/thoughtcrime/securesms/home/HomeActivity.kt | 2 +- .../securesms/longmessage/LongMessageActivity.java | 2 +- .../notifications/DefaultMessageNotifier.java | 8 +++++--- app/src/main/res/layout/seed_reminder_stub.xml | 2 +- 9 files changed, 19 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 165fbbeaf2..4a86d5edc5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -1204,7 +1204,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe val sortedMessages = messages.sortedBy { it.dateSent } val builder = StringBuilder() for (message in sortedMessages) { - val body = MentionUtilities.highlightMentions(message.body, this) + val body = MentionUtilities.highlightMentions(message.body, threadID, this) if (TextUtils.isEmpty(body)) { continue } val formattedTimestamp = DateUtils.getDisplayFormattedTimeSpanString(this, Locale.getDefault(), message.timestamp) builder.append("$formattedTimestamp: $body").append('\n') diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt index aa649743ea..0f6fe2773d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt @@ -119,7 +119,7 @@ class QuoteView : LinearLayout { } quoteViewAuthorTextView.isVisible = thread.isGroupRecipient // Body - quoteViewBodyTextView.text = if (isOpenGroupInvitation) resources.getString(R.string.open_group_invitation_view__open_group_invitation) else MentionUtilities.highlightMentions((body ?: "").toSpannable(), context); + quoteViewBodyTextView.text = if (isOpenGroupInvitation) resources.getString(R.string.open_group_invitation_view__open_group_invitation) else MentionUtilities.highlightMentions((body ?: "").toSpannable(), threadID, context); quoteViewBodyTextView.setTextColor(getTextColor(isOutgoingMessage)) // Accent line / attachment preview val hasAttachments = (attachments != null && attachments.asAttachments().isNotEmpty()) && !isOriginalMissing diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt index 26d7b0905f..ec55af5427 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt @@ -223,7 +223,7 @@ class VisibleMessageContentView : LinearLayout { body.setSpan(replacementSpan, start, end, flags) } - body = MentionUtilities.highlightMentions(body, message.isOutgoing, context) + body = MentionUtilities.highlightMentions(body, message.isOutgoing, message.threadId, context) body = SearchUtil.getHighlightedSpan(Locale.getDefault(), StyleFactory { BackgroundColorSpan(Color.WHITE) }, body, searchQuery) body = SearchUtil.getHighlightedSpan(Locale.getDefault(), StyleFactory { ForegroundColorSpan(Color.BLACK) }, body, searchQuery) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt index 614414b88b..3a0c6e7c15 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt @@ -19,13 +19,15 @@ import java.util.regex.Pattern object MentionUtilities { @JvmStatic - fun highlightMentions(text: CharSequence, context: Context): String { - return highlightMentions(text, false, context).toString() // isOutgoingMessage is irrelevant + fun highlightMentions(text: CharSequence, threadID: Long, context: Context): String { + return highlightMentions(text, false, threadID, context).toString() // isOutgoingMessage is irrelevant } @JvmStatic - fun highlightMentions(text: CharSequence, isOutgoingMessage: Boolean, context: Context): SpannableString { + fun highlightMentions(text: CharSequence, isOutgoingMessage: Boolean, threadID: Long, context: Context): SpannableString { @Suppress("NAME_SHADOWING") var text = text + val threadDB = DatabaseFactory.getThreadDatabase(context) + val isOpenGroup = threadDB.getRecipientForThreadId(threadID)?.isOpenGroupRecipient ?: false val pattern = Pattern.compile("@[0-9a-fA-F]*") var matcher = pattern.matcher(text) val mentions = mutableListOf, String>>() @@ -38,7 +40,8 @@ object MentionUtilities { TextSecurePreferences.getProfileName(context) } else { val contact = DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(publicKey) - contact?.displayName(Contact.ContactContext.REGULAR) + @Suppress("NAME_SHADOWING") val context = if (isOpenGroup) Contact.ContactContext.OPEN_GROUP else Contact.ContactContext.REGULAR + contact?.displayName(context) } if (userDisplayName != null) { text = text.subSequence(0, matcher.start()).toString() + "@" + userDisplayName + text.subSequence(matcher.end(), text.length) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt index a5d4c1d87d..9454070e77 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt @@ -69,7 +69,7 @@ class ConversationView : LinearLayout { } muteIndicatorImageView.setImageResource(drawableRes) val rawSnippet = thread.getDisplayBody(context) - val snippet = highlightMentions(rawSnippet, context) + val snippet = highlightMentions(rawSnippet, thread.threadId, context) snippetTextView.text = snippet snippetTextView.typeface = if (unreadCount > 0) Typeface.DEFAULT_BOLD else Typeface.DEFAULT snippetTextView.visibility = if (isTyping) View.GONE else View.VISIBLE diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index abeb3b2038..4a59fcdba8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -103,6 +103,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis recyclerView.layoutManager = LinearLayoutManager(this) // Set up empty state view createNewPrivateChatButton.setOnClickListener { createNewPrivateChat() } + IP2Country.configureIfNeeded(this@HomeActivity) // This is a workaround for the fact that CursorRecyclerViewAdapter doesn't actually auto-update (even though it says it will) LoaderManager.getInstance(this).restartLoader(0, null, object : LoaderManager.LoaderCallbacks { @@ -154,7 +155,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis OpenGroupManager.startPolling() JobQueue.shared.resumePendingJobs() } - IP2Country.configureIfNeeded(this@HomeActivity) } } EventBus.getDefault().register(this@HomeActivity) diff --git a/app/src/main/java/org/thoughtcrime/securesms/longmessage/LongMessageActivity.java b/app/src/main/java/org/thoughtcrime/securesms/longmessage/LongMessageActivity.java index 49fc990500..04edf1194a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/longmessage/LongMessageActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/longmessage/LongMessageActivity.java @@ -83,7 +83,7 @@ public class LongMessageActivity extends PassphraseRequiredActionBarActivity { } String trimmedBody = getTrimmedBody(message.get().getFullBody()); - String mentionBody = MentionUtilities.highlightMentions(trimmedBody, this); + String mentionBody = MentionUtilities.highlightMentions(trimmedBody, message.get().getMessageRecord().getThreadId(), this); textBody.setText(mentionBody); textBody.setMovementMethod(LinkMovementMethod.getInstance()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java index e4002b4bb3..e7f8e8e5c8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java @@ -333,7 +333,9 @@ public class DefaultMessageNotifier implements MessageNotifier { builder.setMessageCount(notificationState.getMessageCount()); MentionManagerUtilities.INSTANCE.populateUserPublicKeyCacheIfNeeded(notifications.get(0).getThreadId(),context); builder.setPrimaryMessageBody(recipient, notifications.get(0).getIndividualRecipient(), - MentionUtilities.highlightMentions(notifications.get(0).getText(), context), + MentionUtilities.highlightMentions(notifications.get(0).getText(), + notifications.get(0).getThreadId(), + context), notifications.get(0).getSlideDeck()); builder.setContentIntent(notifications.get(0).getPendingIntent(context)); builder.setDeleteIntent(notificationState.getDeleteIntent(context)); @@ -409,13 +411,13 @@ public class DefaultMessageNotifier implements MessageNotifier { while(iterator.hasPrevious()) { NotificationItem item = iterator.previous(); builder.addMessageBody(item.getIndividualRecipient(), item.getRecipient(), - MentionUtilities.highlightMentions(item.getText(), context)); + MentionUtilities.highlightMentions(item.getText(), item.getThreadId(), context)); } if (signal) { builder.setAlarms(notificationState.getRingtone(context), notificationState.getVibrate()); builder.setTicker(notifications.get(0).getIndividualRecipient(), - MentionUtilities.highlightMentions(notifications.get(0).getText(), context)); + MentionUtilities.highlightMentions(notifications.get(0).getText(), notifications.get(0).getThreadId(), context)); } Notification notification = builder.build(); diff --git a/app/src/main/res/layout/seed_reminder_stub.xml b/app/src/main/res/layout/seed_reminder_stub.xml index 39a84ac86a..fcaa9c6b48 100644 --- a/app/src/main/res/layout/seed_reminder_stub.xml +++ b/app/src/main/res/layout/seed_reminder_stub.xml @@ -3,4 +3,4 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/seedReminderView" android:layout_width="match_parent" - android:layout_height="wrap_content" /> \ No newline at end of file + android:layout_height="wrap_content" />