Search in sources :

Example 1 with ReactionRecord

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

the class ConversationParentFragment method onCustomReactionSelected.

@Override
public void onCustomReactionSelected(@NonNull MessageRecord messageRecord, boolean hasAddedCustomEmoji) {
    ReactionRecord oldRecord = Stream.of(messageRecord.getReactions()).filter(record -> record.getAuthor().equals(Recipient.self().getId())).findFirst().orElse(null);
    if (oldRecord != null && hasAddedCustomEmoji) {
        final Context context = requireContext().getApplicationContext();
        reactionDelegate.hide();
        SignalExecutors.BOUNDED.execute(() -> MessageSender.sendReactionRemoval(context, new MessageId(messageRecord.getId(), messageRecord.isMms()), oldRecord));
    } else {
        reactionDelegate.hideForReactWithAny();
        ReactWithAnyEmojiBottomSheetDialogFragment.createForMessageRecord(messageRecord, reactWithAnyEmojiStartPage).show(getChildFragmentManager(), "BOTTOM");
    }
}
Also used : Context(android.content.Context) ReactionRecord(org.thoughtcrime.securesms.database.model.ReactionRecord) MessageId(org.thoughtcrime.securesms.database.model.MessageId)

Example 2 with ReactionRecord

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

the class ConversationDataSource method load.

@Override
@Nullable
public ConversationMessage load(@NonNull MessageId messageId) {
    Stopwatch stopwatch = new Stopwatch("load(" + messageId + "), thread " + threadId);
    MessageDatabase database = messageId.isMms() ? SignalDatabase.mms() : SignalDatabase.sms();
    MessageRecord record = database.getMessageRecordOrNull(messageId.getId());
    stopwatch.split("message");
    try {
        if (record != null) {
            List<Mention> mentions;
            if (messageId.isMms()) {
                mentions = SignalDatabase.mentions().getMentionsForMessage(messageId.getId());
            } else {
                mentions = Collections.emptyList();
            }
            stopwatch.split("mentions");
            List<ReactionRecord> reactions = SignalDatabase.reactions().getReactions(messageId);
            record = ReactionHelper.recordWithReactions(record, reactions);
            stopwatch.split("reactions");
            if (messageId.isMms()) {
                List<DatabaseAttachment> attachments = SignalDatabase.attachments().getAttachmentsForMessage(messageId.getId());
                if (attachments.size() > 0) {
                    record = ((MediaMmsMessageRecord) record).withAttachments(context, attachments);
                }
            }
            stopwatch.split("attachments");
            return ConversationMessage.ConversationMessageFactory.createWithUnresolvedData(ApplicationDependencies.getApplication(), record, mentions);
        } else {
            return null;
        }
    } finally {
        stopwatch.stop(TAG);
    }
}
Also used : MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) Mention(org.thoughtcrime.securesms.database.model.Mention) Stopwatch(org.thoughtcrime.securesms.util.Stopwatch) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) MessageRecord(org.thoughtcrime.securesms.database.model.MessageRecord) MediaMmsMessageRecord(org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord) InMemoryMessageRecord(org.thoughtcrime.securesms.database.model.InMemoryMessageRecord) SmsMessageRecord(org.thoughtcrime.securesms.database.model.SmsMessageRecord) ReactionRecord(org.thoughtcrime.securesms.database.model.ReactionRecord) Nullable(androidx.annotation.Nullable)

Example 3 with ReactionRecord

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

the class ConversationFragment method postMarkAsReadRequest.

