diff --git a/app/build.gradle b/app/build.gradle index 562cbe713c..0d7e670c79 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -142,7 +142,7 @@ dependencies { testImplementation 'org.robolectric:shadows-multidex:4.2' } -def canonicalVersionCode = 211 +def canonicalVersionCode = 214 def canonicalVersionName = "1.11.7" def postFixSize = 10 diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionManagerUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionManagerUtilities.kt index 31d650a671..4beb5e6d47 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionManagerUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionManagerUtilities.kt @@ -9,13 +9,15 @@ import org.thoughtcrime.securesms.database.model.MessageRecord object MentionManagerUtilities { fun populateUserPublicKeyCacheIfNeeded(threadID: Long, context: Context) { + // exit early if we need to + if (MentionsManager.userPublicKeyCache[threadID] != null) return + val result = mutableSetOf() val recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID) if (recipient != null && recipient.address.isClosedGroup) { val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.address.toGroupString(), false).map { it.address.serialize() } result.addAll(members) } else { - if (MentionsManager.userPublicKeyCache[threadID] != null) { return } val messageDatabase = DatabaseFactory.getMmsSmsDatabase(context) val reader = messageDatabase.readerFor(messageDatabase.getConversation(threadID)) var record: MessageRecord? = reader.next 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..4a34b15ff2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt @@ -12,6 +12,8 @@ import androidx.core.content.ContextCompat import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.view_conversation.view.* +import kotlinx.android.synthetic.main.view_profile_picture.view.* +import kotlinx.coroutines.* import network.loki.messenger.R import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded @@ -40,56 +42,63 @@ class ConversationView : LinearLayout { // region Updating fun bind(thread: ThreadRecord, isTyping: Boolean, glide: GlideRequests) { this.thread = thread - populateUserPublicKeyCacheIfNeeded(thread.threadId, context) // FIXME: This is a bad place to do this - val unreadCount = thread.unreadCount - if (thread.recipient.isBlocked) { - accentView.setBackgroundResource(R.color.destructive) - accentView.visibility = View.VISIBLE - } else { - accentView.setBackgroundResource(R.color.accent) - accentView.visibility = if (unreadCount > 0) View.VISIBLE else View.INVISIBLE - } - val formattedUnreadCount = if (unreadCount < 100) unreadCount.toString() else "99+" - unreadCountTextView.text = formattedUnreadCount - val textSize = if (unreadCount < 100) 12.0f else 9.0f - unreadCountTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize) - unreadCountTextView.setTypeface(Typeface.DEFAULT, if (unreadCount < 100) Typeface.BOLD else Typeface.NORMAL) - unreadCountIndicator.isVisible = (unreadCount != 0) profilePictureView.glide = glide - profilePictureView.update(thread.recipient, thread.threadId) - val senderDisplayName = getUserDisplayName(thread.recipient) ?: thread.recipient.address.toString() - conversationViewDisplayNameTextView.text = senderDisplayName - timestampTextView.text = DateUtils.getDisplayFormattedTimeSpanString(context, Locale.getDefault(), thread.date) - val recipient = thread.recipient - muteIndicatorImageView.isVisible = recipient.isMuted || recipient.notifyType != RecipientDatabase.NOTIFY_TYPE_ALL - val drawableRes = if (recipient.isMuted || recipient.notifyType == RecipientDatabase.NOTIFY_TYPE_NONE) { - R.drawable.ic_outline_notifications_off_24 - } else { - R.drawable.ic_notifications_mentions - } - muteIndicatorImageView.setImageResource(drawableRes) - val rawSnippet = thread.getDisplayBody(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 - if (isTyping) { - typingIndicatorView.startAnimation() - } else { - typingIndicatorView.stopAnimation() - } - typingIndicatorView.visibility = if (isTyping) View.VISIBLE else View.GONE - statusIndicatorImageView.visibility = View.VISIBLE - when { - !thread.isOutgoing -> statusIndicatorImageView.visibility = View.GONE - thread.isFailed -> { - val drawable = ContextCompat.getDrawable(context, R.drawable.ic_error)?.mutate() - drawable?.setTint(ContextCompat.getColor(context,R.color.destructive)) - statusIndicatorImageView.setImageDrawable(drawable) + post { + val unreadCount = thread.unreadCount + if (thread.recipient.isBlocked) { + accentView.setBackgroundResource(R.color.destructive) + accentView.visibility = View.VISIBLE + } else { + accentView.setBackgroundResource(R.color.accent) + accentView.visibility = if (unreadCount > 0) View.VISIBLE else View.INVISIBLE + } + val formattedUnreadCount = if (unreadCount < 100) unreadCount.toString() else "99+" + unreadCountTextView.text = formattedUnreadCount + val textSize = if (unreadCount < 100) 12.0f else 9.0f + unreadCountTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize) + unreadCountTextView.setTypeface(Typeface.DEFAULT, if (unreadCount < 100) Typeface.BOLD else Typeface.NORMAL) + unreadCountIndicator.isVisible = (unreadCount != 0) + val senderDisplayName = getUserDisplayName(thread.recipient) + ?: thread.recipient.address.toString() + conversationViewDisplayNameTextView.text = senderDisplayName + timestampTextView.text = DateUtils.getDisplayFormattedTimeSpanString(context, Locale.getDefault(), thread.date) + val recipient = thread.recipient + muteIndicatorImageView.isVisible = recipient.isMuted || recipient.notifyType != RecipientDatabase.NOTIFY_TYPE_ALL + val drawableRes = if (recipient.isMuted || recipient.notifyType == RecipientDatabase.NOTIFY_TYPE_NONE) { + R.drawable.ic_outline_notifications_off_24 + } else { + R.drawable.ic_notifications_mentions + } + muteIndicatorImageView.setImageResource(drawableRes) + val rawSnippet = thread.getDisplayBody(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 + if (isTyping) { + typingIndicatorView.startAnimation() + } else { + typingIndicatorView.stopAnimation() + } + typingIndicatorView.visibility = if (isTyping) View.VISIBLE else View.GONE + statusIndicatorImageView.visibility = View.VISIBLE + when { + !thread.isOutgoing -> statusIndicatorImageView.visibility = View.GONE + thread.isFailed -> { + val drawable = ContextCompat.getDrawable(context, R.drawable.ic_error)?.mutate() + drawable?.setTint(ContextCompat.getColor(context, R.color.destructive)) + statusIndicatorImageView.setImageDrawable(drawable) + } + thread.isPending -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_dot_dot_dot) + thread.isRead -> statusIndicatorImageView.setImageResource(R.drawable.ic_filled_circle_check) + else -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_check) + } + GlobalScope.launch(Dispatchers.IO) { + populateUserPublicKeyCacheIfNeeded(thread.threadId, context) // FIXME: This is a bad place to do this + withContext(Dispatchers.Main) { + profilePictureView.update(thread.recipient, thread.threadId) + } } - thread.isPending -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_dot_dot_dot) - thread.isRead -> statusIndicatorImageView.setImageResource(R.drawable.ic_filled_circle_check) - else -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_check) } } 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 4a59fcdba8..d8bc59d7da 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -80,8 +80,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis // Set up seed reminder view val hasViewedSeed = TextSecurePreferences.getHasViewedSeed(this) if (!hasViewedSeed) { - seedReminderStub.isVisible = true - seedReminderStub.apply { + seedReminderStub.inflate().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)