Merge branch 'dev' into custom-server

# Conflicts:
#	src/org/thoughtcrime/securesms/loki/DisplayNameActivity.kt
This commit is contained in:
Mikunj
2019-10-11 15:40:09 +11:00
25 changed files with 469 additions and 91 deletions

View File

@@ -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);
}
}

View File

@@ -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;