mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-03 05:22:23 +00:00
Merge branch 'dev' into custom-server
# Conflicts: # src/org/thoughtcrime/securesms/loki/DisplayNameActivity.kt
This commit is contained in:
@@ -156,7 +156,11 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.loki.LokiAPIUtilities;
|
||||
import org.thoughtcrime.securesms.loki.LokiThreadDatabaseDelegate;
|
||||
import org.thoughtcrime.securesms.loki.LokiUserDatabase;
|
||||
import org.thoughtcrime.securesms.loki.Mention;
|
||||
import org.thoughtcrime.securesms.loki.UserSelectionView;
|
||||
import org.thoughtcrime.securesms.mediasend.Media;
|
||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||
@@ -224,12 +228,14 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI;
|
||||
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus;
|
||||
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus;
|
||||
import org.whispersystems.signalservice.loki.utilities.Analytics;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
@@ -239,7 +245,9 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import kotlin.Unit;
|
||||
import network.loki.messenger.R;
|
||||
import nl.komponents.kovenant.combine.Tuple2;
|
||||
|
||||
import static org.thoughtcrime.securesms.TransportOption.Type;
|
||||
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
@@ -292,23 +300,24 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private static final int SMS_DEFAULT = 11;
|
||||
private static final int MEDIA_SENDER = 12;
|
||||
|
||||
private GlideRequests glideRequests;
|
||||
protected ComposeText composeText;
|
||||
private AnimatingToggle buttonToggle;
|
||||
private SendButton sendButton;
|
||||
private ImageButton attachButton;
|
||||
protected ConversationTitleView titleView;
|
||||
private TextView charactersLeft;
|
||||
private ConversationFragment fragment;
|
||||
private Button unblockButton;
|
||||
private Button makeDefaultSmsButton;
|
||||
private Button registerButton;
|
||||
private InputAwareLayout container;
|
||||
private View composePanel;
|
||||
protected Stub<ReminderView> reminderView;
|
||||
private Stub<UnverifiedBannerView> unverifiedBannerView;
|
||||
private GlideRequests glideRequests;
|
||||
protected ComposeText composeText;
|
||||
private AnimatingToggle buttonToggle;
|
||||
private SendButton sendButton;
|
||||
private ImageButton attachButton;
|
||||
protected ConversationTitleView titleView;
|
||||
private TextView charactersLeft;
|
||||
private ConversationFragment fragment;
|
||||
private Button unblockButton;
|
||||
private Button makeDefaultSmsButton;
|
||||
private Button registerButton;
|
||||
private InputAwareLayout container;
|
||||
private View composePanel;
|
||||
protected Stub<ReminderView> reminderView;
|
||||
private Stub<UnverifiedBannerView> unverifiedBannerView;
|
||||
private Stub<GroupShareProfileView> groupShareProfileView;
|
||||
private TypingStatusTextWatcher typingTextWatcher;
|
||||
private MentionTextWatcher mentionTextWatcher;
|
||||
private ConversationSearchBottomBar searchNav;
|
||||
private MenuItem searchViewItem;
|
||||
|
||||
@@ -338,6 +347,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private final DynamicNoActionBarTheme dynamicTheme = new DynamicNoActionBarTheme();
|
||||
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
|
||||
// Mentions
|
||||
private UserSelectionView userSelectionView;
|
||||
private int currentMentionStartIndex = -1;
|
||||
private ArrayList<Mention> mentions = new ArrayList<>();
|
||||
private String oldText = "";
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPreCreate() {
|
||||
@@ -389,11 +404,25 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
composeText.addTextChangedListener(typingTextWatcher);
|
||||
}
|
||||
composeText.setSelection(composeText.length(), composeText.length());
|
||||
composeText.addTextChangedListener(mentionTextWatcher);
|
||||
userSelectionView.setOnUserSelected(tuple -> {
|
||||
Mention mention = new Mention(currentMentionStartIndex, tuple.getFirst(), tuple.getSecond());
|
||||
mentions.add(mention);
|
||||
String oldText = composeText.getText().toString();
|
||||
String newText = oldText.substring(0, currentMentionStartIndex) + "@" + tuple.getSecond();
|
||||
composeText.setText(newText);
|
||||
composeText.setSelection(newText.length());
|
||||
userSelectionView.hide();
|
||||
currentMentionStartIndex = -1;
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
LokiAPIUtilities.INSTANCE.populateUserIDCacheIfNeeded(threadId, this);
|
||||
|
||||
if (this.recipient.isGroupRecipient()) {
|
||||
if (this.recipient.getName().equals("Loki Public Chat")) {
|
||||
Analytics.Companion.getShared().track("Loki Public Chat Opened");
|
||||
@@ -1552,6 +1581,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
inlineAttachmentToggle = ViewUtil.findById(this, R.id.inline_attachment_container);
|
||||
inputPanel = ViewUtil.findById(this, R.id.bottom_panel);
|
||||
searchNav = ViewUtil.findById(this, R.id.conversation_search_nav);
|
||||
userSelectionView = ViewUtil.findById(this, R.id.userSelectionView);
|
||||
|
||||
ImageButton quickCameraToggle = ViewUtil.findById(this, R.id.quick_camera_toggle);
|
||||
ImageButton inlineAttachmentButton = ViewUtil.findById(this, R.id.inline_attachment_button);
|
||||
@@ -1564,6 +1594,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
attachmentManager = new AttachmentManager(this, this);
|
||||
audioRecorder = new AudioRecorder(this);
|
||||
typingTextWatcher = new TypingStatusTextWatcher();
|
||||
mentionTextWatcher = new MentionTextWatcher();
|
||||
|
||||
SendButtonListener sendButtonListener = new SendButtonListener();
|
||||
ComposeKeyPressedListener composeKeyPressedListener = new ComposeKeyPressedListener();
|
||||
@@ -2060,12 +2091,20 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private String getMessage() throws InvalidMessageException {
|
||||
String rawText = composeText.getTextTrimmed();
|
||||
|
||||
if (rawText.length() < 1 && !attachmentManager.isAttachmentPresent())
|
||||
throw new InvalidMessageException(getString(R.string.ConversationActivity_message_is_empty_exclamation));
|
||||
|
||||
return rawText;
|
||||
String result = composeText.getTextTrimmed();
|
||||
if (result.length() < 1 && !attachmentManager.isAttachmentPresent()) throw new InvalidMessageException();
|
||||
int shift = 0;
|
||||
for (Mention mention : mentions) {
|
||||
try {
|
||||
int startIndex = mention.getLocationInString() + shift;
|
||||
int endIndex = startIndex + mention.getDisplayName().length() + 1; // + 1 to include the @
|
||||
shift = shift + mention.getHexEncodedPublicKey().length() - mention.getDisplayName().length();
|
||||
result = result.substring(0, startIndex) + "@" + mention.getHexEncodedPublicKey() + result.substring(endIndex);
|
||||
} catch (Exception exception) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Pair<String, Optional<Slide>> getSplitMessage(String rawText, int maxPrimaryMessageSize) {
|
||||
@@ -2592,6 +2631,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private void silentlySetComposeText(String text) {
|
||||
typingTextWatcher.setEnabled(false);
|
||||
composeText.setText(text);
|
||||
if (text.isEmpty()) clearMentions();
|
||||
typingTextWatcher.setEnabled(true);
|
||||
}
|
||||
|
||||
@@ -2706,7 +2746,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private class TypingStatusTextWatcher extends SimpleTextWatcher {
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
@Override
|
||||
@@ -2721,6 +2760,55 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
|
||||
private class MentionTextWatcher extends SimpleTextWatcher {
|
||||
|
||||
@Override
|
||||
public void onTextChanged(String text) {
|
||||
boolean isBackspace = text.length() < oldText.length();
|
||||
if (isBackspace) {
|
||||
currentMentionStartIndex = -1;
|
||||
for (Mention mention : mentions) {
|
||||
boolean isValid;
|
||||
if (mention.getLocationInString() > (text.length() - 1)) {
|
||||
isValid = false;
|
||||
} else {
|
||||
isValid = text.substring(mention.getLocationInString()).startsWith("@" + mention.getDisplayName());
|
||||
}
|
||||
if (!isValid) {
|
||||
mentions.remove(mention);
|
||||
}
|
||||
}
|
||||
} else if (text.length() > 0) {
|
||||
if (currentMentionStartIndex > text.length()) {
|
||||
clearMentions(); // Should never occur
|
||||
}
|
||||
int currentEndIndex = text.length() - 1;
|
||||
char lastCharacter = text.charAt(currentEndIndex);
|
||||
LokiUserDatabase userDatabase = DatabaseFactory.getLokiUserDatabase(ConversationActivity.this);
|
||||
if (lastCharacter == '@') {
|
||||
List<Tuple2<String, String>> users = LokiAPI.Companion.getUsers("", threadId, userDatabase);
|
||||
currentMentionStartIndex = currentEndIndex;
|
||||
userSelectionView.show(users, threadId);
|
||||
} else if (Character.isWhitespace(lastCharacter)) {
|
||||
currentMentionStartIndex = -1;
|
||||
userSelectionView.hide();
|
||||
} else {
|
||||
if (currentMentionStartIndex != -1) {
|
||||
String query = text.substring(currentMentionStartIndex + 1); // + 1 to get rid of the @
|
||||
List<Tuple2<String, String>> users = LokiAPI.Companion.getUsers(query, threadId, userDatabase);
|
||||
userSelectionView.show(users, threadId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearMentions() {
|
||||
oldText = "";
|
||||
currentMentionStartIndex = -1;
|
||||
mentions.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThreadId(long threadId) {
|
||||
this.threadId = threadId;
|
||||
@@ -2747,11 +2835,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
inputPanel.setQuote(GlideApp.with(this),
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
body,
|
||||
slideDeck,
|
||||
recipient);
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
body,
|
||||
slideDeck,
|
||||
recipient);
|
||||
|
||||
} else if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getLinkPreviews().isEmpty()) {
|
||||
LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
|
||||
@@ -2762,18 +2850,18 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
inputPanel.setQuote(GlideApp.with(this),
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
messageRecord.getBody(),
|
||||
slideDeck,
|
||||
recipient);
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
messageRecord.getBody(),
|
||||
slideDeck,
|
||||
recipient);
|
||||
} else {
|
||||
inputPanel.setQuote(GlideApp.with(this),
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
messageRecord.getBody(),
|
||||
messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck(),
|
||||
recipient);
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
messageRecord.getBody(),
|
||||
messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck(),
|
||||
recipient);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.FriendRequestView;
|
||||
import org.thoughtcrime.securesms.loki.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.MentionUtilities;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
@@ -212,7 +213,7 @@ public class ConversationItem extends LinearLayout
|
||||
this.groupSenderProfileName = findViewById(R.id.group_message_sender_profile);
|
||||
this.alertView = findViewById(R.id.indicators_parent);
|
||||
this.contactPhoto = findViewById(R.id.contact_photo);
|
||||
this.moderatorIconImageView = findViewById(R.id.moderator_icon_image_view);
|
||||
this.moderatorIconImageView = findViewById(R.id.moderator_icon_image_view);
|
||||
this.contactPhotoHolder = findViewById(R.id.contact_photo_container);
|
||||
this.bodyBubble = findViewById(R.id.body_bubble);
|
||||
this.mediaThumbnailStub = new Stub<>(findViewById(R.id.image_view_stub));
|
||||
@@ -260,7 +261,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);
|
||||
@@ -466,17 +467,17 @@ 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));
|
||||
|
||||
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);
|
||||
} else { ;
|
||||
Spannable text = MentionUtilities.highlightMentions(linkifyMessageBody(messageRecord.getDisplayBody(context), batchSelected.isEmpty()), messageRecord.isOutgoing(), isGroupThread, context);
|
||||
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));
|
||||
@@ -484,7 +485,7 @@ public class ConversationItem extends LinearLayout
|
||||
bodyText.setOverflowText(null);
|
||||
}
|
||||
|
||||
bodyText.setText(styledText);
|
||||
bodyText.setText(text);
|
||||
bodyText.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
@@ -790,7 +791,8 @@ public class ConversationItem extends LinearLayout
|
||||
if (current.isMms() && !current.isMmsNotification() && ((MediaMmsMessageRecord)current).getQuote() != null) {
|
||||
Quote quote = ((MediaMmsMessageRecord)current).getQuote();
|
||||
//noinspection ConstantConditions
|
||||
quoteView.setQuote(glideRequests, quote.getId(), Recipient.from(context, quote.getAuthor(), true), quote.getText(), quote.isOriginalMissing(), quote.getAttachment(), conversationRecipient);
|
||||
String quoteBody = MentionUtilities.highlightMentions(quote.getText(), isGroupThread, context);
|
||||
quoteView.setQuote(glideRequests, quote.getId(), Recipient.from(context, quote.getAuthor(), true), quoteBody, quote.isOriginalMissing(), quote.getAttachment(), conversationRecipient);
|
||||
quoteView.setVisibility(View.VISIBLE);
|
||||
quoteView.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user