Search in sources :

Example 11 with Mention

use of org.thoughtcrime.securesms.database.model.Mention in project Signal-Android by WhisperSystems.

the class SearchRepository method queryMentions.

@NonNull
private List<MessageResult> queryMentions(@NonNull List<String> cleanQueries) {
    Set<RecipientId> recipientIds = new HashSet<>();
    for (String cleanQuery : cleanQueries) {
        for (Recipient recipient : recipientDatabase.queryRecipientsForMentions(cleanQuery)) {
            recipientIds.add(recipient.getId());
        }
    }
    Map<Long, List<Mention>> mentionQueryResults = mentionDatabase.getMentionsContainingRecipients(recipientIds, 500);
    if (mentionQueryResults.isEmpty()) {
        return Collections.emptyList();
    }
    List<MessageResult> results = new ArrayList<>();
    try (MessageDatabase.Reader reader = mmsDatabase.getMessages(mentionQueryResults.keySet())) {
        MessageRecord record;
        while ((record = reader.getNext()) != null) {
            List<Mention> mentions = mentionQueryResults.get(record.getId());
            if (Util.hasItems(mentions)) {
                MentionUtil.UpdatedBodyAndMentions updated = MentionUtil.updateBodyAndMentionsWithDisplayNames(context, record.getBody(), mentions);
                String updatedBody = updated.getBody() != null ? updated.getBody().toString() : record.getBody();
                String updatedSnippet = makeSnippet(cleanQueries, updatedBody);
                // noinspection ConstantConditions
                results.add(new MessageResult(threadDatabase.getRecipientForThreadId(record.getThreadId()), record.getRecipient(), updatedBody, updatedSnippet, record.getThreadId(), record.getId(), record.getDateReceived(), true));
            }
        }
    }
    return results;
}
Also used : MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) ArrayList(java.util.ArrayList) Recipient(org.thoughtcrime.securesms.recipients.Recipient) MentionUtil(org.thoughtcrime.securesms.database.MentionUtil) Mention(org.thoughtcrime.securesms.database.model.Mention) MessageRecord(org.thoughtcrime.securesms.database.model.MessageRecord) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) NonNull(androidx.annotation.NonNull)

Example 12 with Mention

use of org.thoughtcrime.securesms.database.model.Mention in project Signal-Android by signalapp.

the class ConversationParentFragment method sendMediaMessage.

private void sendMediaMessage(@NonNull MediaSendActivityResult result) {
    long thread = this.threadId;
    long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
    QuoteModel quote = result.isViewOnce() ? null : inputPanel.getQuote().orNull();
    List<Mention> mentions = new ArrayList<>(result.getMentions());
    OutgoingMediaMessage message = new OutgoingMediaMessage(recipient.get(), new SlideDeck(), result.getBody(), System.currentTimeMillis(), -1, expiresIn, result.isViewOnce(), distributionType, quote, Collections.emptyList(), Collections.emptyList(), mentions);
    OutgoingMediaMessage secureMessage = new OutgoingSecureMediaMessage(message);
    final Context context = requireContext().getApplicationContext();
    ApplicationDependencies.getTypingStatusSender().onTypingStopped(thread);
    inputPanel.clearQuote();
    attachmentManager.clear(glideRequests, false);
    silentlySetComposeText("");
    long id = fragment.stageOutgoingMessage(secureMessage);
    SimpleTask.run(() -> {
        long resultId = MessageSender.sendPushWithPreUploadedMedia(context, secureMessage, result.getPreUploadResults(), thread, null);
        int deleted = SignalDatabase.attachments().deleteAbandonedPreuploadedAttachments();
        Log.i(TAG, "Deleted " + deleted + " abandoned attachments.");
        return resultId;
    }, this::sendComplete);
}
Also used : Context(android.content.Context) OutgoingSecureMediaMessage(org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage) Mention(org.thoughtcrime.securesms.database.model.Mention) ArrayList(java.util.ArrayList) OutgoingMediaMessage(org.thoughtcrime.securesms.mms.OutgoingMediaMessage) SlideDeck(org.thoughtcrime.securesms.mms.SlideDeck) QuoteModel(org.thoughtcrime.securesms.mms.QuoteModel) SuppressLint(android.annotation.SuppressLint)

