mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-12 10:53:38 +00:00
Merge pull request #332 from loki-project/profile-pictures
New Profile Picture Placeholder
This commit is contained in:
commit
2ba98bb8c9
@ -3,7 +3,7 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
|
|
||||||
<solid android:color="@color/unimportant" />
|
<solid android:color="@color/profile_picture_background" />
|
||||||
|
|
||||||
<corners android:radius="38dp" />
|
<corners android:radius="38dp" />
|
||||||
|
|
||||||
|
@ -7,5 +7,5 @@
|
|||||||
|
|
||||||
<corners android:radius="38dp" />
|
<corners android:radius="38dp" />
|
||||||
|
|
||||||
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/border" />
|
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/profile_picture_border" />
|
||||||
</shape>
|
</shape>
|
@ -3,9 +3,9 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
|
|
||||||
<solid android:color="@color/unimportant" />
|
<solid android:color="@color/profile_picture_background" />
|
||||||
|
|
||||||
<corners android:radius="23dp" />
|
<corners android:radius="23dp" />
|
||||||
|
|
||||||
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/border" />
|
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/profile_picture_border" />
|
||||||
</shape>
|
</shape>
|
@ -7,5 +7,5 @@
|
|||||||
|
|
||||||
<corners android:radius="23dp" />
|
<corners android:radius="23dp" />
|
||||||
|
|
||||||
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/border" />
|
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/profile_picture_border" />
|
||||||
</shape>
|
</shape>
|
@ -3,9 +3,9 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
|
|
||||||
<solid android:color="#353535" />
|
<solid android:color="@color/profile_picture_background" />
|
||||||
|
|
||||||
<corners android:radius="23dp" />
|
<corners android:radius="23dp" />
|
||||||
|
|
||||||
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/border" />
|
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/profile_picture_border" />
|
||||||
</shape>
|
</shape>
|
@ -3,9 +3,9 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
|
|
||||||
<solid android:color="@color/unimportant" />
|
<solid android:color="@color/profile_picture_background" />
|
||||||
|
|
||||||
<corners android:radius="18dp" />
|
<corners android:radius="18dp" />
|
||||||
|
|
||||||
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/border" />
|
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/profile_picture_border" />
|
||||||
</shape>
|
</shape>
|
@ -7,5 +7,5 @@
|
|||||||
|
|
||||||
<corners android:radius="18dp" />
|
<corners android:radius="18dp" />
|
||||||
|
|
||||||
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/border" />
|
<stroke android:width="@dimen/profile_picture_border_thickness" android:color="@color/profile_picture_border" />
|
||||||
</shape>
|
</shape>
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/doubleModeImageViewContainer"
|
android:id="@+id/doubleModeImageViewContainer"
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
<color name="text">#000000</color>
|
<color name="text">#000000</color>
|
||||||
<color name="destructive">#f26f55</color>
|
<color name="destructive">#f26f55</color>
|
||||||
<color name="unimportant">#606060</color>
|
<color name="unimportant">#606060</color>
|
||||||
|
<color name="profile_picture_border">#23000000</color>
|
||||||
|
<color name="profile_picture_background">#B0B0B0</color>
|
||||||
<color name="cell_background">#FCFCFC</color>
|
<color name="cell_background">#FCFCFC</color>
|
||||||
<color name="cell_selected">#DFDFDF</color>
|
<color name="cell_selected">#DFDFDF</color>
|
||||||
<color name="navigation_bar_background">#FCFCFC</color>
|
<color name="navigation_bar_background">#FCFCFC</color>
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
<color name="text">#FFFFFF</color>
|
<color name="text">#FFFFFF</color>
|
||||||
<color name="destructive">#FF453A</color>
|
<color name="destructive">#FF453A</color>
|
||||||
<color name="unimportant">#D8D8D8</color>
|
<color name="unimportant">#D8D8D8</color>
|
||||||
|
<color name="profile_picture_border">#23FFFFFF</color>
|
||||||
|
<color name="profile_picture_background">#353535</color>
|
||||||
<color name="border">#979797</color>
|
<color name="border">#979797</color>
|
||||||
<color name="cell_background">#1B1B1B</color>
|
<color name="cell_background">#1B1B1B</color>
|
||||||
<color name="cell_selected">#0C0C0C</color>
|
<color name="cell_selected">#0C0C0C</color>
|
||||||
@ -29,6 +31,13 @@
|
|||||||
<color name="pn_option_background">#1B1B1B</color>
|
<color name="pn_option_background">#1B1B1B</color>
|
||||||
<color name="pn_option_border">#212121</color>
|
<color name="pn_option_border">#212121</color>
|
||||||
<color name="paths_building">#FFCE3A</color>
|
<color name="paths_building">#FFCE3A</color>
|
||||||
|
|
||||||
|
<array name="profile_picture_placeholder_colors">
|
||||||
|
<item>#5ff8b0</item>
|
||||||
|
<item>#26cdb9</item>
|
||||||
|
<item>#f3c615</item>
|
||||||
|
<item>#fcac5a</item>
|
||||||
|
</array>
|
||||||
<!-- Session -->
|
<!-- Session -->
|
||||||
|
|
||||||
<!-- Loki -->
|
<!-- Loki -->
|
||||||
|
@ -804,6 +804,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
bodyBubble.setLayoutParams(layoutParams);
|
bodyBubble.setLayoutParams(layoutParams);
|
||||||
if (profilePictureView == null) return;
|
if (profilePictureView == null) return;
|
||||||
profilePictureView.setPublicKey(recipient.getAddress().toString());
|
profilePictureView.setPublicKey(recipient.getAddress().toString());
|
||||||
|
profilePictureView.setDisplayName(recipient.getName());
|
||||||
profilePictureView.setAdditionalPublicKey(null);
|
profilePictureView.setAdditionalPublicKey(null);
|
||||||
profilePictureView.setRSSFeed(false);
|
profilePictureView.setRSSFeed(false);
|
||||||
profilePictureView.setGlide(glideRequests);
|
profilePictureView.setGlide(glideRequests);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.loki.activities
|
package org.thoughtcrime.securesms.loki.activities
|
||||||
|
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -11,10 +10,6 @@ import android.net.Uri
|
|||||||
import android.os.AsyncTask
|
import android.os.AsyncTask
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
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.Spannable
|
||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.text.style.ForegroundColorSpan
|
import android.text.style.ForegroundColorSpan
|
||||||
@ -22,6 +17,11 @@ import android.util.DisplayMetrics
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.Toast
|
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 kotlinx.android.synthetic.main.activity_home.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
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.loki.views.SeedReminderViewDelegate
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.util.GroupUtil
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.thoughtcrime.securesms.util.Util
|
import org.thoughtcrime.securesms.util.Util
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
||||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
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.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.protocol.shelved.syncmessages.SyncMessagesProtocol
|
||||||
import org.whispersystems.signalservice.loki.utilities.toHexString
|
import org.whispersystems.signalservice.loki.utilities.toHexString
|
||||||
|
|
||||||
@ -99,6 +98,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
|||||||
// Set up toolbar buttons
|
// Set up toolbar buttons
|
||||||
profileButton.glide = glide
|
profileButton.glide = glide
|
||||||
profileButton.publicKey = publicKey
|
profileButton.publicKey = publicKey
|
||||||
|
profileButton.displayName = TextSecurePreferences.getProfileName(this)
|
||||||
profileButton.update()
|
profileButton.update()
|
||||||
profileButton.setOnClickListener { openSettings() }
|
profileButton.setOnClickListener { openSettings() }
|
||||||
pathStatusViewContainer.disableClipping()
|
pathStatusViewContainer.disableClipping()
|
||||||
|
@ -52,10 +52,8 @@ import java.security.SecureRandom
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||||
|
|
||||||
private var displayNameEditActionMode: ActionMode? = null
|
private var displayNameEditActionMode: ActionMode? = null
|
||||||
set(value) { field = value; handleDisplayNameEditActionModeChanged() }
|
set(value) { field = value; handleDisplayNameEditActionModeChanged() }
|
||||||
|
|
||||||
private lateinit var glide: GlideRequests
|
private lateinit var glide: GlideRequests
|
||||||
private var displayNameToBeUploaded: String? = null
|
private var displayNameToBeUploaded: String? = null
|
||||||
private var profilePictureToBeUploaded: ByteArray? = null
|
private var profilePictureToBeUploaded: ByteArray? = null
|
||||||
@ -71,17 +69,17 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
// region Lifecycle
|
// region Lifecycle
|
||||||
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
||||||
super.onCreate(savedInstanceState, isReady)
|
super.onCreate(savedInstanceState, isReady)
|
||||||
|
|
||||||
setContentView(R.layout.activity_settings)
|
setContentView(R.layout.activity_settings)
|
||||||
|
val displayName = DatabaseFactory.getLokiUserDatabase(this).getDisplayName(hexEncodedPublicKey)
|
||||||
glide = GlideApp.with(this)
|
glide = GlideApp.with(this)
|
||||||
profilePictureView.glide = glide
|
profilePictureView.glide = glide
|
||||||
profilePictureView.publicKey = hexEncodedPublicKey
|
profilePictureView.publicKey = hexEncodedPublicKey
|
||||||
|
profilePictureView.displayName = displayName
|
||||||
profilePictureView.isLarge = true
|
profilePictureView.isLarge = true
|
||||||
profilePictureView.update()
|
profilePictureView.update()
|
||||||
profilePictureView.setOnClickListener { showEditProfilePictureUI() }
|
profilePictureView.setOnClickListener { showEditProfilePictureUI() }
|
||||||
ctnGroupNameSection.setOnClickListener { startActionMode(DisplayNameEditActionModeCallback()) }
|
ctnGroupNameSection.setOnClickListener { startActionMode(DisplayNameEditActionModeCallback()) }
|
||||||
btnGroupNameDisplay.text = DatabaseFactory.getLokiUserDatabase(this).getDisplayName(hexEncodedPublicKey)
|
btnGroupNameDisplay.text = displayName
|
||||||
publicKeyTextView.text = hexEncodedPublicKey
|
publicKeyTextView.text = hexEncodedPublicKey
|
||||||
copyButton.setOnClickListener { copyPublicKey() }
|
copyButton.setOnClickListener { copyPublicKey() }
|
||||||
shareButton.setOnClickListener { sharePublicKey() }
|
shareButton.setOnClickListener { sharePublicKey() }
|
||||||
@ -103,12 +101,9 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.settings_general, menu)
|
menuInflater.inflate(R.menu.settings_general, menu)
|
||||||
|
// Update UI mode menu icon
|
||||||
// Update UI mode menu icon.
|
|
||||||
// It uses three-level selector where each level corresponds to the related UiMode ordinal value.
|
|
||||||
val uiMode = UiModeUtilities.getUserSelectedUiMode(this)
|
val uiMode = UiModeUtilities.getUserSelectedUiMode(this)
|
||||||
menu.findItem(R.id.action_change_theme).icon!!.level = uiMode.ordinal
|
menu.findItem(R.id.action_change_theme).icon!!.level = uiMode.ordinal
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
@ -2,12 +2,14 @@ package org.thoughtcrime.securesms.loki.views
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
|
import android.text.TextUtils
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import kotlinx.android.synthetic.main.view_conversation.view.*
|
import kotlinx.android.synthetic.main.view_conversation.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded
|
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded
|
||||||
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities.highlightMentions
|
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities.highlightMentions
|
||||||
@ -81,5 +83,10 @@ class ConversationView : LinearLayout {
|
|||||||
else -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_check)
|
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
|
// endregion
|
||||||
}
|
}
|
@ -32,6 +32,7 @@ class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr:
|
|||||||
private fun update() {
|
private fun update() {
|
||||||
btnGroupNameDisplay.text = mentionCandidate.displayName
|
btnGroupNameDisplay.text = mentionCandidate.displayName
|
||||||
profilePictureView.publicKey = mentionCandidate.publicKey
|
profilePictureView.publicKey = mentionCandidate.publicKey
|
||||||
|
profilePictureView.displayName = mentionCandidate.displayName
|
||||||
profilePictureView.additionalPublicKey = null
|
profilePictureView.additionalPublicKey = null
|
||||||
profilePictureView.isRSSFeed = false
|
profilePictureView.isRSSFeed = false
|
||||||
profilePictureView.glide = glide!!
|
profilePictureView.glide = glide!!
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
package org.thoughtcrime.securesms.loki.views
|
package org.thoughtcrime.securesms.loki.views
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.annotation.DimenRes
|
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
|
import androidx.annotation.DimenRes
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
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 kotlinx.android.synthetic.main.view_profile_picture.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto
|
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto
|
||||||
import org.thoughtcrime.securesms.database.Address
|
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.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
@ -24,7 +24,9 @@ import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
|||||||
class ProfilePictureView : RelativeLayout {
|
class ProfilePictureView : RelativeLayout {
|
||||||
lateinit var glide: GlideRequests
|
lateinit var glide: GlideRequests
|
||||||
var publicKey: String? = null
|
var publicKey: String? = null
|
||||||
|
var displayName: String? = null
|
||||||
var additionalPublicKey: String? = null
|
var additionalPublicKey: String? = null
|
||||||
|
var additionalDisplayName: String? = null
|
||||||
var isRSSFeed = false
|
var isRSSFeed = false
|
||||||
var isLarge = false
|
var isLarge = false
|
||||||
|
|
||||||
@ -54,9 +56,17 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
|
|
||||||
// region Updating
|
// region Updating
|
||||||
fun update(recipient: Recipient, threadID: Long) {
|
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 (recipient.isGroupRecipient) {
|
||||||
if ("Session Public Chat" == recipient.name) {
|
if ("Session Public Chat" == recipient.name) {
|
||||||
publicKey = ""
|
publicKey = ""
|
||||||
|
displayName = ""
|
||||||
additionalPublicKey = null
|
additionalPublicKey = null
|
||||||
isRSSFeed = true
|
isRSSFeed = true
|
||||||
} else {
|
} else {
|
||||||
@ -67,12 +77,17 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
users.remove(masterPublicKey)
|
users.remove(masterPublicKey)
|
||||||
}
|
}
|
||||||
val randomUsers = users.sorted() // Sort to provide a level of stability
|
val randomUsers = users.sorted() // Sort to provide a level of stability
|
||||||
publicKey = randomUsers.getOrNull(0) ?: ""
|
val pk = randomUsers.getOrNull(0) ?: ""
|
||||||
additionalPublicKey = randomUsers.getOrNull(1) ?: ""
|
publicKey = pk
|
||||||
|
displayName = getUserDisplayName(pk)
|
||||||
|
val apk = randomUsers.getOrNull(1) ?: ""
|
||||||
|
additionalPublicKey = apk
|
||||||
|
additionalDisplayName = getUserDisplayName(apk)
|
||||||
isRSSFeed = recipient.name == "Loki News" || recipient.name == "Session Updates"
|
isRSSFeed = recipient.name == "Loki News" || recipient.name == "Session Updates"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
publicKey = recipient.address.toString()
|
publicKey = recipient.address.toString()
|
||||||
|
displayName = recipient.name
|
||||||
additionalPublicKey = null
|
additionalPublicKey = null
|
||||||
isRSSFeed = false
|
isRSSFeed = false
|
||||||
}
|
}
|
||||||
@ -86,28 +101,50 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
singleModeImageViewContainer.visibility = if (additionalPublicKey == null && !isRSSFeed && !isLarge) View.VISIBLE else View.INVISIBLE
|
singleModeImageViewContainer.visibility = if (additionalPublicKey == null && !isRSSFeed && !isLarge) View.VISIBLE else View.INVISIBLE
|
||||||
largeSingleModeImageViewContainer.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
|
rssImageView.visibility = if (isRSSFeed) View.VISIBLE else View.INVISIBLE
|
||||||
fun setProfilePictureIfNeeded(imageView: ImageView, hexEncodedPublicKey: String, @DimenRes sizeID: Int) {
|
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)
|
glide.clear(imageView)
|
||||||
if (hexEncodedPublicKey.isNotEmpty()) {
|
if (publicKey.isNotEmpty()) {
|
||||||
val recipient = Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false);
|
val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false);
|
||||||
val signalProfilePicture = recipient.contactPhoto
|
val signalProfilePicture = recipient.contactPhoto
|
||||||
if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0" && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "") {
|
if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0"
|
||||||
|
&& (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "") {
|
||||||
glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView)
|
glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView)
|
||||||
} else {
|
} else {
|
||||||
val size = resources.getDimensionPixelSize(sizeID)
|
val sizeInPX = resources.getDimensionPixelSize(sizeResId)
|
||||||
val masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
|
val masterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
|
||||||
val hepk = if (recipient.isLocalNumber && masterHexEncodedPublicKey != null) masterHexEncodedPublicKey else hexEncodedPublicKey
|
val hepk = if (recipient.isLocalNumber && masterPublicKey != null) masterPublicKey else publicKey
|
||||||
val jazzIcon = JazzIdenticonDrawable(size, size, hepk)
|
glide.load(AvatarPlaceholderGenerator.generate(
|
||||||
glide.load(jazzIcon).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView)
|
context,
|
||||||
|
sizeInPX,
|
||||||
|
hepk,
|
||||||
|
displayName
|
||||||
|
)).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
imageView.setImageDrawable(null)
|
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
|
// endregion
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.loki.views
|
package org.thoughtcrime.securesms.loki.views
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.text.TextUtils
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
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_conversation.view.profilePictureView
|
||||||
import kotlinx.android.synthetic.main.view_user.view.*
|
import kotlinx.android.synthetic.main.view_user.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.groups.GroupManager
|
import org.thoughtcrime.securesms.groups.GroupManager
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
@ -47,22 +49,35 @@ class UserView : LinearLayout {
|
|||||||
|
|
||||||
// region Updating
|
// region Updating
|
||||||
fun bind(user: Recipient, glide: GlideRequests, actionIndicator: ActionIndicator, isSelected: Boolean = false) {
|
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()
|
val address = user.address.serialize()
|
||||||
if (user.isGroupRecipient) {
|
if (user.isGroupRecipient) {
|
||||||
if ("Session Public Chat" == user.name || user.address.isRSSFeed) {
|
if ("Session Public Chat" == user.name || user.address.isRSSFeed) {
|
||||||
profilePictureView.publicKey = ""
|
profilePictureView.publicKey = ""
|
||||||
|
profilePictureView.displayName = null
|
||||||
profilePictureView.additionalPublicKey = null
|
profilePictureView.additionalPublicKey = null
|
||||||
profilePictureView.isRSSFeed = true
|
profilePictureView.isRSSFeed = true
|
||||||
} else {
|
} else {
|
||||||
val threadID = GroupManager.getThreadIDFromGroupID(address, context)
|
val threadID = GroupManager.getThreadIDFromGroupID(address, context)
|
||||||
val users = MentionsManager.shared.userPublicKeyCache[threadID]?.toList() ?: listOf()
|
val users = MentionsManager.shared.userPublicKeyCache[threadID]?.toList() ?: listOf()
|
||||||
val randomUsers = users.sorted() // Sort to provide a level of stability
|
val randomUsers = users.sorted() // Sort to provide a level of stability
|
||||||
profilePictureView.publicKey = randomUsers.getOrNull(0) ?: ""
|
val pk = randomUsers.getOrNull(0) ?: ""
|
||||||
profilePictureView.additionalPublicKey = randomUsers.getOrNull(1) ?: ""
|
profilePictureView.publicKey = pk
|
||||||
|
profilePictureView.displayName = getUserDisplayName(pk)
|
||||||
|
val apk = randomUsers.getOrNull(1) ?: ""
|
||||||
|
profilePictureView.additionalPublicKey = apk
|
||||||
|
profilePictureView.additionalDisplayName = getUserDisplayName(apk)
|
||||||
profilePictureView.isRSSFeed = false
|
profilePictureView.isRSSFeed = false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
profilePictureView.publicKey = address
|
profilePictureView.publicKey = address
|
||||||
|
profilePictureView.displayName = getUserDisplayName(address)
|
||||||
profilePictureView.additionalPublicKey = null
|
profilePictureView.additionalPublicKey = null
|
||||||
profilePictureView.isRSSFeed = false
|
profilePictureView.isRSSFeed = false
|
||||||
}
|
}
|
||||||
|
@ -14,21 +14,22 @@ import android.graphics.RectF;
|
|||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.NotificationCompat.Action;
|
import androidx.core.app.NotificationCompat.Action;
|
||||||
import androidx.core.app.RemoteInput;
|
import androidx.core.app.RemoteInput;
|
||||||
import android.text.SpannableStringBuilder;
|
|
||||||
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
|
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.contacts.avatars.GeneratedContactPhoto;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
|
import org.thoughtcrime.securesms.loki.todo.AvatarPlaceholderGenerator;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.NotificationUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.NotificationUtilities;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
@ -81,8 +82,6 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
}
|
}
|
||||||
|
|
||||||
ContactPhoto contactPhoto = recipient.getContactPhoto();
|
ContactPhoto contactPhoto = recipient.getContactPhoto();
|
||||||
FallbackContactPhoto fallbackContactPhoto = recipient.getFallbackContactPhoto();
|
|
||||||
|
|
||||||
if (contactPhoto != null) {
|
if (contactPhoto != null) {
|
||||||
try {
|
try {
|
||||||
setLargeIcon(GlideApp.with(context.getApplicationContext())
|
setLargeIcon(GlideApp.with(context.getApplicationContext())
|
||||||
@ -94,10 +93,10 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
.get());
|
.get());
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
setLargeIcon(fallbackContactPhoto.asDrawable(context, recipient.getColor().toConversationColor(context)));
|
setLargeIcon(getPlaceholderDrawable(context, recipient));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setLargeIcon(fallbackContactPhoto.asDrawable(context, recipient.getColor().toConversationColor(context)));
|
setLargeIcon(getPlaceholderDrawable(context, recipient));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -321,4 +320,12 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
return content;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user