private void postMarkAsReadRequest() {
    if (getListAdapter().hasNoConversationMessages()) {
        return;
    }
    int position = getListLayoutManager().findFirstVisibleItemPosition();
    if (position == getListAdapter().getItemCount() - 1) {
        return;
    }
    if (position >= (isTypingIndicatorShowing() ? 1 : 0)) {
        ConversationMessage item = getListAdapter().getItem(position);
        if (item != null) {
            MessageRecord record = item.getMessageRecord();
            long latestReactionReceived = Stream.of(record.getReactions()).map(ReactionRecord::getDateReceived).max(Long::compareTo).orElse(0L);
            markReadHelper.onViewsRevealed(Math.max(record.getDateReceived(), latestReactionReceived));
        }
    }
}
Also used : MmsMessageRecord(org.thoughtcrime.securesms.database.model.MmsMessageRecord) MediaMmsMessageRecord(org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord) MessageRecord(org.thoughtcrime.securesms.database.model.MessageRecord) InMemoryMessageRecord(org.thoughtcrime.securesms.database.model.InMemoryMessageRecord) ReactionRecord(org.thoughtcrime.securesms.database.model.ReactionRecord) SuppressLint(android.annotation.SuppressLint)

Example 4 with ReactionRecord

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

the class MessageContentProcessor method handleReaction.

@Nullable
private MessageId handleReaction(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message, @NonNull Recipient senderRecipient) {
    log(content.getTimestamp(), "Handle reaction for message " + message.getReaction().get().getTargetSentTimestamp());
    SignalServiceDataMessage.Reaction reaction = message.getReaction().get();
    if (!EmojiUtil.isEmoji(reaction.getEmoji())) {
        Log.w(TAG, "Reaction text is not a valid emoji! Ignoring the message.");
        return null;
    }
    Recipient targetAuthor = Recipient.externalPush(reaction.getTargetAuthor());
    MessageRecord targetMessage = SignalDatabase.mmsSms().getMessageFor(reaction.getTargetSentTimestamp(), targetAuthor.getId());
    if (targetMessage == null) {
        warn(String.valueOf(content.getTimestamp()), "[handleReaction] Could not find matching message! Putting it in the early message cache. timestamp: " + reaction.getTargetSentTimestamp() + "  author: " + targetAuthor.getId());
        ApplicationDependencies.getEarlyMessageCache().store(targetAuthor.getId(), reaction.getTargetSentTimestamp(), content);
        return null;
    }
    if (targetMessage.isRemoteDelete()) {
        warn(String.valueOf(content.getTimestamp()), "[handleReaction] Found a matching message, but it's flagged as remotely deleted. timestamp: " + reaction.getTargetSentTimestamp() + "  author: " + targetAuthor.getId());
        return null;
    }
    ThreadRecord targetThread = SignalDatabase.threads().getThreadRecord(targetMessage.getThreadId());
    if (targetThread == null) {
        warn(String.valueOf(content.getTimestamp()), "[handleReaction] Could not find a thread for the message! timestamp: " + reaction.getTargetSentTimestamp() + "  author: " + targetAuthor.getId());
        return null;
    }
    Recipient threadRecipient = targetThread.getRecipient().resolve();
    if (threadRecipient.isGroup() && !threadRecipient.getParticipants().contains(senderRecipient)) {
        warn(String.valueOf(content.getTimestamp()), "[handleReaction] Reaction author is not in the group! timestamp: " + reaction.getTargetSentTimestamp() + "  author: " + targetAuthor.getId());
        return null;
    }
    if (!threadRecipient.isGroup() && !senderRecipient.equals(threadRecipient) && !senderRecipient.isSelf()) {
        warn(String.valueOf(content.getTimestamp()), "[handleReaction] Reaction author is not a part of the 1:1 thread! timestamp: " + reaction.getTargetSentTimestamp() + "  author: " + targetAuthor.getId());
        return null;
    }
    MessageId targetMessageId = new MessageId(targetMessage.getId(), targetMessage.isMms());
    if (reaction.isRemove()) {
        SignalDatabase.reactions().deleteReaction(targetMessageId, senderRecipient.getId());
        ApplicationDependencies.getMessageNotifier().updateNotification(context);
    } else {
        ReactionRecord reactionRecord = new ReactionRecord(reaction.getEmoji(), senderRecipient.getId(), message.getTimestamp(), System.currentTimeMillis());
        SignalDatabase.reactions().addReaction(targetMessageId, reactionRecord);
        ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
    }
    return new MessageId(targetMessage.getId(), targetMessage.isMms());
}
Also used : SignalServiceDataMessage(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage) ThreadRecord(org.thoughtcrime.securesms.database.model.ThreadRecord) MmsMessageRecord(org.thoughtcrime.securesms.database.model.MmsMessageRecord) MessageRecord(org.thoughtcrime.securesms.database.model.MessageRecord) Recipient(org.thoughtcrime.securesms.recipients.Recipient) ReactionRecord(org.thoughtcrime.securesms.database.model.ReactionRecord) MessageId(org.thoughtcrime.securesms.database.model.MessageId) SyncMessageId(org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId) Nullable(androidx.annotation.Nullable)

