From 993e49db487940524f97898ddf164da5e5905ed1 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Wed, 7 Sep 2022 14:48:51 -0300 Subject: [PATCH] Username search UI tweak. --- .../securesms/components/AvatarImageView.java | 7 +++- .../contacts/ContactSelectionListItem.java | 36 +++++++++++++++++-- .../contacts/ContactsCursorLoader.java | 2 +- .../contacts/ContactsCursorRows.java | 6 ++-- .../avatars/ResourceContactPhoto.java | 17 +++------ .../conversation/colors/AvatarColor.java | 3 +- .../conversation/colors/AvatarColorPair.kt | 32 +++++++++++++++++ app/src/main/res/values/strings.xml | 3 +- 8 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/conversation/colors/AvatarColorPair.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/AvatarImageView.java b/app/src/main/java/org/thoughtcrime/securesms/components/AvatarImageView.java index 86ff7b35e0..a77125e4cd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/AvatarImageView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/AvatarImageView.java @@ -64,6 +64,7 @@ public final class AvatarImageView extends AppCompatImageView { private @Nullable RecipientContactPhoto recipientContactPhoto; private @NonNull Drawable unknownRecipientDrawable; + private @Nullable AvatarColor fallbackPhotoColor; public AvatarImageView(Context context) { super(context); @@ -105,6 +106,10 @@ public final class AvatarImageView extends AppCompatImageView { this.fallbackPhotoProvider = fallbackPhotoProvider; } + public void setFallbackPhotoColor(@Nullable AvatarColor fallbackPhotoColor) { + this.fallbackPhotoColor = fallbackPhotoColor; + } + /** * Shows self as the actual profile picture. */ @@ -213,7 +218,7 @@ public final class AvatarImageView extends AppCompatImageView { requestManager.clear(this); if (fallbackPhotoProvider != null) { setImageDrawable(fallbackPhotoProvider.getPhotoForRecipientWithoutName() - .asDrawable(getContext(), AvatarColor.UNKNOWN, inverted)); + .asDrawable(getContext(), Util.firstNonNull(fallbackPhotoColor, AvatarColor.UNKNOWN), inverted)); } else { setImageDrawable(unknownRecipientDrawable); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java index aa37399612..8c92d18c3d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java @@ -2,6 +2,8 @@ package org.thoughtcrime.securesms.contacts; import android.annotation.SuppressLint; import android.content.Context; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.widget.CheckBox; @@ -10,18 +12,23 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.badges.BadgeImageView; import org.thoughtcrime.securesms.components.AvatarImageView; import org.thoughtcrime.securesms.components.FromTextView; +import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto; +import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto; +import org.thoughtcrime.securesms.conversation.colors.AvatarColor; import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter; import org.thoughtcrime.securesms.recipients.LiveRecipient; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientForeverObserver; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.util.SpanUtil; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; @@ -51,6 +58,8 @@ public class ContactSelectionListItem extends ConstraintLayout implements Recipi private LiveRecipient recipient; private GlideRequests glideRequests; + private final UsernameFallbackPhotoProvider usernameFallbackPhotoProvider = new UsernameFallbackPhotoProvider(); + public ContactSelectionListItem(Context context) { super(context); } @@ -104,8 +113,11 @@ public class ContactSelectionListItem extends ConstraintLayout implements Recipi this.contactLabel = label; this.contactAbout = about; + this.contactPhotoImage.setFallbackPhotoProvider(null); if (type == ContactRepository.NEW_PHONE_TYPE || type == ContactRepository.NEW_USERNAME_TYPE) { this.recipient = null; + this.contactPhotoImage.setFallbackPhotoProvider(usernameFallbackPhotoProvider); + this.contactPhotoImage.setFallbackPhotoColor(AvatarColor.ON_SURFACE_VARIANT); this.contactPhotoImage.setAvatar(glideRequests, null, false); } else if (recipientId != null) { if (this.recipient != null) { @@ -168,6 +180,8 @@ public class ContactSelectionListItem extends ConstraintLayout implements Recipi @SuppressLint("SetTextI18n") private void setText(@Nullable Recipient recipient, int type, String name, String number, String label, @Nullable String about) { + this.numberView.setVisibility(View.VISIBLE); + if (number == null || number.isEmpty()) { this.nameView.setEnabled(false); this.numberView.setText(""); @@ -181,10 +195,9 @@ public class ContactSelectionListItem extends ConstraintLayout implements Recipi this.nameView.setEnabled(true); this.labelView.setVisibility(View.GONE); } else if (type == ContactRepository.NEW_USERNAME_TYPE) { - this.numberView.setText("@" + number); + this.numberView.setVisibility(View.GONE); this.nameView.setEnabled(true); - this.labelView.setText(label); - this.labelView.setVisibility(View.VISIBLE); + this.labelView.setVisibility(View.GONE); } else if (recipient != null && recipient.isDistributionList()) { this.numberView.setText(getViewerCount(number)); this.labelView.setVisibility(View.GONE); @@ -198,6 +211,8 @@ public class ContactSelectionListItem extends ConstraintLayout implements Recipi if (recipient != null) { this.nameView.setText(recipient); chipName = recipient.getShortDisplayName(getContext()); + } else if (type == ContactRepository.NEW_USERNAME_TYPE && number != null) { + this.nameView.setText(presentUsername(number)); } else { this.nameView.setText(name); chipName = name; @@ -224,6 +239,14 @@ public class ContactSelectionListItem extends ConstraintLayout implements Recipi int viewerCount = Integer.parseInt(number); return getContext().getResources().getQuantityString(R.plurals.contact_selection_list_item__number_of_viewers, viewerCount, viewerCount); } + + private CharSequence presentUsername(@NonNull String username) { + if (username.contains("#")) { + return username; + } else { + return new SpannableStringBuilder(username).append(SpanUtil.color(ContextCompat.getColor(getContext(), R.color.signal_colorOutline), "#")); + } + } public @Nullable LiveRecipient getRecipient() { return recipient; @@ -264,4 +287,11 @@ public class ContactSelectionListItem extends ConstraintLayout implements Recipi Log.w(TAG, "Bad change! Local recipient doesn't match. Ignoring. Local: " + (this.recipient == null ? "null" : this.recipient.getId()) + ", Changed: " + recipient.getId()); } } + + private static class UsernameFallbackPhotoProvider extends Recipient.FallbackPhotoProvider { + @Override + public @NonNull FallbackContactPhoto getPhotoForRecipientWithoutName() { + return new ResourceContactPhoto(R.drawable.ic_search_24, R.drawable.ic_search_24, R.drawable.ic_search_24); + } + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java index fcdf376b21..01fbfaef8b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java @@ -259,7 +259,7 @@ public class ContactsCursorLoader extends AbstractContactsCursorLoader { } private Cursor getUsernameSearchCursor() { - return ContactsCursorRows.forUsernameSearch(getUnknownContactTitle(), getFilter()); + return ContactsCursorRows.forUsernameSearch(getFilter()); } private String getUnknownContactTitle() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorRows.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorRows.java index d3729679a6..bf4ac82eef 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorRows.java +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorRows.java @@ -104,11 +104,11 @@ public final class ContactsCursorRows { /** * Create a row for a contacts cursor for a username the user is entering or has entered. */ - public static @NonNull MatrixCursor forUsernameSearch(@NonNull String unknownContactTitle, @NonNull String filter) { + public static @NonNull MatrixCursor forUsernameSearch(@NonNull String filter) { MatrixCursor matrixCursor = createMatrixCursor(1); matrixCursor.addRow(new Object[]{null, - unknownContactTitle, + null, filter, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM, "\u21e2", @@ -119,7 +119,7 @@ public final class ContactsCursorRows { } public static @NonNull MatrixCursor forUsernameSearchHeader(@NonNull Context context) { - return forHeader(context.getString(R.string.ContactsCursorLoader_username_search)); + return forHeader(context.getString(R.string.ContactsCursorLoader_find_by_username)); } public static @NonNull MatrixCursor forPhoneNumberSearchHeader(@NonNull Context context) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/avatars/ResourceContactPhoto.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/avatars/ResourceContactPhoto.java index 5b46faa9f6..500c43b14e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/avatars/ResourceContactPhoto.java +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/avatars/ResourceContactPhoto.java @@ -1,7 +1,6 @@ package org.thoughtcrime.securesms.contacts.avatars; import android.content.Context; -import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; @@ -17,8 +16,8 @@ import com.makeramen.roundedimageview.RoundedDrawable; import org.jetbrains.annotations.NotNull; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.avatar.Avatars; import org.thoughtcrime.securesms.conversation.colors.AvatarColor; +import org.thoughtcrime.securesms.conversation.colors.AvatarColorPair; import java.util.Objects; @@ -64,18 +63,10 @@ public class ResourceContactPhoto implements FallbackContactPhoto { } private @NonNull Drawable buildDrawable(@NonNull Context context, int resourceId, @NonNull AvatarColor color, boolean inverted) { - final int backgroundColor; - final int foregroundColor; + AvatarColorPair avatarColorPair = AvatarColorPair.create(context, color); - if (color == AvatarColor.UNKNOWN) { - backgroundColor = ContextCompat.getColor(context, R.color.signal_colorSurfaceVariant); - foregroundColor = ContextCompat.getColor(context, R.color.signal_colorOnSurface); - } else { - Avatars.ForegroundColor foregroundAvatarColor = Avatars.getForegroundColor(color); - - backgroundColor = color.colorInt(); - foregroundColor = foregroundAvatarColor.getColorInt(); - } + final int backgroundColor = avatarColorPair.getBackgroundColor(); + final int foregroundColor = avatarColorPair.getForegroundColor(); Drawable background = Objects.requireNonNull(ContextCompat.getDrawable(context, R.drawable.circle_tintable)); RoundedDrawable foreground = (RoundedDrawable) RoundedDrawable.fromDrawable(AppCompatResources.getDrawable(context, resourceId)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/AvatarColor.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/AvatarColor.java index 5761824482..ff679e476d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/AvatarColor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/AvatarColor.java @@ -24,7 +24,8 @@ public enum AvatarColor { A190("A190", 0xFFEAE6D5), A200("A200", 0xFFD2D2DC), A210("A210", 0xFFD7D7D9), - UNKNOWN("UNKNOWN", 0x00000000); + UNKNOWN("UNKNOWN", 0x00000000), + ON_SURFACE_VARIANT("ON_SURFACE_VARIANT", 0x00000000); /** Fast map of name to enum, while also giving us a location to map old colors to new ones. */ private static final Map NAME_MAP = new HashMap<>(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/AvatarColorPair.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/AvatarColorPair.kt new file mode 100644 index 0000000000..de1b1f0240 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/colors/AvatarColorPair.kt @@ -0,0 +1,32 @@ +package org.thoughtcrime.securesms.conversation.colors + +import android.content.Context +import androidx.annotation.ColorInt +import androidx.core.content.ContextCompat +import org.thoughtcrime.securesms.R +import org.thoughtcrime.securesms.avatar.Avatars + +class AvatarColorPair private constructor( + @ColorInt val foregroundColor: Int, + @ColorInt val backgroundColor: Int +) { + companion object { + @JvmStatic + fun create(context: Context, avatarColor: AvatarColor): AvatarColorPair { + return when (avatarColor) { + AvatarColor.UNKNOWN -> AvatarColorPair( + foregroundColor = ContextCompat.getColor(context, R.color.signal_colorOnSurface), + backgroundColor = ContextCompat.getColor(context, R.color.signal_colorSurfaceVariant) + ) + AvatarColor.ON_SURFACE_VARIANT -> AvatarColorPair( + foregroundColor = ContextCompat.getColor(context, R.color.signal_colorOnSurfaceVariant), + backgroundColor = ContextCompat.getColor(context, R.color.signal_colorSurfaceVariant) + ) + else -> AvatarColorPair( + foregroundColor = Avatars.getForegroundColor(avatarColor).colorInt, + backgroundColor = avatarColor.colorInt() + ) + } + } + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 59c65a57da..945906381a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -214,7 +214,8 @@ Contacts Groups Phone number search - Username search + + Find by username My Stories