Enforce two line limit on group description.

Sorry.
This commit is contained in:
Cody Henthorne 2021-05-19 11:57:53 -04:00 committed by GitHub
parent 5d5d61d8ed
commit f890ae8ddc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 75 additions and 57 deletions

View file

@ -24,7 +24,6 @@ import org.thoughtcrime.securesms.components.emoji.parsing.EmojiParser;
import org.thoughtcrime.securesms.components.mention.MentionAnnotation;
import org.thoughtcrime.securesms.components.mention.MentionRendererDelegate;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
@ -91,7 +90,8 @@ public class EmojiTextView extends AppCompatTextView {
super.onDraw(canvas);
}
@Override public void setText(@Nullable CharSequence text, BufferType type) {
@Override
public void setText(@Nullable CharSequence text, BufferType type) {
EmojiParser.CandidateList candidates = isInEditMode() ? null : EmojiProvider.getCandidates(text);
if (scaleEmojis && candidates != null && candidates.allEmojis) {
@ -118,25 +118,21 @@ public class EmojiTextView extends AppCompatTextView {
useSystemEmoji = useSystemEmoji();
if (useSystemEmoji || candidates == null || candidates.size() == 0) {
super.setText(new SpannableStringBuilder(Optional.fromNullable(text).or("")).append(Optional.fromNullable(overflowText).or("")), BufferType.NORMAL);
if (getEllipsize() == TextUtils.TruncateAt.END && maxLength > 0) {
ellipsizeAnyTextForMaxLength();
}
super.setText(new SpannableStringBuilder(Optional.fromNullable(text).or("")), BufferType.NORMAL);
} else {
CharSequence emojified = EmojiProvider.emojify(candidates, text, this);
super.setText(new SpannableStringBuilder(emojified).append(Optional.fromNullable(overflowText).or("")), BufferType.SPANNABLE);
super.setText(new SpannableStringBuilder(emojified), BufferType.SPANNABLE);
}
// Android fails to ellipsize spannable strings. (https://issuetracker.google.com/issues/36991688)
// We ellipsize them ourselves by manually truncating the appropriate section.
if (getEllipsize() == TextUtils.TruncateAt.END) {
if (getText() != null && getText().length() > 0 && getEllipsize() == TextUtils.TruncateAt.END) {
if (maxLength > 0) {
ellipsizeAnyTextForMaxLength();
} else {
} else if (getMaxLines() > 0) {
ellipsizeEmojiTextForMaxLines();
}
}
}
if (getLayoutParams() != null && getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) {
requestLayout();
@ -192,7 +188,8 @@ public class EmojiTextView extends AppCompatTextView {
if (lineCount > maxLines) {
int overflowStart = getLayout().getLineStart(maxLines - 1);
CharSequence overflow = getText().subSequence(overflowStart, getText().length());
CharSequence ellipsized = TextUtils.ellipsize(overflow, getPaint(), getWidth(), TextUtils.TruncateAt.END);
float adjust = overflowText != null ? getPaint().measureText(overflowText, 0, overflowText.length()) : 0f;
CharSequence ellipsized = TextUtils.ellipsize(overflow, getPaint(), getWidth() - adjust, TextUtils.TruncateAt.END);
SpannableStringBuilder newContent = new SpannableStringBuilder();
newContent.append(getText().subSequence(0, overflowStart))

View file

@ -19,6 +19,7 @@ import androidx.core.widget.ImageViewCompat;
import org.signal.core.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
import org.thoughtcrime.securesms.database.DatabaseFactory;
@ -31,7 +32,7 @@ public class ConversationBannerView extends ConstraintLayout {
private TextView contactTitle;
private TextView contactAbout;
private TextView contactSubtitle;
private TextView contactDescription;
private EmojiTextView contactDescription;
private View tapToView;
public ConversationBannerView(Context context) {
@ -91,6 +92,10 @@ public class ConversationBannerView extends ConstraintLayout {
contactDescription.setVisibility(TextUtils.isEmpty(description) ? GONE : VISIBLE);
}
public @NonNull EmojiTextView getDescription() {
return contactDescription;
}
public void showBackgroundBubble(boolean enabled) {
if (enabled) {
setBackgroundResource(R.drawable.wallpaper_bubble_background_12);

View file

@ -541,13 +541,15 @@ public class ConversationFragment extends LoggingFragment {
} else {
conversationBanner.setLinkifyDescription(true);
boolean linkifyWebLinks = recipientInfo.getMessageRequestState() == MessageRequestState.NONE;
conversationBanner.setDescription(GroupDescriptionUtil.style(context,
conversationBanner.showDescription();
GroupDescriptionUtil.setText(context,
conversationBanner.getDescription(),
recipientInfo.getGroupDescription(),
linkifyWebLinks,
() -> GroupDescriptionDialog.show(getChildFragmentManager(),
recipient.getDisplayName(context),
recipientInfo.getGroupDescription(),
linkifyWebLinks)));
linkifyWebLinks));
}
} else {
final String description;

View file

@ -24,6 +24,7 @@ import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.color.MaterialColor;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
import org.thoughtcrime.securesms.conversation.ConversationIntents;
@ -46,7 +47,7 @@ public final class GroupJoinBottomSheetDialogFragment extends BottomSheetDialogF
private AvatarImageView avatar;
private TextView groupName;
private TextView groupDetails;
private TextView groupDescription;
private EmojiTextView groupDescription;
private TextView groupJoinExplain;
private Button groupJoinButton;
private Button groupCancelButton;
@ -158,10 +159,11 @@ public final class GroupJoinBottomSheetDialogFragment extends BottomSheetDialogF
private void updateGroupDescription(@NonNull String name, @NonNull String description) {
groupDescription.setVisibility(View.VISIBLE);
groupDescription.setMovementMethod(LinkMovementMethod.getInstance());
groupDescription.setText(GroupDescriptionUtil.style(requireContext(),
GroupDescriptionUtil.setText(requireContext(),
groupDescription,
description,
true,
() -> GroupDescriptionDialog.show(getChildFragmentManager(), name, description, true)));
() -> GroupDescriptionDialog.show(getChildFragmentManager(), name, description, true));
}
private static ExtendedGroupJoinStatus getGroupJoinStatus() {

View file

@ -458,15 +458,17 @@ public class ManageGroupFragment extends LoggingFragment {
if (TextUtils.isEmpty(description.getDescription())) {
if (FeatureFlags.groupsV2Description() && description.canEditDescription()) {
groupDescription.setOverflowText(null);
groupDescription.setText(R.string.ManageGroupActivity_add_group_description);
groupDescription.setOnClickListener(v -> startActivity(EditProfileActivity.getIntentForGroupProfile(requireActivity(), getGroupId())));
}
} else {
groupDescription.setOnClickListener(null);
groupDescription.setText(GroupDescriptionUtil.style(requireContext(),
GroupDescriptionUtil.setText(requireContext(),
groupDescription,
description.getDescription(),
description.shouldLinkifyWebLinks(),
() -> GroupDescriptionDialog.show(getChildFragmentManager(), getGroupId(), null, description.shouldLinkifyWebLinks())));
() -> GroupDescriptionDialog.show(getChildFragmentManager(), getGroupId(), null, description.shouldLinkifyWebLinks()));
}
}

View file

@ -16,6 +16,7 @@ import androidx.fragment.app.FragmentManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.LiveGroup;
import org.thoughtcrime.securesms.groups.ParcelableGroupId;
@ -34,7 +35,7 @@ public final class GroupDescriptionDialog extends DialogFragment {
private static final String ARGUMENT_LINKIFY = "linkify";
private static final String DIALOG_TAG = "GroupDescriptionDialog";
private TextView descriptionText;
private EmojiTextView descriptionText;
public static void show(@NonNull FragmentManager fragmentManager, @NonNull String title, @Nullable String description, boolean linkify) {
show(fragmentManager, null, title, description, linkify);
@ -76,9 +77,9 @@ public final class GroupDescriptionDialog extends DialogFragment {
.create();
if (argumentDescription != null) {
descriptionText.setText(GroupDescriptionUtil.style(requireContext(), argumentDescription, linkify, null));
GroupDescriptionUtil.setText(requireContext(), descriptionText, argumentDescription, linkify, null);
} else if (liveGroup != null) {
liveGroup.getDescription().observe(this, d -> descriptionText.setText(GroupDescriptionUtil.style(requireContext(), d, linkify, null)));
liveGroup.getDescription().observe(this, d -> GroupDescriptionUtil.setText(requireContext(), descriptionText, d, linkify, null));
}
if (TextUtils.isEmpty(argumentTitle) && liveGroup != null) {

View file

@ -7,6 +7,7 @@ import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.ClickableSpan;
import android.text.style.URLSpan;
import android.text.util.Linkify;
@ -18,6 +19,7 @@ import androidx.annotation.Nullable;
import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
public final class GroupDescriptionUtil {
@ -25,14 +27,14 @@ public final class GroupDescriptionUtil {
public static final int MAX_DESCRIPTION_LENGTH = 80;
/**
* Style a group description.
* Set a group description.
*
* @param description full description
* @param emojiTextView Text view to update with description
* @param linkify flag indicating if web urls should be linkified
* @param moreClick Callback for when truncating and need to show more via another means. Required to enable truncating.
* @return styled group description
*/
public static @NonNull Spannable style(@NonNull Context context, @NonNull String description, boolean linkify, @Nullable Runnable moreClick) {
public static void setText(@NonNull Context context, @NonNull EmojiTextView emojiTextView, @NonNull String description, boolean linkify, @Nullable Runnable moreClick) {
SpannableString descriptionSpannable = new SpannableString(description);
if (linkify) {
@ -46,7 +48,7 @@ public final class GroupDescriptionUtil {
}
}
if (moreClick != null && descriptionSpannable.length() > MAX_DESCRIPTION_LENGTH) {
if (moreClick != null) {
ClickableSpan style = new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
@ -59,11 +61,14 @@ public final class GroupDescriptionUtil {
}
};
SpannableStringBuilder builder = new SpannableStringBuilder(descriptionSpannable.subSequence(0, MAX_DESCRIPTION_LENGTH)).append(context.getString(R.string.ManageGroupActivity_more));
builder.setSpan(style, MAX_DESCRIPTION_LENGTH + 1, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return builder;
emojiTextView.setEllipsize(TextUtils.TruncateAt.END);
emojiTextView.setMaxLines(2);
SpannableString overflowText = new SpannableString(context.getString(R.string.ManageGroupActivity_more));
overflowText.setSpan(style, 0, overflowText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
emojiTextView.setOverflowText(overflowText);
}
return descriptionSpannable;
emojiTextView.setText(descriptionSpannable);
}
}

View file

@ -4,6 +4,7 @@ import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;
import android.view.LayoutInflater;
import android.view.View;
@ -261,16 +262,15 @@ final class StickerManagementAdapter extends SectionedRecyclerViewAdapter<String
boolean lastInList,
boolean allowApngAnimation)
{
title.setText(stickerPack.getTitle().or(itemView.getResources().getString(R.string.StickerManagementAdapter_untitled)));
SpannableStringBuilder titleBuilder = new SpannableStringBuilder(stickerPack.getTitle().or(itemView.getResources().getString(R.string.StickerManagementAdapter_untitled)));
if (BlessedPacks.contains(stickerPack.getPackId())) {
titleBuilder.append(blessedBadge);
}
title.setText(titleBuilder);
author.setText(stickerPack.getAuthor().or(itemView.getResources().getString(R.string.StickerManagementAdapter_unknown)));
divider.setVisibility(lastInList ? View.GONE : View.VISIBLE);
if (BlessedPacks.contains(stickerPack.getPackId())) {
title.setOverflowText(blessedBadge);
} else {
title.setOverflowText(null);
}
glideRequests.load(new DecryptableUri(stickerPack.getCover().getUri()))
.transition(DrawableTransitionOptions.withCrossFade())
.set(ApngOptions.ANIMATE, allowApngAnimation)

View file

@ -61,7 +61,9 @@
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:ellipsize="end"
android:gravity="center_horizontal"
android:maxLines="2"
android:textColor="@color/signal_text_secondary"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"

View file

@ -58,10 +58,12 @@
android:id="@+id/manage_group_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:gravity="center_horizontal"
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="@style/Signal.Text.Body"
android:textColor="@color/signal_text_secondary"
android:visibility="gone"

View file

@ -748,7 +748,7 @@
<string name="ManageGroupActivity_upgrade_this_group">upgrade this group.</string>
<string name="ManageGroupActivity_this_is_an_insecure_mms_group">This is an insecure MMS Group. To chat privately, invite your contacts to Signal.</string>
<string name="ManageGroupActivity_invite_now">Invite now</string>
<string name="ManageGroupActivity_more">more</string>
<string name="ManageGroupActivity_more">more</string>
<string name="ManageGroupActivity_add_group_description">Add group description…</string>
<!-- GroupMentionSettingDialog -->