mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
Generate placeholder avatars from two characters, re-fetch missed avatars (#856)
* feat: splitting names in the avatar generation * fix: re-fetch avatars if initial downloads fail * fix: remove shadowed name, add tests for common labels
This commit is contained in:
parent
11d49426d3
commit
6649a9a745
@ -254,7 +254,7 @@ public class JobManager implements ConstraintObserver.Notifier {
|
||||
public static class Builder {
|
||||
|
||||
private ExecutorFactory executorFactory = new DefaultExecutorFactory();
|
||||
private int jobThreadCount = Math.max(2, Math.min(Runtime.getRuntime().availableProcessors() - 1, 4));
|
||||
private int jobThreadCount = 1;
|
||||
private Map<String, Job.Factory> jobFactories = new HashMap<>();
|
||||
private Map<String, Constraint.Factory> constraintFactories = new HashMap<>();
|
||||
private List<ConstraintObserver> constraintObservers = new ArrayList<>();
|
||||
|
@ -84,7 +84,7 @@ public class RetrieveProfileAvatarJob extends BaseJob {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Util.equals(profileAvatar, recipient.resolve().getProfileAvatar())) {
|
||||
if (AvatarHelper.avatarFileExists(context, recipient.resolve().getAddress()) && Util.equals(profileAvatar, recipient.resolve().getProfileAvatar())) {
|
||||
Log.w(TAG, "Already retrieved profile avatar: " + profileAvatar);
|
||||
return;
|
||||
}
|
||||
|
@ -1,14 +1,20 @@
|
||||
package org.thoughtcrime.securesms.util
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Rect
|
||||
import android.graphics.RectF
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.text.TextPaint
|
||||
import android.text.TextUtils
|
||||
import network.loki.messenger.R
|
||||
import java.math.BigInteger
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
|
||||
object AvatarPlaceholderGenerator {
|
||||
|
||||
@ -28,7 +34,7 @@ object AvatarPlaceholderGenerator {
|
||||
val colorPrimary = colorArray[(hash % colorArray.size).toInt()]
|
||||
|
||||
val labelText = when {
|
||||
!TextUtils.isEmpty(displayName) -> extractLabel(displayName!!.capitalize())
|
||||
!TextUtils.isEmpty(displayName) -> extractLabel(displayName!!.capitalize(Locale.ROOT))
|
||||
!TextUtils.isEmpty(hashString) -> extractLabel(hashString)
|
||||
else -> EMPTY_LABEL
|
||||
}
|
||||
@ -57,14 +63,19 @@ object AvatarPlaceholderGenerator {
|
||||
return BitmapDrawable(context.resources, bitmap)
|
||||
}
|
||||
|
||||
private fun extractLabel(content: String): String {
|
||||
var content = content.trim()
|
||||
if (content.isEmpty()) return EMPTY_LABEL
|
||||
return if (content.length > 2 && content.startsWith("05")) {
|
||||
content[2].toString().toUpperCase(Locale.ROOT)
|
||||
fun extractLabel(content: String): String {
|
||||
val trimmedContent = content.trim()
|
||||
if (trimmedContent.isEmpty()) return EMPTY_LABEL
|
||||
return if (trimmedContent.length > 2 && trimmedContent.startsWith("05")) {
|
||||
trimmedContent[2].toString()
|
||||
} else {
|
||||
content.first().toString().toUpperCase(Locale.ROOT)
|
||||
}
|
||||
val splitWords = trimmedContent.split(Regex("\\W"))
|
||||
if (splitWords.size < 2) {
|
||||
trimmedContent.take(2)
|
||||
} else {
|
||||
splitWords.filter { word -> word.isNotEmpty() }.take(2).map { it.first() }.joinToString("")
|
||||
}
|
||||
}.uppercase()
|
||||
}
|
||||
|
||||
private fun getSha512(input: String): String {
|
||||
|
@ -0,0 +1,26 @@
|
||||
package org.thoughtcrime.securesms.recipients
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator
|
||||
|
||||
class AvatarGeneratorTest {
|
||||
|
||||
@Test
|
||||
fun testCommonAvatarFormats() {
|
||||
val testNamesAndResults = mapOf(
|
||||
"H " to "H",
|
||||
"Test Name" to "TN",
|
||||
"test name" to "TN",
|
||||
"howdy partner" to "HP",
|
||||
"testname" to "TE", //
|
||||
"05aaapubkey" to "A", // pubkey values only return first non-05 character
|
||||
"Test" to "TE"
|
||||
)
|
||||
testNamesAndResults.forEach { (test, expected) ->
|
||||
val processed = AvatarPlaceholderGenerator.extractLabel(test)
|
||||
assertEquals(expected, processed)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -46,6 +46,11 @@ public class AvatarHelper {
|
||||
return new File(avatarDirectory, new File(address.serialize()).getName());
|
||||
}
|
||||
|
||||
public static boolean avatarFileExists(@NonNull Context context , @NonNull Address address) {
|
||||
File avatarFile = getAvatarFile(context, address);
|
||||
return avatarFile.exists();
|
||||
}
|
||||
|
||||
public static void setAvatar(@NonNull Context context, @NonNull Address address, @Nullable byte[] data)
|
||||
throws IOException
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.session.libsession.messaging.sending_receiving
|
||||
|
||||
import android.text.TextUtils
|
||||
import org.session.libsession.avatars.AvatarHelper
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.jobs.AttachmentDownloadJob
|
||||
import org.session.libsession.messaging.jobs.JobQueue
|
||||
@ -188,28 +189,33 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage, proto: SignalS
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val context = MessagingModuleConfiguration.shared.context
|
||||
val userPublicKey = storage.getUserPublicKey()
|
||||
val messageSender: String? = message.sender
|
||||
// Get or create thread
|
||||
// FIXME: In case this is an open group this actually * doesn't * create the thread if it doesn't yet
|
||||
// exist. This is intentional, but it's very non-obvious.
|
||||
val threadID = storage.getOrCreateThreadIdFor(message.syncTarget
|
||||
?: message.sender!!, message.groupPublicKey, openGroupID)
|
||||
?: messageSender!!, message.groupPublicKey, openGroupID)
|
||||
if (threadID < 0) {
|
||||
// Thread doesn't exist; should only be reached in a case where we are processing open group messages for a no longer existent thread
|
||||
throw MessageReceiver.Error.NoThread
|
||||
}
|
||||
// Update profile if needed
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(message.sender!!), false)
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(messageSender!!), false)
|
||||
val profile = message.profile
|
||||
if (profile != null && userPublicKey != message.sender) {
|
||||
if (profile != null && userPublicKey != messageSender) {
|
||||
val profileManager = SSKEnvironment.shared.profileManager
|
||||
val name = profile.displayName!!
|
||||
if (name.isNotEmpty()) {
|
||||
profileManager.setName(context, recipient, name)
|
||||
}
|
||||
val newProfileKey = profile.profileKey
|
||||
if (newProfileKey?.isNotEmpty() == true && (newProfileKey.size == 16 || newProfileKey.size == 32) && profile.profilePictureURL?.isNotEmpty() == true
|
||||
&& (recipient.profileKey == null || !MessageDigest.isEqual(recipient.profileKey, newProfileKey))) {
|
||||
profileManager.setProfileKey(context, recipient, newProfileKey)
|
||||
|
||||
val needsProfilePicture = !AvatarHelper.avatarFileExists(context, Address.fromSerialized(messageSender))
|
||||
val profileKeyValid = newProfileKey?.isNotEmpty() == true && (newProfileKey.size == 16 || newProfileKey.size == 32) && profile.profilePictureURL?.isNotEmpty() == true
|
||||
val profileKeyChanged = (recipient.profileKey == null || !MessageDigest.isEqual(recipient.profileKey, newProfileKey))
|
||||
|
||||
if ((profileKeyValid && profileKeyChanged) || (profileKeyValid && needsProfilePicture)) {
|
||||
profileManager.setProfileKey(context, recipient, newProfileKey!!)
|
||||
profileManager.setUnidentifiedAccessMode(context, recipient, Recipient.UnidentifiedAccessMode.UNKNOWN)
|
||||
profileManager.setProfilePictureURL(context, recipient, profile.profilePictureURL!!)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user