Example 13 with Mention

use of org.thoughtcrime.securesms.database.model.Mention in project Signal-Android by signalapp.

the class MmsDatabase method insertMediaMessage.

private long insertMediaMessage(long threadId, @Nullable String body, @NonNull List<Attachment> attachments, @NonNull List<Attachment> quoteAttachments, @NonNull List<Contact> sharedContacts, @NonNull List<LinkPreview> linkPreviews, @NonNull List<Mention> mentions, @Nullable BodyRangeList messageRanges, @NonNull ContentValues contentValues, @Nullable InsertListener insertListener, boolean updateThread) throws MmsException {
    SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
    AttachmentDatabase partsDatabase = SignalDatabase.attachments();
    MentionDatabase mentionDatabase = SignalDatabase.mentions();
    boolean mentionsSelf = Stream.of(mentions).filter(m -> Recipient.resolved(m.getRecipientId()).isSelf()).findFirst().isPresent();
    List<Attachment> allAttachments = new LinkedList<>();
    List<Attachment> contactAttachments = Stream.of(sharedContacts).map(Contact::getAvatarAttachment).filter(a -> a != null).toList();
    List<Attachment> previewAttachments = Stream.of(linkPreviews).filter(lp -> lp.getThumbnail().isPresent()).map(lp -> lp.getThumbnail().get()).toList();
    allAttachments.addAll(attachments);
    allAttachments.addAll(contactAttachments);
    allAttachments.addAll(previewAttachments);
    contentValues.put(BODY, body);
    contentValues.put(PART_COUNT, allAttachments.size());
    contentValues.put(MENTIONS_SELF, mentionsSelf ? 1 : 0);
    if (messageRanges != null) {
        contentValues.put(MESSAGE_RANGES, messageRanges.toByteArray());
    }
    db.beginTransaction();
    try {
        long messageId = db.insert(TABLE_NAME, null, contentValues);
        mentionDatabase.insert(threadId, messageId, mentions);
        Map<Attachment, AttachmentId> insertedAttachments = partsDatabase.insertAttachmentsForMessage(messageId, allAttachments, quoteAttachments);
        String serializedContacts = getSerializedSharedContacts(insertedAttachments, sharedContacts);
        String serializedPreviews = getSerializedLinkPreviews(insertedAttachments, linkPreviews);
        if (!TextUtils.isEmpty(serializedContacts)) {
            ContentValues contactValues = new ContentValues();
            contactValues.put(SHARED_CONTACTS, serializedContacts);
            SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();
            int rows = database.update(TABLE_NAME, contactValues, ID + " = ?", new String[] { String.valueOf(messageId) });
            if (rows <= 0) {
                Log.w(TAG, "Failed to update message with shared contact data.");
            }
        }
        if (!TextUtils.isEmpty(serializedPreviews)) {
            ContentValues contactValues = new ContentValues();
            contactValues.put(LINK_PREVIEWS, serializedPreviews);
            SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();
            int rows = database.update(TABLE_NAME, contactValues, ID + " = ?", new String[] { String.valueOf(messageId) });
            if (rows <= 0) {
                Log.w(TAG, "Failed to update message with link preview data.");
            }
        }
        db.setTransactionSuccessful();
        return messageId;
    } finally {
        db.endTransaction();
        if (insertListener != null) {
            insertListener.onComplete();
        }
        long contentValuesThreadId = contentValues.getAsLong(THREAD_ID);
        if (updateThread) {
            SignalDatabase.threads().setLastScrolled(contentValuesThreadId, 0);
            SignalDatabase.threads().update(threadId, true);
        }
    }
}
Also used : SignalStore(org.thoughtcrime.securesms.keyvalue.SignalStore) SlideDeck(org.thoughtcrime.securesms.mms.SlideDeck) GroupMigrationMembershipChange(org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange) LinkPreview(org.thoughtcrime.securesms.linkpreview.LinkPreview) NonNull(androidx.annotation.NonNull) Avatar(org.thoughtcrime.securesms.contactshare.Contact.Avatar) MessageGroupContext(org.thoughtcrime.securesms.mms.MessageGroupContext) Mention(org.thoughtcrime.securesms.database.model.Mention) MessageRecord(org.thoughtcrime.securesms.database.model.MessageRecord) SecureRandom(java.security.SecureRandom) JSONException(org.json.JSONException) JsonUtils(org.thoughtcrime.securesms.util.JsonUtils) JSONObject(org.json.JSONObject) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) BodyRangeList(org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList) SqlUtil(org.thoughtcrime.securesms.util.SqlUtil) IdentityKeyMismatchSet(org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchSet) Map(java.util.Map) ViewOnceUtil(org.thoughtcrime.securesms.revealable.ViewOnceUtil) Recipient(org.thoughtcrime.securesms.recipients.Recipient) OutgoingTextMessage(org.thoughtcrime.securesms.sms.OutgoingTextMessage) OutgoingGroupUpdateMessage(org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) NotificationInd(com.google.android.mms.pdu_alt.NotificationInd) ACI(org.whispersystems.signalservice.api.push.ACI) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) Collection(java.util.Collection) OutgoingSecureMediaMessage(org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage) Set(java.util.Set) UUID(java.util.UUID) OutgoingExpirationUpdateMessage(org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage) Log(org.signal.core.util.logging.Log) NetworkFailureSet(org.thoughtcrime.securesms.database.documents.NetworkFailureSet) List(java.util.List) Nullable(androidx.annotation.Nullable) ContentValues(android.content.ContentValues) IncomingTextMessage(org.thoughtcrime.securesms.sms.IncomingTextMessage) Attachment(org.thoughtcrime.securesms.attachments.Attachment) OutgoingMediaMessage(org.thoughtcrime.securesms.mms.OutgoingMediaMessage) MediaUtil(org.thoughtcrime.securesms.util.MediaUtil) Context(android.content.Context) Stream(com.annimon.stream.Stream) Util(org.thoughtcrime.securesms.util.Util) HashMap(java.util.HashMap) SQLiteStatement(net.zetetic.database.sqlcipher.SQLiteStatement) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) ArrayList(java.util.ArrayList) TextSecurePreferences(org.thoughtcrime.securesms.util.TextSecurePreferences) HashSet(java.util.HashSet) Pair(org.whispersystems.libsignal.util.Pair) MmsNotificationAttachment(org.thoughtcrime.securesms.attachments.MmsNotificationAttachment) NotificationMmsMessageRecord(org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord) QuoteModel(org.thoughtcrime.securesms.mms.QuoteModel) MediaMmsMessageRecord(org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord) LinkedList(java.util.LinkedList) PduHeaders(com.google.android.mms.pdu_alt.PduHeaders) Cursor(android.database.Cursor) MessageId(org.thoughtcrime.securesms.database.model.MessageId) Collectors(com.annimon.stream.Collectors) Contact(org.thoughtcrime.securesms.contactshare.Contact) IdentityKeyMismatch(org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch) MmsException(org.thoughtcrime.securesms.mms.MmsException) TextUtils(android.text.TextUtils) IOException(java.io.IOException) Quote(org.thoughtcrime.securesms.database.model.Quote) Optional(org.whispersystems.libsignal.util.guava.Optional) CursorUtil(org.thoughtcrime.securesms.util.CursorUtil) ViewOnceExpirationInfo(org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId) NetworkFailure(org.thoughtcrime.securesms.database.documents.NetworkFailure) TrimThreadJob(org.thoughtcrime.securesms.jobs.TrimThreadJob) SmsMessageRecord(org.thoughtcrime.securesms.database.model.SmsMessageRecord) Collections(java.util.Collections) JSONArray(org.json.JSONArray) IncomingMediaMessage(org.thoughtcrime.securesms.mms.IncomingMediaMessage) ContentValues(android.content.ContentValues) Attachment(org.thoughtcrime.securesms.attachments.Attachment) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) MmsNotificationAttachment(org.thoughtcrime.securesms.attachments.MmsNotificationAttachment) LinkedList(java.util.LinkedList) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId) Contact(org.thoughtcrime.securesms.contactshare.Contact)

