From 210a88ce02c06899dc2dfa955030042373683c6d Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Mon, 22 Jul 2019 12:13:53 +1000 Subject: [PATCH] Use identicons as profile pictures --- build.gradle | 5 ++- .../securesms/ConversationListActivity.java | 39 +++++++++++++------ .../securesms/components/AvatarImageView.java | 27 +++++++++++-- .../widgets/ProfilePreference.java | 32 ++++++++++++--- 4 files changed, 82 insertions(+), 21 deletions(-) diff --git a/build.gradle b/build.gradle index 0b72429f61..159068118f 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext.gradle_version = "3.4.1" ext.kotlin_version = "1.3.31" ext.kovenant_version = "3.3.0" - ext.work_manager_version = "2.1.0" + ext.identicon_version = "v11" repositories { google() @@ -180,6 +180,7 @@ dependencies { implementation "com.squareup.okhttp3:okhttp:3.12.1" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "nl.komponents.kovenant:kovenant:$kovenant_version" + implementation "com.github.lelloman:android-identicons:$identicon_version" } android { @@ -196,7 +197,7 @@ android { versionCode 487 versionName "4.40.4" - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 26 multiDexEnabled true diff --git a/src/org/thoughtcrime/securesms/ConversationListActivity.java b/src/org/thoughtcrime/securesms/ConversationListActivity.java index d042571b1e..afc34ed652 100644 --- a/src/org/thoughtcrime/securesms/ConversationListActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationListActivity.java @@ -21,34 +21,31 @@ import android.annotation.SuppressLint; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; -import android.graphics.drawable.Drawable; +import android.graphics.Outline; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.widget.Toolbar; import android.support.v7.widget.TooltipCompat; -import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; +import android.view.View; import android.view.ViewGroup; +import android.view.ViewOutlineProvider; +import android.view.ViewTreeObserver; import android.widget.ImageView; import android.widget.Toast; -import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.lelloman.identicon.drawable.ClassicIdenticonDrawable; -import org.thoughtcrime.securesms.color.MaterialColor; import org.thoughtcrime.securesms.components.RatingManager; import org.thoughtcrime.securesms.components.SearchToolbar; -import org.thoughtcrime.securesms.contacts.avatars.ContactColors; -import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto; -import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto; import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo; import org.thoughtcrime.securesms.lock.RegistrationLockDialog; -import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.notifications.MarkReadReceiver; import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.permissions.Permissions; @@ -60,7 +57,6 @@ import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.concurrent.SimpleTask; -import org.whispersystems.libsignal.util.guava.Optional; import java.util.List; @@ -182,7 +178,27 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit } private void initializeProfileIcon(@NonNull Recipient recipient) { - ImageView icon = findViewById(R.id.toolbar_icon); + ImageView profilePictureImageView = findViewById(R.id.toolbar_icon); + profilePictureImageView.setOutlineProvider(new ViewOutlineProvider() { + + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, view.getWidth(), view.getHeight()); + } + }); + profilePictureImageView.setClipToOutline(true); + profilePictureImageView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + + @Override + public boolean onPreDraw() { + profilePictureImageView.getViewTreeObserver().removeOnPreDrawListener(this); + ClassicIdenticonDrawable identicon = new ClassicIdenticonDrawable(profilePictureImageView.getWidth(), profilePictureImageView.getHeight(), recipient.getAddress().serialize().hashCode()); + profilePictureImageView.setImageDrawable(identicon); + return true; + } + }); + + /* String name = Optional.fromNullable(recipient.getName()).or(Optional.fromNullable(TextSecurePreferences.getProfileName(this))).or(""); MaterialColor fallbackColor = recipient.getColor(); @@ -198,8 +214,9 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit .circleCrop() .diskCacheStrategy(DiskCacheStrategy.ALL) .into(icon); + */ - icon.setOnClickListener(v -> handleDisplaySettings()); + profilePictureImageView.setOnClickListener(v -> handleDisplaySettings()); } @Override diff --git a/src/org/thoughtcrime/securesms/components/AvatarImageView.java b/src/org/thoughtcrime/securesms/components/AvatarImageView.java index d781095a35..6ac2c623cd 100644 --- a/src/org/thoughtcrime/securesms/components/AvatarImageView.java +++ b/src/org/thoughtcrime/securesms/components/AvatarImageView.java @@ -4,18 +4,19 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Outline; import android.graphics.Paint; import android.provider.ContactsContract; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.AppCompatImageView; import android.util.AttributeSet; +import android.view.View; +import android.view.ViewOutlineProvider; -import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.lelloman.identicon.drawable.ClassicIdenticonDrawable; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.contacts.avatars.ContactColors; -import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto; import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientExporter; @@ -43,6 +44,7 @@ public class AvatarImageView extends AppCompatImageView { private boolean inverted; private Paint outlinePaint; private OnClickListener listener; + private Recipient recipient; public AvatarImageView(Context context) { super(context); @@ -64,6 +66,14 @@ public class AvatarImageView extends AppCompatImageView { } outlinePaint = ThemeUtil.isDarkTheme(getContext()) ? DARK_THEME_OUTLINE_PAINT : LIGHT_THEME_OUTLINE_PAINT; + setOutlineProvider(new ViewOutlineProvider() { + + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, view.getWidth(), view.getHeight()); + } + }); + setClipToOutline(true); } @Override @@ -83,7 +93,17 @@ public class AvatarImageView extends AppCompatImageView { super.setOnClickListener(listener); } + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + if (w == 0 || h == 0 || recipient == null) { return; } + ClassicIdenticonDrawable identicon = new ClassicIdenticonDrawable(w, h, recipient.getAddress().serialize().hashCode()); + setImageDrawable(identicon); + } + public void setAvatar(@NonNull GlideRequests requestManager, @Nullable Recipient recipient, boolean quickContactEnabled) { + this.recipient = recipient; + /* if (recipient != null) { requestManager.load(recipient.getContactPhoto()) .fallback(recipient.getFallbackContactPhotoDrawable(getContext(), inverted)) @@ -96,6 +116,7 @@ public class AvatarImageView extends AppCompatImageView { setImageDrawable(new ResourceContactPhoto(R.drawable.ic_profile_default).asDrawable(getContext(), ContactColors.UNKNOWN_COLOR.toConversationColor(getContext()), inverted)); super.setOnClickListener(listener); } + */ } public void clear(@NonNull GlideRequests glideRequests) { diff --git a/src/org/thoughtcrime/securesms/preferences/widgets/ProfilePreference.java b/src/org/thoughtcrime/securesms/preferences/widgets/ProfilePreference.java index 5c56ef6d49..d93d27571e 100644 --- a/src/org/thoughtcrime/securesms/preferences/widgets/ProfilePreference.java +++ b/src/org/thoughtcrime/securesms/preferences/widgets/ProfilePreference.java @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.preferences.widgets; import android.content.Context; +import android.graphics.Outline; import android.os.Build; import android.support.annotation.RequiresApi; import android.support.v7.preference.Preference; @@ -9,16 +10,15 @@ import android.support.v7.preference.PreferenceViewHolder; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; +import android.view.ViewOutlineProvider; +import android.view.ViewTreeObserver; import android.widget.ImageView; import android.widget.TextView; -import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.lelloman.identicon.drawable.ClassicIdenticonDrawable; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto; -import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto; import org.thoughtcrime.securesms.database.Address; -import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.util.TextSecurePreferences; public class ProfilePreference extends Preference { @@ -65,15 +65,37 @@ public class ProfilePreference extends Preference { public void refresh() { if (profileNumberView == null) return; - final Address localAddress = Address.fromSerialized(TextSecurePreferences.getLocalNumber(getContext())); + String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(getContext()); + final Address localAddress = Address.fromSerialized(userHexEncodedPublicKey); final String profileName = TextSecurePreferences.getProfileName(getContext()); + avatarView.setOutlineProvider(new ViewOutlineProvider() { + + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, view.getWidth(), view.getHeight()); + } + }); + avatarView.setClipToOutline(true); + avatarView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + + @Override + public boolean onPreDraw() { + avatarView.getViewTreeObserver().removeOnPreDrawListener(this); + ClassicIdenticonDrawable identicon = new ClassicIdenticonDrawable(avatarView.getWidth(), avatarView.getHeight(), userHexEncodedPublicKey.hashCode()); + avatarView.setImageDrawable(identicon); + return true; + } + }); + + /* GlideApp.with(getContext().getApplicationContext()) .load(new ProfileContactPhoto(localAddress, String.valueOf(TextSecurePreferences.getProfileAvatarId(getContext())))) .error(new ResourceContactPhoto(R.drawable.ic_camera_alt_white_24dp).asDrawable(getContext(), getContext().getResources().getColor(R.color.grey_400))) .circleCrop() .diskCacheStrategy(DiskCacheStrategy.ALL) .into(avatarView); + */ if (!TextUtils.isEmpty(profileName)) { profileNameView.setText(profileName);