mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-25 01:07:47 +00:00
Implement mention rendering
This commit is contained in:
parent
7116f2502a
commit
5901967eee
@ -2,6 +2,7 @@
|
||||
<resources>
|
||||
<!-- Loki -->
|
||||
<color name="loki_green">#78be20</color>
|
||||
<color name="loki_dark_green">#419B41</color>
|
||||
<color name="loki_darkest_gray">#0a0a0a</color>
|
||||
<!-- Loki -->
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -9,9 +9,6 @@ import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Toast
|
||||
import kotlinx.android.synthetic.main.activity_seed.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||
@ -180,13 +177,12 @@ class SeedActivity : BaseActionBarActivity(), DeviceLinkingDialogDelegate {
|
||||
IdentityKeyUtil.generateIdentityKeyPair(this, seed)
|
||||
}
|
||||
val keyPair = IdentityKeyUtil.getIdentityKeyPair(this)
|
||||
val publicKey = keyPair.publicKey
|
||||
val hexEncodedPublicKey = keyPair.hexEncodedPublicKey
|
||||
val userHexEncodedPublicKey = keyPair.hexEncodedPublicKey
|
||||
val registrationID = KeyHelper.generateRegistrationId(false)
|
||||
TextSecurePreferences.setLocalRegistrationId(this, registrationID)
|
||||
DatabaseFactory.getIdentityDatabase(this).saveIdentity(Address.fromSerialized(hexEncodedPublicKey), publicKey,
|
||||
DatabaseFactory.getIdentityDatabase(this).saveIdentity(Address.fromSerialized(userHexEncodedPublicKey), keyPair.publicKey,
|
||||
IdentityDatabase.VerifiedStatus.VERIFIED, true, System.currentTimeMillis(), true)
|
||||
TextSecurePreferences.setLocalNumber(this, hexEncodedPublicKey)
|
||||
TextSecurePreferences.setLocalNumber(this, userHexEncodedPublicKey)
|
||||
when (mode) {
|
||||
Mode.Register -> Analytics.shared.track("Seed Created")
|
||||
Mode.Restore -> Analytics.shared.track("Seed Restored")
|
||||
@ -195,23 +191,21 @@ class SeedActivity : BaseActionBarActivity(), DeviceLinkingDialogDelegate {
|
||||
if (mode == Mode.Link) {
|
||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
|
||||
TextSecurePreferences.setPromptedPushRegistration(this, true)
|
||||
val primaryDevicePublicKey = publicKeyEditText.text.trim().toString()
|
||||
val authorisation = PairingAuthorisation(primaryDevicePublicKey, hexEncodedPublicKey).sign(PairingAuthorisation.Type.REQUEST, keyPair.privateKey.serialize())
|
||||
val masterHexEncodedPublicKey = publicKeyEditText.text.trim().toString()
|
||||
val authorisation = PairingAuthorisation(masterHexEncodedPublicKey, userHexEncodedPublicKey).sign(PairingAuthorisation.Type.REQUEST, keyPair.privateKey.serialize())
|
||||
if (authorisation == null) {
|
||||
Log.d("Loki", "Failed to sign outgoing pairing request.")
|
||||
Log.d("Loki", "Failed to sign pairing request.")
|
||||
resetForRegistration()
|
||||
return Toast.makeText(application, "Failed to link device.", Toast.LENGTH_SHORT).show()
|
||||
return Toast.makeText(application, "Couldn't start device linking process.", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
val application = ApplicationContext.getInstance(this)
|
||||
application.startLongPollingIfNeeded()
|
||||
application.setUpP2PAPI()
|
||||
application.setUpStorageAPIIfNeeded()
|
||||
DeviceLinkingDialog.show(this, DeviceLinkingView.Mode.Slave, this)
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
retryIfNeeded(8) {
|
||||
sendPairingAuthorisationMessage(this@SeedActivity, authorisation.primaryDevicePublicKey, authorisation).get()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
startActivity(Intent(this, DisplayNameActivity::class.java))
|
||||
finish()
|
||||
|
Loading…
x
Reference in New Issue
Block a user