mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 04:28:35 +00:00
Allow forwarding of contacts.
This commit is contained in:
@@ -135,7 +135,6 @@ final class MenuState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean shouldShowForwardAction = !actionMessage &&
|
boolean shouldShowForwardAction = !actionMessage &&
|
||||||
!sharedContact &&
|
|
||||||
!viewOnce &&
|
!viewOnce &&
|
||||||
!remoteDelete &&
|
!remoteDelete &&
|
||||||
!hasPendingMedia &&
|
!hasPendingMedia &&
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.mms.PartAuthority
|
|||||||
import org.thoughtcrime.securesms.sharing.MultiShareArgs
|
import org.thoughtcrime.securesms.sharing.MultiShareArgs
|
||||||
import org.thoughtcrime.securesms.stories.Stories
|
import org.thoughtcrime.securesms.stories.Stories
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil
|
import org.thoughtcrime.securesms.util.MediaUtil
|
||||||
|
import org.thoughtcrime.securesms.util.hasSharedContact
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
|
|
||||||
@@ -136,6 +137,10 @@ data class MultiselectForwardFragmentArgs @JvmOverloads constructor(
|
|||||||
builder.asTextStory(mediaMessage?.storyType?.isTextStory ?: false)
|
builder.asTextStory(mediaMessage?.storyType?.isTextStory ?: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conversationMessage.messageRecord.hasSharedContact() && conversationMessage.multiselectCollection.isMediaSelected(selectedParts)) {
|
||||||
|
builder.withSharedContacts((conversationMessage.messageRecord as MmsMessageRecord).sharedContacts)
|
||||||
|
}
|
||||||
|
|
||||||
if (conversationMessage.messageRecord.isMms && conversationMessage.multiselectCollection.isMediaSelected(selectedParts)) {
|
if (conversationMessage.messageRecord.isMms && conversationMessage.multiselectCollection.isMediaSelected(selectedParts)) {
|
||||||
val mediaMessage: MmsMessageRecord = conversationMessage.messageRecord as MmsMessageRecord
|
val mediaMessage: MmsMessageRecord = conversationMessage.messageRecord as MmsMessageRecord
|
||||||
val isAlbum = mediaMessage.containsMediaSlide() &&
|
val isAlbum = mediaMessage.containsMediaSlide() &&
|
||||||
|
|||||||
@@ -2647,7 +2647,8 @@ public class MessageContentProcessor {
|
|||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
true,
|
true,
|
||||||
bodyRanges);
|
bodyRanges,
|
||||||
|
Collections.emptyList());
|
||||||
|
|
||||||
messageId = SignalDatabase.messages().insertMessageOutbox(outgoingMessage, threadId, false, GroupReceiptTable.STATUS_UNKNOWN, null);
|
messageId = SignalDatabase.messages().insertMessageOutbox(outgoingMessage, threadId, false, GroupReceiptTable.STATUS_UNKNOWN, null);
|
||||||
database = SignalDatabase.messages();
|
database = SignalDatabase.messages();
|
||||||
|
|||||||
@@ -120,7 +120,8 @@ data class OutgoingMessage(
|
|||||||
linkPreviews: List<LinkPreview> = emptyList(),
|
linkPreviews: List<LinkPreview> = emptyList(),
|
||||||
mentions: List<Mention> = emptyList(),
|
mentions: List<Mention> = emptyList(),
|
||||||
isSecure: Boolean = false,
|
isSecure: Boolean = false,
|
||||||
bodyRanges: BodyRangeList? = null
|
bodyRanges: BodyRangeList? = null,
|
||||||
|
contacts: List<Contact> = emptyList()
|
||||||
) : this(
|
) : this(
|
||||||
recipient = recipient,
|
recipient = recipient,
|
||||||
body = buildMessage(slideDeck, body ?: ""),
|
body = buildMessage(slideDeck, body ?: ""),
|
||||||
@@ -133,7 +134,8 @@ data class OutgoingMessage(
|
|||||||
linkPreviews = linkPreviews,
|
linkPreviews = linkPreviews,
|
||||||
mentions = mentions,
|
mentions = mentions,
|
||||||
isSecure = isSecure,
|
isSecure = isSecure,
|
||||||
bodyRanges = bodyRanges
|
bodyRanges = bodyRanges,
|
||||||
|
sharedContacts = contacts
|
||||||
)
|
)
|
||||||
|
|
||||||
fun withExpiry(expiresIn: Long): OutgoingMessage {
|
fun withExpiry(expiresIn: Long): OutgoingMessage {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
|||||||
import org.signal.core.util.BreakIteratorCompat;
|
import org.signal.core.util.BreakIteratorCompat;
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey;
|
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey;
|
||||||
|
import org.thoughtcrime.securesms.contactshare.Contact;
|
||||||
import org.thoughtcrime.securesms.database.model.Mention;
|
import org.thoughtcrime.securesms.database.model.Mention;
|
||||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
|
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||||
@@ -23,6 +24,7 @@ import org.thoughtcrime.securesms.stories.Stories;
|
|||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.thoughtcrime.securesms.util.ParcelUtil;
|
import org.thoughtcrime.securesms.util.ParcelUtil;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -50,6 +52,7 @@ public final class MultiShareArgs implements Parcelable {
|
|||||||
private final long expiresAt;
|
private final long expiresAt;
|
||||||
private final boolean isTextStory;
|
private final boolean isTextStory;
|
||||||
private final BodyRangeList bodyRanges;
|
private final BodyRangeList bodyRanges;
|
||||||
|
private final List<Contact> sharedContacts;
|
||||||
|
|
||||||
private MultiShareArgs(@NonNull Builder builder) {
|
private MultiShareArgs(@NonNull Builder builder) {
|
||||||
contactSearchKeys = builder.contactSearchKeys;
|
contactSearchKeys = builder.contactSearchKeys;
|
||||||
@@ -66,6 +69,7 @@ public final class MultiShareArgs implements Parcelable {
|
|||||||
expiresAt = builder.expiresAt;
|
expiresAt = builder.expiresAt;
|
||||||
isTextStory = builder.isTextStory;
|
isTextStory = builder.isTextStory;
|
||||||
bodyRanges = builder.bodyRanges;
|
bodyRanges = builder.bodyRanges;
|
||||||
|
sharedContacts = builder.sharedContacts == null ? new ArrayList<>() : new ArrayList<>(builder.sharedContacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MultiShareArgs(Parcel in) {
|
protected MultiShareArgs(Parcel in) {
|
||||||
@@ -104,6 +108,7 @@ public final class MultiShareArgs implements Parcelable {
|
|||||||
Log.w(TAG, "Invalid body range", e);
|
Log.w(TAG, "Invalid body range", e);
|
||||||
}
|
}
|
||||||
this.bodyRanges = bodyRanges;
|
this.bodyRanges = bodyRanges;
|
||||||
|
sharedContacts = in.createTypedArrayList(Contact.CREATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ContactSearchKey> getContactSearchKeys() {
|
public Set<ContactSearchKey> getContactSearchKeys() {
|
||||||
@@ -169,6 +174,10 @@ public final class MultiShareArgs implements Parcelable {
|
|||||||
return bodyRanges;
|
return bodyRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NonNull List<Contact> getSharedContacts() {
|
||||||
|
return sharedContacts;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isValidForStories() {
|
public boolean isValidForStories() {
|
||||||
if (isViewOnce()) {
|
if (isViewOnce()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -269,6 +278,8 @@ public final class MultiShareArgs implements Parcelable {
|
|||||||
} else {
|
} else {
|
||||||
ParcelUtil.writeByteArray(dest, null);
|
ParcelUtil.writeByteArray(dest, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dest.writeTypedList(sharedContacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder buildUpon() {
|
public Builder buildUpon() {
|
||||||
@@ -288,7 +299,8 @@ public final class MultiShareArgs implements Parcelable {
|
|||||||
.withTimestamp(timestamp)
|
.withTimestamp(timestamp)
|
||||||
.withExpiration(expiresAt)
|
.withExpiration(expiresAt)
|
||||||
.asTextStory(isTextStory)
|
.asTextStory(isTextStory)
|
||||||
.withBodyRanges(bodyRanges);
|
.withBodyRanges(bodyRanges)
|
||||||
|
.withSharedContacts(sharedContacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean requiresInterstitial() {
|
private boolean requiresInterstitial() {
|
||||||
@@ -303,19 +315,20 @@ public final class MultiShareArgs implements Parcelable {
|
|||||||
|
|
||||||
private final Set<ContactSearchKey> contactSearchKeys;
|
private final Set<ContactSearchKey> contactSearchKeys;
|
||||||
|
|
||||||
private List<Media> media;
|
private List<Media> media;
|
||||||
private String draftText;
|
private String draftText;
|
||||||
private StickerLocator stickerLocator;
|
private StickerLocator stickerLocator;
|
||||||
private boolean borderless;
|
private boolean borderless;
|
||||||
private Uri dataUri;
|
private Uri dataUri;
|
||||||
private String dataType;
|
private String dataType;
|
||||||
private LinkPreview linkPreview;
|
private LinkPreview linkPreview;
|
||||||
private boolean viewOnce;
|
private boolean viewOnce;
|
||||||
private List<Mention> mentions;
|
private List<Mention> mentions;
|
||||||
private long timestamp;
|
private long timestamp;
|
||||||
private long expiresAt;
|
private long expiresAt;
|
||||||
private boolean isTextStory;
|
private boolean isTextStory;
|
||||||
private BodyRangeList bodyRanges;
|
private BodyRangeList bodyRanges;
|
||||||
|
private List<Contact> sharedContacts;
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
this(Collections.emptySet());
|
this(Collections.emptySet());
|
||||||
@@ -390,6 +403,11 @@ public final class MultiShareArgs implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NonNull Builder withSharedContacts(List<Contact> sharedContacts) {
|
||||||
|
this.sharedContacts = new ArrayList<>(sharedContacts);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public @NonNull MultiShareArgs build() {
|
public @NonNull MultiShareArgs build() {
|
||||||
return new MultiShareArgs(this);
|
return new MultiShareArgs(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import org.signal.core.util.logging.Log;
|
|||||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||||
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
||||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey;
|
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey;
|
||||||
|
import org.thoughtcrime.securesms.contactshare.Contact;
|
||||||
import org.thoughtcrime.securesms.conversation.MessageSendType;
|
import org.thoughtcrime.securesms.conversation.MessageSendType;
|
||||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentTable;
|
import org.thoughtcrime.securesms.database.AttachmentTable;
|
||||||
@@ -111,6 +112,7 @@ public final class MultiShareSender {
|
|||||||
boolean forceSms = recipient.isForceSmsSelection() && sendType.usesSmsTransport();
|
boolean forceSms = recipient.isForceSmsSelection() && sendType.usesSmsTransport();
|
||||||
int subscriptionId = sendType.getSimSubscriptionIdOr(-1);
|
int subscriptionId = sendType.getSimSubscriptionIdOr(-1);
|
||||||
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.getExpiresInSeconds());
|
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.getExpiresInSeconds());
|
||||||
|
List<Contact> contacts = multiShareArgs.getSharedContacts();
|
||||||
boolean needsSplit = !sendType.usesSmsTransport() &&
|
boolean needsSplit = !sendType.usesSmsTransport() &&
|
||||||
message != null &&
|
message != null &&
|
||||||
message.length() > sendType.calculateCharacters(message).maxPrimaryMessageSize;
|
message.length() > sendType.calculateCharacters(message).maxPrimaryMessageSize;
|
||||||
@@ -122,7 +124,8 @@ public final class MultiShareSender {
|
|||||||
boolean hasPushMedia = hasMmsMedia ||
|
boolean hasPushMedia = hasMmsMedia ||
|
||||||
multiShareArgs.getLinkPreview() != null ||
|
multiShareArgs.getLinkPreview() != null ||
|
||||||
!mentions.isEmpty() ||
|
!mentions.isEmpty() ||
|
||||||
needsSplit;
|
needsSplit ||
|
||||||
|
!contacts.isEmpty();
|
||||||
|
|
||||||
MultiShareTimestampProvider sentTimestamp = recipient.isDistributionList() ? distributionListSentTimestamps : MultiShareTimestampProvider.create();
|
MultiShareTimestampProvider sentTimestamp = recipient.isDistributionList() ? distributionListSentTimestamps : MultiShareTimestampProvider.create();
|
||||||
boolean canSendAsTextStory = recipientSearchKey.isStory() && multiShareArgs.isValidForTextStoryGeneration();
|
boolean canSendAsTextStory = recipientSearchKey.isStory() && multiShareArgs.isValidForTextStoryGeneration();
|
||||||
@@ -145,7 +148,8 @@ public final class MultiShareSender {
|
|||||||
sentTimestamp,
|
sentTimestamp,
|
||||||
canSendAsTextStory,
|
canSendAsTextStory,
|
||||||
storiesBatch,
|
storiesBatch,
|
||||||
generatedTextStoryBackgroundColor);
|
generatedTextStoryBackgroundColor,
|
||||||
|
contacts);
|
||||||
results.add(new MultiShareSendResult(recipientSearchKey, MultiShareSendResult.Type.SUCCESS));
|
results.add(new MultiShareSendResult(recipientSearchKey, MultiShareSendResult.Type.SUCCESS));
|
||||||
} else if (recipientSearchKey.isStory()) {
|
} else if (recipientSearchKey.isStory()) {
|
||||||
results.add(new MultiShareSendResult(recipientSearchKey, MultiShareSendResult.Type.INVALID_SHARE_TO_STORY));
|
results.add(new MultiShareSendResult(recipientSearchKey, MultiShareSendResult.Type.INVALID_SHARE_TO_STORY));
|
||||||
@@ -213,7 +217,8 @@ public final class MultiShareSender {
|
|||||||
@NonNull MultiShareTimestampProvider sentTimestamps,
|
@NonNull MultiShareTimestampProvider sentTimestamps,
|
||||||
boolean canSendAsTextStory,
|
boolean canSendAsTextStory,
|
||||||
@NonNull List<OutgoingMessage> storiesToBatchSend,
|
@NonNull List<OutgoingMessage> storiesToBatchSend,
|
||||||
@NonNull ChatColors generatedTextStoryBackgroundColor)
|
@NonNull ChatColors generatedTextStoryBackgroundColor,
|
||||||
|
@NonNull List<Contact> contacts)
|
||||||
{
|
{
|
||||||
String body = multiShareArgs.getDraftText();
|
String body = multiShareArgs.getDraftText();
|
||||||
if (sendType.usesSignalTransport() && !forceSms && body != null) {
|
if (sendType.usesSignalTransport() && !forceSms && body != null) {
|
||||||
@@ -251,7 +256,8 @@ public final class MultiShareSender {
|
|||||||
buildLinkPreviews(context, multiShareArgs.getLinkPreview()),
|
buildLinkPreviews(context, multiShareArgs.getLinkPreview()),
|
||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
false,
|
false,
|
||||||
multiShareArgs.getBodyRanges());
|
multiShareArgs.getBodyRanges(),
|
||||||
|
contacts);
|
||||||
|
|
||||||
outgoingMessages.add(outgoingMessage);
|
outgoingMessages.add(outgoingMessage);
|
||||||
} else if (canSendAsTextStory) {
|
} else if (canSendAsTextStory) {
|
||||||
@@ -288,7 +294,8 @@ public final class MultiShareSender {
|
|||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
validatedMentions,
|
validatedMentions,
|
||||||
false,
|
false,
|
||||||
multiShareArgs.getBodyRanges());
|
multiShareArgs.getBodyRanges(),
|
||||||
|
contacts);
|
||||||
|
|
||||||
outgoingMessages.add(outgoingMessage);
|
outgoingMessages.add(outgoingMessage);
|
||||||
}
|
}
|
||||||
@@ -305,7 +312,8 @@ public final class MultiShareSender {
|
|||||||
buildLinkPreviews(context, multiShareArgs.getLinkPreview()),
|
buildLinkPreviews(context, multiShareArgs.getLinkPreview()),
|
||||||
validatedMentions,
|
validatedMentions,
|
||||||
false,
|
false,
|
||||||
multiShareArgs.getBodyRanges());
|
multiShareArgs.getBodyRanges(),
|
||||||
|
contacts);
|
||||||
|
|
||||||
outgoingMessages.add(outgoingMessage);
|
outgoingMessages.add(outgoingMessage);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user