mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-27 21:24:42 +00:00
Update various message request UI.
This commit is contained in:
committed by
Greyson Parrelli
parent
caa1d0a2b3
commit
9eba978da6
@@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.ContextUtil;
|
||||
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
|
||||
import org.thoughtcrime.securesms.util.SpanUtil;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.whispersystems.signalservice.api.util.Preconditions;
|
||||
|
||||
public class ConversationHeaderView extends ConstraintLayout {
|
||||
@@ -135,7 +136,7 @@ public class ConversationHeaderView extends ConstraintLayout {
|
||||
}
|
||||
|
||||
if (recipient.isIndividual() && !recipient.isSelf()) {
|
||||
CharSequence chevronRight = SignalSymbols.getSpannedString(getContext(), SignalSymbols.Weight.BOLD, SignalSymbols.Glyph.CHEVRON_RIGHT);
|
||||
CharSequence chevronRight = SignalSymbols.getSpannedString(getContext(), SignalSymbols.Weight.BOLD, SignalSymbols.Glyph.CHEVRON_RIGHT, R.color.signal_colorOutline);
|
||||
title.append(" ");
|
||||
title.append(SpanUtil.ofSize(chevronRight, 24));
|
||||
|
||||
@@ -192,6 +193,7 @@ public class ConversationHeaderView extends ConstraintLayout {
|
||||
|
||||
binding.messageRequestDescription.setText(prependIcon(description, iconRes));
|
||||
binding.messageRequestDescription.setVisibility(View.VISIBLE);
|
||||
updateOutlineVisibility();
|
||||
}
|
||||
|
||||
public @NonNull EmojiTextView getDescription() {
|
||||
@@ -212,17 +214,17 @@ public class ConversationHeaderView extends ConstraintLayout {
|
||||
binding.messageRequestReviewCarefully.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void setUnverifiedNameSubtitle(@DrawableRes int iconRes, @StringRes int clickableRes, boolean forGroup, @Nullable Runnable onClick) {
|
||||
public void setUnverifiedNameSubtitle(@DrawableRes int iconRes, boolean forGroup, @NonNull Runnable onClick) {
|
||||
binding.messageRequestProfileNameUnverified.setVisibility(View.VISIBLE);
|
||||
binding.messageRequestProfileNameUnverified.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
CharSequence builder = SpanUtil.clickSubstring(
|
||||
getContext(),
|
||||
forGroup ? R.string.ConversationFragment_group_names_not_verified : R.string.ConversationFragment_profile_names_not_verified,
|
||||
clickableRes,
|
||||
listener -> onClick.run(),
|
||||
true,
|
||||
R.color.signal_colorOnSurface
|
||||
);
|
||||
binding.messageRequestProfileNameUnverified.setOnClickListener(view -> onClick.run());
|
||||
|
||||
String substring = forGroup ? getContext().getString(R.string.ConversationFragment_group_names)
|
||||
: getContext().getString(R.string.ConversationFragment_profile_names);
|
||||
|
||||
String fullString = forGroup ? getContext().getString(R.string.ConversationFragment_group_names_not_verified, substring)
|
||||
: getContext().getString(R.string.ConversationFragment_profile_names_not_verified, substring);
|
||||
|
||||
CharSequence builder = SpanUtil.underlineSubstring(fullString, substring);
|
||||
binding.messageRequestProfileNameUnverified.setText(prependIcon(builder, iconRes, forGroup));
|
||||
}
|
||||
|
||||
@@ -286,17 +288,27 @@ public class ConversationHeaderView extends ConstraintLayout {
|
||||
binding.messageRequestDivider.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.messageRequestInfoOutline.setVisibility(View.VISIBLE);
|
||||
binding.messageRequestDivider.setVisibility(View.INVISIBLE);
|
||||
binding.messageRequestDivider.setVisibility(View.GONE);
|
||||
}
|
||||
} else if (ViewKt.isVisible(binding.releaseHeaderContainer)) {
|
||||
binding.messageRequestInfoOutline.setVisibility(View.GONE);
|
||||
binding.messageRequestDivider.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
binding.messageRequestInfoOutline.setVisibility(View.GONE);
|
||||
binding.messageRequestDivider.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateOutlineBoxSize() {
|
||||
int visibleCount = 0;
|
||||
for (int i = 0; i < binding.messageRequestInfo.getChildCount(); i++) {
|
||||
if (ViewKt.isVisible(binding.messageRequestInfo.getChildAt(i))) {
|
||||
visibleCount++;
|
||||
}
|
||||
}
|
||||
|
||||
int padding = visibleCount == 1 ? getContext().getResources().getDimensionPixelOffset(R.dimen.conversation_header_padding) : getContext().getResources().getDimensionPixelOffset(R.dimen.conversation_header_padding_expanded);
|
||||
ViewUtil.setPaddingStart(binding.messageRequestInfo, padding);
|
||||
ViewUtil.setPaddingEnd(binding.messageRequestInfo, padding);
|
||||
}
|
||||
|
||||
private @NonNull CharSequence prependIcon(@NonNull CharSequence input, @DrawableRes int iconRes) {
|
||||
return prependIcon(input, iconRes, false);
|
||||
}
|
||||
@@ -305,8 +317,8 @@ public class ConversationHeaderView extends ConstraintLayout {
|
||||
private @NonNull CharSequence prependIcon(@NonNull CharSequence input, @DrawableRes int iconRes, boolean useIntrinsicWidth) {
|
||||
Drawable drawable = ContextCompat.getDrawable(getContext(), iconRes);
|
||||
Preconditions.checkNotNull(drawable);
|
||||
int width = useIntrinsicWidth ? drawable.getIntrinsicWidth() : (int) DimensionUnit.SP.toPixels(20);
|
||||
drawable.setBounds(0, 0, width, (int) DimensionUnit.SP.toPixels(20));
|
||||
int width = useIntrinsicWidth ? drawable.getIntrinsicWidth() : (int) DimensionUnit.SP.toPixels(16);
|
||||
drawable.setBounds(0, 0, width, (int) DimensionUnit.SP.toPixels(16));
|
||||
drawable.setColorFilter(ContextCompat.getColor(getContext(), R.color.signal_colorOnSurface), PorterDuff.Mode.SRC_ATOP);
|
||||
|
||||
return new SpannableStringBuilder()
|
||||
|
||||
@@ -563,7 +563,7 @@ class ConversationAdapterV2(
|
||||
|
||||
if (recipient.isGroup) {
|
||||
if (!groupInfo.hasExistingContacts) {
|
||||
conversationBanner.setUnverifiedNameSubtitle(R.drawable.symbol_group_question_20, R.string.ConversationFragment_group_names, true) {
|
||||
conversationBanner.setUnverifiedNameSubtitle(R.drawable.symbol_group_question_16, true) {
|
||||
clickListener.onShowUnverifiedProfileSheet(true)
|
||||
}
|
||||
} else {
|
||||
@@ -572,17 +572,20 @@ class ConversationAdapterV2(
|
||||
|
||||
if (groupInfo.pendingMemberCount > 0) {
|
||||
val invited = context.resources.getQuantityString(R.plurals.MessageRequestProfileView_invited, groupInfo.pendingMemberCount, groupInfo.pendingMemberCount)
|
||||
conversationBanner.setSubtitle(context.resources.getQuantityString(R.plurals.MessageRequestProfileView_members_and_invited, groupInfo.fullMemberCount, groupInfo.fullMemberCount, invited), R.drawable.symbol_group_light_20) { goToGroupSettings(recipient) }
|
||||
conversationBanner.setSubtitle(context.resources.getQuantityString(R.plurals.MessageRequestProfileView_members_and_invited, groupInfo.fullMemberCount, groupInfo.fullMemberCount, invited), R.drawable.symbol_group_compact_16) { goToGroupSettings(recipient) }
|
||||
} else if (groupInfo.fullMemberCount > 0) {
|
||||
conversationBanner.setSubtitle(context.resources.getQuantityString(R.plurals.MessageRequestProfileView_members, groupInfo.fullMemberCount, groupInfo.fullMemberCount), R.drawable.symbol_group_light_20) { goToGroupSettings(recipient) }
|
||||
if (groupInfo.fullMemberCount == 1 && recipient.isActiveGroup) {
|
||||
conversationBanner.hideUnverifiedNameSubtitle()
|
||||
}
|
||||
conversationBanner.setSubtitle(context.resources.getQuantityString(R.plurals.MessageRequestProfileView_members, groupInfo.fullMemberCount, groupInfo.fullMemberCount), R.drawable.symbol_group_compact_16) { goToGroupSettings(recipient) }
|
||||
} else {
|
||||
conversationBanner.hideSubtitle()
|
||||
}
|
||||
} else if (isSelf) {
|
||||
conversationBanner.setSubtitle(context.getString(R.string.ConversationFragment__you_can_add_notes_for_yourself_in_this_conversation), R.drawable.symbol_note_light_24, null)
|
||||
conversationBanner.setSubtitle(context.getString(R.string.ConversationFragment__you_can_add_notes_for_yourself_in_this_conversation), R.drawable.symbol_note_compact_16, null)
|
||||
} else {
|
||||
if (recipient.nickname.isEmpty && !recipient.isSystemContact) {
|
||||
conversationBanner.setUnverifiedNameSubtitle(R.drawable.symbol_person_question_16, R.string.ConversationFragment_profile_names, false) {
|
||||
if ((recipient.profileName.toString() == recipient.getDisplayName(context)) && recipient.nickname.isEmpty && !recipient.isSystemContact) {
|
||||
conversationBanner.setUnverifiedNameSubtitle(R.drawable.symbol_person_question_16, false) {
|
||||
clickListener.onShowUnverifiedProfileSheet(false)
|
||||
}
|
||||
} else {
|
||||
@@ -593,7 +596,7 @@ class ConversationAdapterV2(
|
||||
if (subtitle == null || subtitle == title) {
|
||||
conversationBanner.hideSubtitle()
|
||||
} else {
|
||||
conversationBanner.setSubtitle(subtitle, R.drawable.symbol_phone_light_20, null)
|
||||
conversationBanner.setSubtitle(subtitle, R.drawable.symbol_phone_compact_16, null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,7 +609,7 @@ class ConversationAdapterV2(
|
||||
conversationBanner.setButton(context.getString(R.string.ConversationFragment_safety_tips)) {
|
||||
clickListener.onShowSafetyTips(false)
|
||||
}
|
||||
conversationBanner.setDescription(getDescription(context, sharedGroups), R.drawable.symbol_group_light_20)
|
||||
conversationBanner.setDescription(getDescription(context, sharedGroups), R.drawable.symbol_group_compact_16)
|
||||
} else if (messageRequestState?.isAccepted == false && recipient.isGroup) {
|
||||
conversationBanner.showWarningSubtitle()
|
||||
conversationBanner.setButton(context.getString(R.string.ConversationFragment_safety_tips)) {
|
||||
@@ -633,8 +636,9 @@ class ConversationAdapterV2(
|
||||
}
|
||||
} else {
|
||||
conversationBanner.hideWarningSubtitle()
|
||||
conversationBanner.setDescription(getDescription(context, sharedGroups), R.drawable.symbol_group_light_20)
|
||||
conversationBanner.setDescription(getDescription(context, sharedGroups), R.drawable.symbol_group_compact_16)
|
||||
}
|
||||
conversationBanner.updateOutlineBoxSize()
|
||||
}
|
||||
|
||||
private fun getDescription(context: Context, sharedGroups: List<String>): String {
|
||||
|
||||
@@ -10,12 +10,14 @@ import android.graphics.Typeface
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.TextPaint
|
||||
import android.text.style.MetricAffectingSpan
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
|
||||
/**
|
||||
* Helper object for working with the SignalSymbols font
|
||||
@@ -40,7 +42,8 @@ object SignalSymbols {
|
||||
fun getSpannedString(
|
||||
context: Context,
|
||||
weight: Weight,
|
||||
glyph: Glyph
|
||||
glyph: Glyph,
|
||||
@ColorRes colorRes: Int = -1
|
||||
): CharSequence {
|
||||
val typeface = getTypeface(context, weight)
|
||||
val span = CustomTypefaceSpan(typeface)
|
||||
@@ -48,7 +51,11 @@ object SignalSymbols {
|
||||
val text = SpannableStringBuilder(glyph.unicode.toString())
|
||||
text.setSpan(span, 0, text.length, 0)
|
||||
|
||||
return text
|
||||
return if (colorRes != -1) {
|
||||
SpanUtil.color(colorRes, text)
|
||||
} else {
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -255,6 +255,8 @@ class RecipientBottomSheetDialogFragment : BottomSheetDialogFragment() {
|
||||
nickname.setOnClickListener {
|
||||
nicknameLauncher.launch(NicknameActivity.Args(recipientId, false))
|
||||
}
|
||||
} else if (recipient.isReleaseNotes) {
|
||||
fullName.text = name
|
||||
}
|
||||
|
||||
var aboutText = recipient.combinedAboutAndEmoji
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.text.style.StyleSpan;
|
||||
import android.text.style.TextAppearanceSpan;
|
||||
import android.text.style.TypefaceSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.text.style.UnderlineSpan;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
@@ -99,6 +100,17 @@ public final class SpanUtil {
|
||||
return spannable;
|
||||
}
|
||||
|
||||
public static CharSequence underlineSubstring(CharSequence fullString, CharSequence substring) {
|
||||
SpannableString spannable = new SpannableString(fullString);
|
||||
int start = TextUtils.indexOf(fullString, substring);
|
||||
int end = start + substring.length();
|
||||
|
||||
if (start >= 0 && end <= fullString.length()) {
|
||||
spannable.setSpan(new UnderlineSpan(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
return spannable;
|
||||
}
|
||||
|
||||
public static CharSequence color(int color, CharSequence sequence) {
|
||||
SpannableString spannable = new SpannableString(sequence);
|
||||
spannable.setSpan(new ForegroundColorSpan(color), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
Reference in New Issue
Block a user