Example 14 with Mention

use of org.thoughtcrime.securesms.database.model.Mention in project Signal-Android by signalapp.

the class MentionUtil method update.

@NonNull
private static UpdatedBodyAndMentions update(@Nullable CharSequence body, @NonNull List<Mention> mentions, @NonNull Function<Mention, CharSequence> replacementTextGenerator) {
    if (body == null || mentions.isEmpty()) {
        return new UpdatedBodyAndMentions(body, mentions);
    }
    SortedSet<Mention> sortedMentions = new TreeSet<>(mentions);
    SpannableStringBuilder updatedBody = new SpannableStringBuilder();
    List<Mention> updatedMentions = new ArrayList<>();
    int bodyIndex = 0;
    for (Mention mention : sortedMentions) {
        if (invalidMention(body, mention)) {
            continue;
        }
        updatedBody.append(body.subSequence(bodyIndex, mention.getStart()));
        CharSequence replaceWith = replacementTextGenerator.apply(mention);
        Mention updatedMention = new Mention(mention.getRecipientId(), updatedBody.length(), replaceWith.length());
        updatedBody.append(replaceWith);
        updatedMentions.add(updatedMention);
        bodyIndex = mention.getStart() + mention.getLength();
    }
    if (bodyIndex < body.length()) {
        updatedBody.append(body.subSequence(bodyIndex, body.length()));
    }
    return new UpdatedBodyAndMentions(updatedBody.toString(), updatedMentions);
}
Also used : TreeSet(java.util.TreeSet) Mention(org.thoughtcrime.securesms.database.model.Mention) ArrayList(java.util.ArrayList) SpannableStringBuilder(android.text.SpannableStringBuilder) NonNull(androidx.annotation.NonNull)

