|
|
@ -42,6 +42,7 @@ import android.text.style.ForegroundColorSpan;
|
|
|
|
import android.text.style.URLSpan;
|
|
|
|
import android.text.style.URLSpan;
|
|
|
|
import android.text.util.Linkify;
|
|
|
|
import android.text.util.Linkify;
|
|
|
|
import android.util.AttributeSet;
|
|
|
|
import android.util.AttributeSet;
|
|
|
|
|
|
|
|
import android.util.Range;
|
|
|
|
import android.util.TypedValue;
|
|
|
|
import android.util.TypedValue;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
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.libsignal.util.guava.Optional;
|
|
|
|
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI;
|
|
|
|
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Locale;
|
|
|
|
import java.util.Locale;
|
|
|
|
import java.util.Set;
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
import java.util.regex.Matcher;
|
|
|
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
|
|
|
|
import network.loki.messenger.R;
|
|
|
|
import network.loki.messenger.R;
|
|
|
|
|
|
|
|
|
|
|
@ -258,7 +262,7 @@ public class ConversationItem extends LinearLayout
|
|
|
|
setMessageShape(messageRecord, previousMessageRecord, nextMessageRecord, groupThread);
|
|
|
|
setMessageShape(messageRecord, previousMessageRecord, nextMessageRecord, groupThread);
|
|
|
|
setMediaAttributes(messageRecord, previousMessageRecord, nextMessageRecord, conversationRecipient, groupThread);
|
|
|
|
setMediaAttributes(messageRecord, previousMessageRecord, nextMessageRecord, conversationRecipient, groupThread);
|
|
|
|
setInteractionState(messageRecord, pulseHighlight);
|
|
|
|
setInteractionState(messageRecord, pulseHighlight);
|
|
|
|
setBodyText(messageRecord, searchQuery);
|
|
|
|
setBodyText(messageRecord, searchQuery, groupThread);
|
|
|
|
setBubbleState(messageRecord);
|
|
|
|
setBubbleState(messageRecord);
|
|
|
|
setStatusIcons(messageRecord);
|
|
|
|
setStatusIcons(messageRecord);
|
|
|
|
setContactPhoto(recipient);
|
|
|
|
setContactPhoto(recipient);
|
|
|
@ -464,7 +468,7 @@ public class ConversationItem extends LinearLayout
|
|
|
|
!StickerUrl.isValidShareLink(linkPreview.getUrl());
|
|
|
|
!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.setClickable(false);
|
|
|
|
bodyText.setFocusable(false);
|
|
|
|
bodyText.setFocusable(false);
|
|
|
|
bodyText.setTextSize(TypedValue.COMPLEX_UNIT_SP, TextSecurePreferences.getMessageBodyTextSize(context));
|
|
|
|
bodyText.setTextSize(TypedValue.COMPLEX_UNIT_SP, TextSecurePreferences.getMessageBodyTextSize(context));
|
|
|
@ -472,9 +476,9 @@ public class ConversationItem extends LinearLayout
|
|
|
|
if (isCaptionlessMms(messageRecord)) {
|
|
|
|
if (isCaptionlessMms(messageRecord)) {
|
|
|
|
bodyText.setVisibility(View.GONE);
|
|
|
|
bodyText.setVisibility(View.GONE);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Spannable styledText = linkifyMessageBody(messageRecord.getDisplayBody(getContext()), batchSelected.isEmpty());
|
|
|
|
Spannable text = linkifyMessageBody(highlightMentions(messageRecord.getDisplayBody(context), isGroupThread), batchSelected.isEmpty());
|
|
|
|
styledText = SearchUtil.getHighlightedSpan(locale, () -> new BackgroundColorSpan(Color.YELLOW), styledText, searchQuery);
|
|
|
|
text = SearchUtil.getHighlightedSpan(locale, () -> new BackgroundColorSpan(Color.YELLOW), text, searchQuery);
|
|
|
|
styledText = SearchUtil.getHighlightedSpan(locale, () -> new ForegroundColorSpan(Color.BLACK), styledText, searchQuery);
|
|
|
|
text = SearchUtil.getHighlightedSpan(locale, () -> new ForegroundColorSpan(Color.BLACK), text, searchQuery);
|
|
|
|
|
|
|
|
|
|
|
|
if (hasExtraText(messageRecord)) {
|
|
|
|
if (hasExtraText(messageRecord)) {
|
|
|
|
bodyText.setOverflowText(getLongMessageSpan(messageRecord));
|
|
|
|
bodyText.setOverflowText(getLongMessageSpan(messageRecord));
|
|
|
@ -482,7 +486,7 @@ public class ConversationItem extends LinearLayout
|
|
|
|
bodyText.setOverflowText(null);
|
|
|
|
bodyText.setOverflowText(null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bodyText.setText(styledText);
|
|
|
|
bodyText.setText(text);
|
|
|
|
bodyText.setVisibility(View.VISIBLE);
|
|
|
|
bodyText.setVisibility(View.VISIBLE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -772,6 +776,40 @@ public class ConversationItem extends LinearLayout
|
|
|
|
return messageBody;
|
|
|
|
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) {
|
|
|
|
private void setStatusIcons(MessageRecord messageRecord) {
|
|
|
|
bodyText.setCompoundDrawablesWithIntrinsicBounds(0, 0, messageRecord.isKeyExchange() ? R.drawable.ic_menu_login : 0, 0);
|
|
|
|
bodyText.setCompoundDrawablesWithIntrinsicBounds(0, 0, messageRecord.isKeyExchange() ? R.drawable.ic_menu_login : 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|