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);
+ }
}