diff --git a/res/drawable/profile_picture_view_large_background.xml b/res/drawable/profile_picture_view_large_background.xml index bfc404e25f..c5f6d91a0d 100644 --- a/res/drawable/profile_picture_view_large_background.xml +++ b/res/drawable/profile_picture_view_large_background.xml @@ -3,7 +3,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - + diff --git a/res/drawable/profile_picture_view_large_foreground.xml b/res/drawable/profile_picture_view_large_foreground.xml index 18cac49b38..7d6f94a2b4 100644 --- a/res/drawable/profile_picture_view_large_foreground.xml +++ b/res/drawable/profile_picture_view_large_foreground.xml @@ -7,5 +7,5 @@ - + \ No newline at end of file diff --git a/res/drawable/profile_picture_view_medium_background.xml b/res/drawable/profile_picture_view_medium_background.xml index 287d6298e2..2b379dec4e 100644 --- a/res/drawable/profile_picture_view_medium_background.xml +++ b/res/drawable/profile_picture_view_medium_background.xml @@ -3,9 +3,9 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - + - + \ No newline at end of file diff --git a/res/drawable/profile_picture_view_medium_foreground.xml b/res/drawable/profile_picture_view_medium_foreground.xml index e62cfbe3fb..e05dd6aaba 100644 --- a/res/drawable/profile_picture_view_medium_foreground.xml +++ b/res/drawable/profile_picture_view_medium_foreground.xml @@ -7,5 +7,5 @@ - + \ No newline at end of file diff --git a/res/drawable/profile_picture_view_rss_medium_background.xml b/res/drawable/profile_picture_view_rss_medium_background.xml index b060c41b4b..9496e53ed0 100644 --- a/res/drawable/profile_picture_view_rss_medium_background.xml +++ b/res/drawable/profile_picture_view_rss_medium_background.xml @@ -3,9 +3,9 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - + - + \ No newline at end of file diff --git a/res/drawable/profile_picture_view_small_background.xml b/res/drawable/profile_picture_view_small_background.xml index 2f44fefe9f..d01f12f77a 100644 --- a/res/drawable/profile_picture_view_small_background.xml +++ b/res/drawable/profile_picture_view_small_background.xml @@ -3,9 +3,9 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - + - + \ No newline at end of file diff --git a/res/drawable/profile_picture_view_small_foreground.xml b/res/drawable/profile_picture_view_small_foreground.xml index 98d2b0a4e7..6a46584bf8 100644 --- a/res/drawable/profile_picture_view_small_foreground.xml +++ b/res/drawable/profile_picture_view_small_foreground.xml @@ -7,5 +7,5 @@ - + \ No newline at end of file diff --git a/res/layout/view_profile_picture.xml b/res/layout/view_profile_picture.xml index 2cae135b49..ba9c55df02 100644 --- a/res/layout/view_profile_picture.xml +++ b/res/layout/view_profile_picture.xml @@ -1,8 +1,8 @@ - + android:layout_height="wrap_content" + xmlns:app="http://schemas.android.com/apk/res-auto"> #000000 #f26f55 #606060 + #23000000 + #B0B0B0 #FCFCFC #DFDFDF #FCFCFC diff --git a/res/values/colors.xml b/res/values/colors.xml index a7ff67af2f..ca2a48f500 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -7,6 +7,8 @@ #FFFFFF #FF453A #D8D8D8 + #23FFFFFF + #353535 #979797 #1B1B1B #0C0C0C @@ -29,6 +31,13 @@ #1B1B1B #212121 #FFCE3A + + + #5ff8b0 + #26cdb9 + #f3c615 + #fcac5a + diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationItem.java b/src/org/thoughtcrime/securesms/conversation/ConversationItem.java index ca3d10db17..ed4f24d110 100644 --- a/src/org/thoughtcrime/securesms/conversation/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/conversation/ConversationItem.java @@ -804,6 +804,7 @@ public class ConversationItem extends LinearLayout bodyBubble.setLayoutParams(layoutParams); if (profilePictureView == null) return; profilePictureView.setPublicKey(recipient.getAddress().toString()); + profilePictureView.setDisplayName(recipient.getName()); profilePictureView.setAdditionalPublicKey(null); profilePictureView.setRSSFeed(false); profilePictureView.setGlide(glideRequests); diff --git a/src/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt index 2764601dcf..251f756761 100644 --- a/src/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt @@ -1,7 +1,6 @@ package org.thoughtcrime.securesms.loki.activities import android.app.AlertDialog -import androidx.lifecycle.Observer import android.content.BroadcastReceiver import android.content.Context import android.content.Intent @@ -11,10 +10,6 @@ import android.net.Uri import android.os.AsyncTask import android.os.Bundle import android.os.Handler -import androidx.loader.app.LoaderManager -import androidx.loader.content.Loader -import androidx.localbroadcastmanager.content.LocalBroadcastManager -import androidx.recyclerview.widget.LinearLayoutManager import android.text.Spannable import android.text.SpannableString import android.text.style.ForegroundColorSpan @@ -22,6 +17,11 @@ import android.util.DisplayMetrics import android.view.View import android.widget.RelativeLayout import android.widget.Toast +import androidx.lifecycle.Observer +import androidx.loader.app.LoaderManager +import androidx.loader.content.Loader +import androidx.localbroadcastmanager.content.LocalBroadcastManager +import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.activity_home.* import network.loki.messenger.R import org.thoughtcrime.securesms.ApplicationContext @@ -43,14 +43,13 @@ import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetViewDelegat import org.thoughtcrime.securesms.loki.views.SeedReminderViewDelegate import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideRequests -import org.thoughtcrime.securesms.util.GroupUtil import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.Util import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol -import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocol +import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol import org.whispersystems.signalservice.loki.protocol.shelved.syncmessages.SyncMessagesProtocol import org.whispersystems.signalservice.loki.utilities.toHexString @@ -99,6 +98,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe // Set up toolbar buttons profileButton.glide = glide profileButton.publicKey = publicKey + profileButton.displayName = TextSecurePreferences.getProfileName(this) profileButton.update() profileButton.setOnClickListener { openSettings() } pathStatusViewContainer.disableClipping() diff --git a/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt index 1a88113784..6f110b9ca7 100644 --- a/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt @@ -52,10 +52,8 @@ import java.security.SecureRandom import java.util.* class SettingsActivity : PassphraseRequiredActionBarActivity() { - private var displayNameEditActionMode: ActionMode? = null set(value) { field = value; handleDisplayNameEditActionModeChanged() } - private lateinit var glide: GlideRequests private var displayNameToBeUploaded: String? = null private var profilePictureToBeUploaded: ByteArray? = null @@ -71,17 +69,17 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { // region Lifecycle override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) { super.onCreate(savedInstanceState, isReady) - setContentView(R.layout.activity_settings) - + val displayName = DatabaseFactory.getLokiUserDatabase(this).getDisplayName(hexEncodedPublicKey) glide = GlideApp.with(this) profilePictureView.glide = glide profilePictureView.publicKey = hexEncodedPublicKey + profilePictureView.displayName = displayName profilePictureView.isLarge = true profilePictureView.update() profilePictureView.setOnClickListener { showEditProfilePictureUI() } ctnGroupNameSection.setOnClickListener { startActionMode(DisplayNameEditActionModeCallback()) } - btnGroupNameDisplay.text = DatabaseFactory.getLokiUserDatabase(this).getDisplayName(hexEncodedPublicKey) + btnGroupNameDisplay.text = displayName publicKeyTextView.text = hexEncodedPublicKey copyButton.setOnClickListener { copyPublicKey() } shareButton.setOnClickListener { sharePublicKey() } @@ -103,12 +101,9 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.settings_general, menu) - - // Update UI mode menu icon. - // It uses three-level selector where each level corresponds to the related UiMode ordinal value. + // Update UI mode menu icon val uiMode = UiModeUtilities.getUserSelectedUiMode(this) menu.findItem(R.id.action_change_theme).icon!!.level = uiMode.ordinal - return true } diff --git a/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt b/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt new file mode 100644 index 0000000000..70343f8434 --- /dev/null +++ b/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt @@ -0,0 +1,79 @@ +package org.thoughtcrime.securesms.loki.todo + +import android.content.Context +import android.graphics.* +import android.graphics.drawable.BitmapDrawable +import android.text.TextPaint +import android.text.TextUtils +import androidx.annotation.ColorInt +import androidx.core.graphics.ColorUtils +import network.loki.messenger.R +import java.util.* + +object AvatarPlaceholderGenerator { + private val tmpFloatArray = FloatArray(3) + + private const val EMPTY_LABEL = "0"; + + fun generate(context: Context, pixelSize: Int, hashString: String, displayName: String?): BitmapDrawable { + //TODO That should be replaced with a proper hash extraction code. + val hash: Long + if (hashString.length >= 12 && hashString.matches(Regex("^[0-9A-Fa-f]+\$"))) { + hash = hashString.substring(0 until 12).toLong(16) + } else { + hash = 0 + } + + // Do not cache color array, it may be different depends on the current theme. + val colorArray = context.resources.getIntArray(R.array.profile_picture_placeholder_colors) + val colorPrimary = colorArray[(hash % colorArray.size).toInt()] + val colorSecondary = changeColorHueBy(colorPrimary, 12f) + + val labelText = when { + !TextUtils.isEmpty(displayName) -> extractLabel(displayName!!) + !TextUtils.isEmpty(hashString) -> extractLabel(hashString) + else -> EMPTY_LABEL + } + + val bitmap = Bitmap.createBitmap(pixelSize, pixelSize, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + + // Draw background/frame + val paint = Paint(Paint.ANTI_ALIAS_FLAG) + paint.shader = LinearGradient(0f, 0f, 0f, pixelSize.toFloat(), + colorPrimary, + colorPrimary, + Shader.TileMode.REPEAT) + canvas.drawCircle(pixelSize.toFloat() / 2, pixelSize.toFloat() / 2, pixelSize.toFloat() / 2, paint) + + // Draw text + val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG) + textPaint.typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL) + textPaint.textSize = pixelSize * 0.5f + textPaint.color = Color.WHITE + val areaRect = Rect(0, 0, pixelSize, pixelSize) + val textBounds = RectF(areaRect) + textBounds.right = textPaint.measureText(labelText) + textBounds.bottom = textPaint.descent() - textPaint.ascent() + textBounds.left += (areaRect.width() - textBounds.right) * 0.5f + textBounds.top += (areaRect.height() - textBounds.bottom) * 0.5f + canvas.drawText(labelText, textBounds.left, textBounds.top - textPaint.ascent(), textPaint) + + return BitmapDrawable(context.resources, bitmap) + } + + @ColorInt + private fun changeColorHueBy(@ColorInt color: Int, hueDelta: Float): Int { + val hslColor = tmpFloatArray + ColorUtils.colorToHSL(color, hslColor) + hslColor[0] = (hslColor[0] + hueDelta) % 360f + return ColorUtils.HSLToColor(hslColor) + } + + private fun extractLabel(content: String): String { + var content = content.trim() + if (content.isEmpty()) return EMPTY_LABEL + + return content.first().toString().toUpperCase(Locale.ROOT) + } +} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/views/ConversationView.kt b/src/org/thoughtcrime/securesms/loki/views/ConversationView.kt index ebc6c679be..f51850db6f 100644 --- a/src/org/thoughtcrime/securesms/loki/views/ConversationView.kt +++ b/src/org/thoughtcrime/securesms/loki/views/ConversationView.kt @@ -2,12 +2,14 @@ package org.thoughtcrime.securesms.loki.views import android.content.Context import android.graphics.Typeface +import android.text.TextUtils import android.util.AttributeSet import android.view.LayoutInflater import android.view.View import android.widget.LinearLayout import kotlinx.android.synthetic.main.view_conversation.view.* import network.loki.messenger.R +import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.model.ThreadRecord import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded import org.thoughtcrime.securesms.loki.utilities.MentionUtilities.highlightMentions @@ -81,5 +83,10 @@ class ConversationView : LinearLayout { else -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_check) } } + + private fun getUserDisplayName(publicKey: String?): String? { + if (TextUtils.isEmpty(publicKey)) return null + return DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey!!) + } // endregion } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt b/src/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt index 1e6a0d057c..a9b62a5fd9 100644 --- a/src/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt +++ b/src/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt @@ -32,6 +32,7 @@ class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr: private fun update() { btnGroupNameDisplay.text = mentionCandidate.displayName profilePictureView.publicKey = mentionCandidate.publicKey + profilePictureView.displayName = mentionCandidate.displayName profilePictureView.additionalPublicKey = null profilePictureView.isRSSFeed = false profilePictureView.glide = glide!! diff --git a/src/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt b/src/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt index de93c4b81d..8186639c5f 100644 --- a/src/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt +++ b/src/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt @@ -1,19 +1,19 @@ package org.thoughtcrime.securesms.loki.views import android.content.Context -import androidx.annotation.DimenRes import android.util.AttributeSet import android.view.LayoutInflater import android.view.View import android.widget.ImageView import android.widget.RelativeLayout +import androidx.annotation.DimenRes import com.bumptech.glide.load.engine.DiskCacheStrategy -import kotlinx.android.synthetic.main.view_conversation.view.* import kotlinx.android.synthetic.main.view_profile_picture.view.* import network.loki.messenger.R import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto import org.thoughtcrime.securesms.database.Address -import org.thoughtcrime.securesms.loki.todo.JazzIdenticonDrawable +import org.thoughtcrime.securesms.database.DatabaseFactory +import org.thoughtcrime.securesms.loki.todo.AvatarPlaceholderGenerator import org.thoughtcrime.securesms.mms.GlideRequests import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.util.TextSecurePreferences @@ -24,7 +24,9 @@ import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager class ProfilePictureView : RelativeLayout { lateinit var glide: GlideRequests var publicKey: String? = null + var displayName: String? = null var additionalPublicKey: String? = null + var additionalDisplayName: String? = null var isRSSFeed = false var isLarge = false @@ -54,9 +56,17 @@ class ProfilePictureView : RelativeLayout { // region Updating fun update(recipient: Recipient, threadID: Long) { + fun getUserDisplayName(publicKey: String?): String? { + if (publicKey == null || publicKey.isBlank()) { + return null + } else { + return DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey!!) + } + } if (recipient.isGroupRecipient) { if ("Session Public Chat" == recipient.name) { publicKey = "" + displayName = "" additionalPublicKey = null isRSSFeed = true } else { @@ -67,12 +77,17 @@ class ProfilePictureView : RelativeLayout { users.remove(masterPublicKey) } val randomUsers = users.sorted() // Sort to provide a level of stability - publicKey = randomUsers.getOrNull(0) ?: "" - additionalPublicKey = randomUsers.getOrNull(1) ?: "" + val pk = randomUsers.getOrNull(0) ?: "" + publicKey = pk + displayName = getUserDisplayName(pk) + val apk = randomUsers.getOrNull(1) ?: "" + additionalPublicKey = apk + additionalDisplayName = getUserDisplayName(apk) isRSSFeed = recipient.name == "Loki News" || recipient.name == "Session Updates" } } else { publicKey = recipient.address.toString() + displayName = recipient.name additionalPublicKey = null isRSSFeed = false } @@ -86,28 +101,50 @@ class ProfilePictureView : RelativeLayout { singleModeImageViewContainer.visibility = if (additionalPublicKey == null && !isRSSFeed && !isLarge) View.VISIBLE else View.INVISIBLE largeSingleModeImageViewContainer.visibility = if (additionalPublicKey == null && !isRSSFeed && isLarge) View.VISIBLE else View.INVISIBLE rssImageView.visibility = if (isRSSFeed) View.VISIBLE else View.INVISIBLE - fun setProfilePictureIfNeeded(imageView: ImageView, hexEncodedPublicKey: String, @DimenRes sizeID: Int) { - glide.clear(imageView) - if (hexEncodedPublicKey.isNotEmpty()) { - val recipient = Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false); - val signalProfilePicture = recipient.contactPhoto - if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0" && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "") { - glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView) - } else { - val size = resources.getDimensionPixelSize(sizeID) - val masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context) - val hepk = if (recipient.isLocalNumber && masterHexEncodedPublicKey != null) masterHexEncodedPublicKey else hexEncodedPublicKey - val jazzIcon = JazzIdenticonDrawable(size, size, hepk) - glide.load(jazzIcon).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView) - } + setProfilePictureIfNeeded( + doubleModeImageView1, + publicKey, + displayName, + R.dimen.small_profile_picture_size) + setProfilePictureIfNeeded( + doubleModeImageView2, + additionalPublicKey ?: "", + additionalDisplayName, + R.dimen.small_profile_picture_size) + setProfilePictureIfNeeded( + singleModeImageView, + publicKey, + displayName, + R.dimen.medium_profile_picture_size) + setProfilePictureIfNeeded( + largeSingleModeImageView, + publicKey, + displayName, + R.dimen.large_profile_picture_size) + } + + private fun setProfilePictureIfNeeded(imageView: ImageView, publicKey: String, displayName: String?, @DimenRes sizeResId: Int) { + glide.clear(imageView) + if (publicKey.isNotEmpty()) { + val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false); + val signalProfilePicture = recipient.contactPhoto + if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0" + && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "") { + glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView) } else { - imageView.setImageDrawable(null) + val sizeInPX = resources.getDimensionPixelSize(sizeResId) + val masterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context) + val hepk = if (recipient.isLocalNumber && masterPublicKey != null) masterPublicKey else publicKey + glide.load(AvatarPlaceholderGenerator.generate( + context, + sizeInPX, + hepk, + displayName + )).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView) } + } else { + imageView.setImageDrawable(null) } - setProfilePictureIfNeeded(doubleModeImageView1, publicKey, R.dimen.small_profile_picture_size) - setProfilePictureIfNeeded(doubleModeImageView2, additionalPublicKey ?: "", R.dimen.small_profile_picture_size) - setProfilePictureIfNeeded(singleModeImageView, publicKey, R.dimen.medium_profile_picture_size) - setProfilePictureIfNeeded(largeSingleModeImageView, publicKey, R.dimen.large_profile_picture_size) } // endregion } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/views/UserView.kt b/src/org/thoughtcrime/securesms/loki/views/UserView.kt index 9619a90389..96c1de080a 100644 --- a/src/org/thoughtcrime/securesms/loki/views/UserView.kt +++ b/src/org/thoughtcrime/securesms/loki/views/UserView.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.loki.views import android.content.Context +import android.text.TextUtils import android.util.AttributeSet import android.view.LayoutInflater import android.view.View @@ -8,6 +9,7 @@ import android.widget.LinearLayout import kotlinx.android.synthetic.main.view_conversation.view.profilePictureView import kotlinx.android.synthetic.main.view_user.view.* import network.loki.messenger.R +import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.groups.GroupManager import org.thoughtcrime.securesms.mms.GlideRequests import org.thoughtcrime.securesms.recipients.Recipient @@ -47,22 +49,35 @@ class UserView : LinearLayout { // region Updating fun bind(user: Recipient, glide: GlideRequests, actionIndicator: ActionIndicator, isSelected: Boolean = false) { + fun getUserDisplayName(publicKey: String?): String? { + if (publicKey == null || publicKey.isBlank()) { + return null + } else { + return DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey!!) + } + } val address = user.address.serialize() if (user.isGroupRecipient) { if ("Session Public Chat" == user.name || user.address.isRSSFeed) { profilePictureView.publicKey = "" + profilePictureView.displayName = null profilePictureView.additionalPublicKey = null profilePictureView.isRSSFeed = true } else { val threadID = GroupManager.getThreadIDFromGroupID(address, context) val users = MentionsManager.shared.userPublicKeyCache[threadID]?.toList() ?: listOf() val randomUsers = users.sorted() // Sort to provide a level of stability - profilePictureView.publicKey = randomUsers.getOrNull(0) ?: "" - profilePictureView.additionalPublicKey = randomUsers.getOrNull(1) ?: "" + val pk = randomUsers.getOrNull(0) ?: "" + profilePictureView.publicKey = pk + profilePictureView.displayName = getUserDisplayName(pk) + val apk = randomUsers.getOrNull(1) ?: "" + profilePictureView.additionalPublicKey = apk + profilePictureView.additionalDisplayName = getUserDisplayName(apk) profilePictureView.isRSSFeed = false } } else { profilePictureView.publicKey = address + profilePictureView.displayName = getUserDisplayName(address) profilePictureView.additionalPublicKey = null profilePictureView.isRSSFeed = false } diff --git a/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java b/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java index bc5f695a35..9abb67d1ba 100644 --- a/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java +++ b/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java @@ -14,21 +14,22 @@ import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; +import android.text.SpannableStringBuilder; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat.Action; import androidx.core.app.RemoteInput; -import android.text.SpannableStringBuilder; import com.bumptech.glide.load.engine.DiskCacheStrategy; import org.thoughtcrime.securesms.contacts.avatars.ContactColors; import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto; -import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.loki.todo.AvatarPlaceholderGenerator; import org.thoughtcrime.securesms.loki.utilities.NotificationUtilities; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.GlideApp; @@ -80,9 +81,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil addPerson(recipient.getContactUri().toString()); } - ContactPhoto contactPhoto = recipient.getContactPhoto(); - FallbackContactPhoto fallbackContactPhoto = recipient.getFallbackContactPhoto(); - + ContactPhoto contactPhoto = recipient.getContactPhoto(); if (contactPhoto != null) { try { setLargeIcon(GlideApp.with(context.getApplicationContext()) @@ -94,10 +93,10 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil .get()); } catch (InterruptedException | ExecutionException e) { Log.w(TAG, e); - setLargeIcon(fallbackContactPhoto.asDrawable(context, recipient.getColor().toConversationColor(context))); + setLargeIcon(getPlaceholderDrawable(context, recipient)); } } else { - setLargeIcon(fallbackContactPhoto.asDrawable(context, recipient.getColor().toConversationColor(context))); + setLargeIcon(getPlaceholderDrawable(context, recipient)); } } else { @@ -321,4 +320,12 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil return content; } + private static Drawable getPlaceholderDrawable(Context context, Recipient recipient) { + String publicKey = recipient.getAddress().serialize(); + String hepk = (recipient.isLocalNumber() && publicKey != null) + ? TextSecurePreferences.getMasterHexEncodedPublicKey(context) + : publicKey; + String displayName = recipient.getName(); + return AvatarPlaceholderGenerator.INSTANCE.generate(context, 128, hepk, displayName); + } }