Example 5 with ReactionRecord

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

the class ReactionsConversationView method buildSortedReactionsList.

@NonNull
private static List<Reaction> buildSortedReactionsList(@NonNull List<ReactionRecord> records) {
    Map<String, Reaction> counters = new LinkedHashMap<>();
    RecipientId selfId = Recipient.self().getId();
    for (ReactionRecord record : records) {
        String baseEmoji = EmojiUtil.getCanonicalRepresentation(record.getEmoji());
        Reaction info = counters.get(baseEmoji);
        if (info == null) {
            info = new Reaction(baseEmoji, record.getEmoji(), 1, record.getDateReceived(), selfId.equals(record.getAuthor()));
        } else {
            info.update(record.getEmoji(), record.getDateReceived(), selfId.equals(record.getAuthor()));
        }
        counters.put(baseEmoji, info);
    }
    List<Reaction> reactions = new ArrayList<>(counters.values());
    Collections.sort(reactions, Collections.reverseOrder());
    if (reactions.size() > 3) {
        List<Reaction> shortened = new ArrayList<>(3);
        shortened.add(reactions.get(0));
        shortened.add(reactions.get(1));
        shortened.add(Stream.of(reactions).skip(2).reduce(new Reaction(null, null, 0, 0, false), Reaction::merge));
        return shortened;
    } else {
        return reactions;
    }
}
Also used : RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) ArrayList(java.util.ArrayList) ReactionRecord(org.thoughtcrime.securesms.database.model.ReactionRecord) LinkedHashMap(java.util.LinkedHashMap) NonNull(androidx.annotation.NonNull)

Aggregations

ReactionRecord (org.thoughtcrime.securesms.database.model.ReactionRecord)8 MessageId (org.thoughtcrime.securesms.database.model.MessageId)3 MessageRecord (org.thoughtcrime.securesms.database.model.MessageRecord)3 Context (android.content.Context)2 Nullable (androidx.annotation.Nullable)2 InMemoryMessageRecord (org.thoughtcrime.securesms.database.model.InMemoryMessageRecord)2 MediaMmsMessageRecord (org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord)2 MmsMessageRecord (org.thoughtcrime.securesms.database.model.MmsMessageRecord)2 SuppressLint (android.annotation.SuppressLint)1 NonNull (androidx.annotation.NonNull)1 ArrayList (java.util.ArrayList)1 LinkedHashMap (java.util.LinkedHashMap)1 DatabaseAttachment (org.thoughtcrime.securesms.attachments.DatabaseAttachment)1 MessageDatabase (org.thoughtcrime.securesms.database.MessageDatabase)1 SyncMessageId (org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId)1 NoSuchMessageException (org.thoughtcrime.securesms.database.NoSuchMessageException)1 Mention (org.thoughtcrime.securesms.database.model.Mention)1 SmsMessageRecord (org.thoughtcrime.securesms.database.model.SmsMessageRecord)1 ThreadRecord (org.thoughtcrime.securesms.database.model.ThreadRecord)1 Recipient (org.thoughtcrime.securesms.recipients.Recipient)1