diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/mutiselect/forward/MultiselectForwardFragmentArgs.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/mutiselect/forward/MultiselectForwardFragmentArgs.kt index eaa56ceb28..128b1bdcb3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/mutiselect/forward/MultiselectForwardFragmentArgs.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/mutiselect/forward/MultiselectForwardFragmentArgs.kt @@ -42,7 +42,7 @@ class MultiselectForwardFragmentArgs( @WorkerThread private fun buildMultiShareArgs(context: Context, conversationMessage: ConversationMessage, selectedParts: Set): MultiShareArgs { - val builder = MultiShareArgs.Builder(setOf()) + val builder = MultiShareArgs.Builder(setOf()).withMentions(conversationMessage.mentions) if (conversationMessage.multiselectCollection.isTextSelected(selectedParts)) { val mediaMessage: MmsMessageRecord? = conversationMessage.messageRecord as? MmsMessageRecord diff --git a/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareArgs.java b/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareArgs.java index 9c38457aa2..4b30767a7b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareArgs.java +++ b/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareArgs.java @@ -10,6 +10,7 @@ import androidx.annotation.Nullable; import com.annimon.stream.Stream; +import org.thoughtcrime.securesms.database.model.Mention; import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.mediasend.Media; import org.thoughtcrime.securesms.stickers.StickerLocator; @@ -33,6 +34,7 @@ public final class MultiShareArgs implements Parcelable { private final String dataType; private final boolean viewOnce; private final LinkPreview linkPreview; + private final List mentions; private MultiShareArgs(@NonNull Builder builder) { shareContactAndThreads = builder.shareContactAndThreads; @@ -44,6 +46,7 @@ public final class MultiShareArgs implements Parcelable { dataType = builder.dataType; viewOnce = builder.viewOnce; linkPreview = builder.linkPreview; + mentions = builder.mentions == null ? new ArrayList<>() : new ArrayList<>(builder.mentions); } protected MultiShareArgs(Parcel in) { @@ -55,6 +58,7 @@ public final class MultiShareArgs implements Parcelable { dataUri = in.readParcelable(Uri.class.getClassLoader()); dataType = in.readString(); viewOnce = in.readByte() != 0; + mentions = in.createTypedArrayList(Mention.CREATOR); String linkedPreviewString = in.readString(); LinkPreview preview; @@ -103,6 +107,10 @@ public final class MultiShareArgs implements Parcelable { return linkPreview; } + public @NonNull List getMentions() { + return mentions; + } + public @NonNull InterstitialContentType getInterstitialContentType() { if (!requiresInterstitial()) { return InterstitialContentType.NONE; @@ -145,6 +153,7 @@ public final class MultiShareArgs implements Parcelable { dest.writeParcelable(dataUri, flags); dest.writeString(dataType); dest.writeByte((byte) (viewOnce ? 1 : 0)); + dest.writeTypedList(mentions); if (linkPreview != null) { try { @@ -169,7 +178,8 @@ public final class MultiShareArgs implements Parcelable { .withDraftText(draftText) .withLinkPreview(linkPreview) .withMedia(media) - .withStickerLocator(stickerLocator); + .withStickerLocator(stickerLocator) + .withMentions(mentions); } private boolean requiresInterstitial() { @@ -189,6 +199,7 @@ public final class MultiShareArgs implements Parcelable { private String dataType; private LinkPreview linkPreview; private boolean viewOnce; + private List mentions; public Builder(@NonNull Set shareContactAndThreads) { this.shareContactAndThreads = shareContactAndThreads; @@ -234,6 +245,11 @@ public final class MultiShareArgs implements Parcelable { return this; } + public @NonNull Builder withMentions(@Nullable List mentions) { + this.mentions = mentions != null ? new ArrayList<>(mentions) : null; + return this; + } + public @NonNull MultiShareArgs build() { return new MultiShareArgs(this); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareSender.java b/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareSender.java index 2fb898a3a1..b6d8b19e01 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareSender.java +++ b/app/src/main/java/org/thoughtcrime/securesms/sharing/MultiShareSender.java @@ -15,6 +15,7 @@ import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.TransportOption; import org.thoughtcrime.securesms.TransportOptions; import org.thoughtcrime.securesms.database.ThreadDatabase; +import org.thoughtcrime.securesms.database.model.Mention; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.mediasend.Media; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; @@ -22,6 +23,7 @@ import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.mms.SlideFactory; import org.thoughtcrime.securesms.mms.StickerSlide; import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.util.MessageUtil; @@ -33,6 +35,7 @@ import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; /** * MultiShareSender encapsulates send logic (stolen from {@link org.thoughtcrime.securesms.conversation.ConversationActivity} @@ -65,6 +68,7 @@ public final class MultiShareSender { for (ShareContactAndThread shareContactAndThread : multiShareArgs.getShareContactAndThreads()) { Recipient recipient = Recipient.resolved(shareContactAndThread.getRecipientId()); + List mentions = getValidMentionsForRecipient(recipient, multiShareArgs.getMentions()); TransportOption transport = resolveTransportOption(context, recipient); boolean forceSms = recipient.isForceSmsSelection() && transport.isSms(); int subscriptionId = transport.getSimSubscriptionId().or(-1); @@ -78,12 +82,13 @@ public final class MultiShareSender { multiShareArgs.getLinkPreview() != null || recipient.isGroup() || recipient.getEmail().isPresent() || + !mentions.isEmpty() || needsSplit; if ((recipient.isMmsGroup() || recipient.getEmail().isPresent()) && !isMmsEnabled) { results.add(new MultiShareSendResult(shareContactAndThread, MultiShareSendResult.Type.MMS_NOT_ENABLED)); } else if (isMediaMessage) { - sendMediaMessage(context, multiShareArgs, recipient, slideDeck, transport, shareContactAndThread.getThreadId(), forceSms, expiresIn, multiShareArgs.isViewOnce(), subscriptionId); + sendMediaMessage(context, multiShareArgs, recipient, slideDeck, transport, shareContactAndThread.getThreadId(), forceSms, expiresIn, multiShareArgs.isViewOnce(), subscriptionId, mentions); results.add(new MultiShareSendResult(shareContactAndThread, MultiShareSendResult.Type.SUCCESS)); } else { sendTextMessage(context, multiShareArgs, recipient, shareContactAndThread.getThreadId() ,forceSms, expiresIn, subscriptionId); @@ -132,7 +137,8 @@ public final class MultiShareSender { boolean forceSms, long expiresIn, boolean isViewOnce, - int subscriptionId) + int subscriptionId, + @NonNull List validatedMentions) { String body = multiShareArgs.getDraftText(); if (transportOption.isType(TransportOption.Type.TEXTSECURE) && !forceSms && body != null) { @@ -156,7 +162,7 @@ public final class MultiShareSender { Collections.emptyList(), multiShareArgs.getLinkPreview() != null ? Collections.singletonList(multiShareArgs.getLinkPreview()) : Collections.emptyList(), - Collections.emptyList()); + validatedMentions); MessageSender.send(context, outgoingMediaMessage, threadId, forceSms, null); } @@ -189,6 +195,21 @@ public final class MultiShareSender { return slideDeck; } + private static @NonNull List getValidMentionsForRecipient(@NonNull Recipient recipient, @NonNull List mentions) { + if (mentions.isEmpty() || !recipient.isPushV2Group() || !recipient.isActiveGroup()) { + return Collections.emptyList(); + } else { + Set validRecipientIds = recipient.getParticipants() + .stream() + .map(Recipient::getId) + .collect(Collectors.toSet()); + + return mentions.stream() + .filter(mention -> validRecipientIds.contains(mention.getRecipientId())) + .collect(Collectors.toList()); + } + } + public static final class MultiShareSendResultCollection { private final List results;