Example 15 with Mention

use of org.thoughtcrime.securesms.database.model.Mention in project Signal-Android by signalapp.

the class MentionDatabase method insert.

public void insert(long threadId, long messageId, @NonNull Collection<Mention> mentions) {
    SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
    db.beginTransaction();
    try {
        for (Mention mention : mentions) {
            ContentValues values = new ContentValues();
            values.put(THREAD_ID, threadId);
            values.put(MESSAGE_ID, messageId);
            values.put(RECIPIENT_ID, mention.getRecipientId().toLong());
            values.put(RANGE_START, mention.getStart());
            values.put(RANGE_LENGTH, mention.getLength());
            db.insert(TABLE_NAME, null, values);
        }
        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
    }
}
Also used : ContentValues(android.content.ContentValues) Mention(org.thoughtcrime.securesms.database.model.Mention)

Aggregations

Mention (org.thoughtcrime.securesms.database.model.Mention)32 NonNull (androidx.annotation.NonNull)20 ArrayList (java.util.ArrayList)20 LinkedList (java.util.LinkedList)14 List (java.util.List)14 Context (android.content.Context)12 Nullable (androidx.annotation.Nullable)12 MessageRecord (org.thoughtcrime.securesms.database.model.MessageRecord)12 QuoteModel (org.thoughtcrime.securesms.mms.QuoteModel)12 SlideDeck (org.thoughtcrime.securesms.mms.SlideDeck)12 Recipient (org.thoughtcrime.securesms.recipients.Recipient)12 OutgoingMediaMessage (org.thoughtcrime.securesms.mms.OutgoingMediaMessage)10 OutgoingSecureMediaMessage (org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage)10 RecipientId (org.thoughtcrime.securesms.recipients.RecipientId)10 Cursor (android.database.Cursor)8 Collectors (com.annimon.stream.Collectors)8 Stream (com.annimon.stream.Stream)8 IOException (java.io.IOException)8 SecureRandom (java.security.SecureRandom)8 Collections (java.util.Collections)8