Implement mention rendering

This commit is contained in:
Niels Andriesse
2019-10-09 16:41:14 +11:00
parent 7116f2502a
commit 5901967eee
3 changed files with 54 additions and 21 deletions

View File

@@ -42,6 +42,7 @@ import android.text.style.ForegroundColorSpan;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.util.AttributeSet;
import android.util.Range;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
@@ -114,11 +115,14 @@ import org.thoughtcrime.securesms.util.views.Stub;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import network.loki.messenger.R;
@@ -258,7 +262,7 @@ public class ConversationItem extends LinearLayout
setMessageShape(messageRecord, previousMessageRecord, nextMessageRecord, groupThread);
setMediaAttributes(messageRecord, previousMessageRecord, nextMessageRecord, conversationRecipient, groupThread);
setInteractionState(messageRecord, pulseHighlight);
setBodyText(messageRecord, searchQuery);
setBodyText(messageRecord, searchQuery, groupThread);
setBubbleState(messageRecord);
setStatusIcons(messageRecord);
setContactPhoto(recipient);
@@ -464,7 +468,7 @@ public class ConversationItem extends LinearLayout
!StickerUrl.isValidShareLink(linkPreview.getUrl());
}
private void setBodyText(MessageRecord messageRecord, @Nullable String searchQuery) {
private void setBodyText(MessageRecord messageRecord, @Nullable String searchQuery, boolean isGroupThread) {
bodyText.setClickable(false);
bodyText.setFocusable(false);
bodyText.setTextSize(TypedValue.COMPLEX_UNIT_SP, TextSecurePreferences.getMessageBodyTextSize(context));
@@ -472,9 +476,9 @@ public class ConversationItem extends LinearLayout
if (isCaptionlessMms(messageRecord)) {
bodyText.setVisibility(View.GONE);
} else {
Spannable styledText = linkifyMessageBody(messageRecord.getDisplayBody(getContext()), batchSelected.isEmpty());
styledText = SearchUtil.getHighlightedSpan(locale, () -> new BackgroundColorSpan(Color.YELLOW), styledText, searchQuery);
styledText = SearchUtil.getHighlightedSpan(locale, () -> new ForegroundColorSpan(Color.BLACK), styledText, searchQuery);
Spannable text = linkifyMessageBody(highlightMentions(messageRecord.getDisplayBody(context), isGroupThread), batchSelected.isEmpty());
text = SearchUtil.getHighlightedSpan(locale, () -> new BackgroundColorSpan(Color.YELLOW), text, searchQuery);
text = SearchUtil.getHighlightedSpan(locale, () -> new ForegroundColorSpan(Color.BLACK), text, searchQuery);
if (hasExtraText(messageRecord)) {
bodyText.setOverflowText(getLongMessageSpan(messageRecord));
@@ -482,7 +486,7 @@ public class ConversationItem extends LinearLayout
bodyText.setOverflowText(null);
}
bodyText.setText(styledText);
bodyText.setText(text);
bodyText.setVisibility(View.VISIBLE);
}
}
@@ -772,6 +776,40 @@ public class ConversationItem extends LinearLayout
return messageBody;
}
private SpannableString highlightMentions(CharSequence text, boolean isGroupThread) {
Pattern pattern = Pattern.compile("@\\w*");
Matcher matcher = pattern.matcher(text);
ArrayList<Range<Integer>> mentions = new ArrayList<>();
if (matcher.find() && isGroupThread) {
while (true) {
CharSequence userID = text.subSequence(matcher.start() + 1, matcher.end()); // +1 to get rid of the @
Integer matchEnd;
String userDisplayName;
if (userID.equals(TextSecurePreferences.getLocalNumber(context))) {
userDisplayName = TextSecurePreferences.getProfileName(context);
} else {
String publicChatID = LokiGroupChatAPI.getPublicChatServer() + "." + LokiGroupChatAPI.getPublicChatServerID();
userDisplayName = DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(publicChatID, userID.toString());
}
if (userDisplayName != null) {
text = text.subSequence(0, matcher.start()) + "@" + userDisplayName + text.subSequence(matcher.end(), Math.max(text.length(), matcher.end()));
matchEnd = matcher.start() + 1 + userDisplayName.length();
mentions.add(Range.create(matcher.start(), matchEnd));
} else {
matchEnd = matcher.end();
}
matcher = pattern.matcher(text.subSequence(matchEnd, Math.max(text.length(), matchEnd)));
if (!matcher.find()) { break; }
}
}
SpannableString result = new SpannableString(text);
for (Range<Integer> range : mentions) {
int highlightColor = (messageRecord.isOutgoing()) ? getResources().getColor(R.color.loki_dark_green) : getResources().getColor(R.color.loki_green);
result.setSpan(new BackgroundColorSpan(highlightColor), range.getLower(), range.getUpper(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return result;
}
private void setStatusIcons(MessageRecord messageRecord) {
bodyText.setCompoundDrawablesWithIntrinsicBounds(0, 0, messageRecord.isKeyExchange() ? R.drawable.ic_menu_login : 0, 0);