Implement Stories feature behind flag.

Co-Authored-By: Greyson Parrelli <37311915+greyson-signal@users.noreply.github.com>
Co-Authored-By: Rashad Sookram <95182499+rashad-signal@users.noreply.github.com>
This commit is contained in:
Alex Hart
2022-02-24 13:40:28 -04:00
parent 765185952e
commit 174cd860a0
416 changed files with 19506 additions and 857 deletions

View File

@@ -102,8 +102,10 @@ public final class MultiShareSender {
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, mentions);
sendMediaMessage(context, multiShareArgs, recipient, slideDeck, transport, shareContactAndThread.getThreadId(), forceSms, expiresIn, multiShareArgs.isViewOnce(), subscriptionId, mentions, shareContactAndThread.isStory());
results.add(new MultiShareSendResult(shareContactAndThread, MultiShareSendResult.Type.SUCCESS));
} else if (shareContactAndThread.isStory()) {
results.add(new MultiShareSendResult(shareContactAndThread, MultiShareSendResult.Type.INVALID_SHARE_TO_STORY));
} else {
sendTextMessage(context, multiShareArgs, recipient, shareContactAndThread.getThreadId(), forceSms, expiresIn, subscriptionId);
results.add(new MultiShareSendResult(shareContactAndThread, MultiShareSendResult.Type.SUCCESS));
@@ -152,7 +154,8 @@ public final class MultiShareSender {
long expiresIn,
boolean isViewOnce,
int subscriptionId,
@NonNull List<Mention> validatedMentions)
@NonNull List<Mention> validatedMentions,
boolean isStory)
{
String body = multiShareArgs.getDraftText();
if (transportOption.isType(TransportOption.Type.TEXTSECURE) && !forceSms && body != null) {
@@ -164,26 +167,64 @@ public final class MultiShareSender {
}
}
OutgoingMediaMessage outgoingMediaMessage = new OutgoingMediaMessage(recipient,
slideDeck,
body,
System.currentTimeMillis(),
subscriptionId,
expiresIn,
isViewOnce,
ThreadDatabase.DistributionTypes.DEFAULT,
null,
Collections.emptyList(),
multiShareArgs.getLinkPreview() != null ? Collections.singletonList(multiShareArgs.getLinkPreview())
: Collections.emptyList(),
validatedMentions);
List<OutgoingMediaMessage> outgoingMessages = new ArrayList<>();
if (recipient.isRegistered() && !forceSms) {
MessageSender.send(context, new OutgoingSecureMediaMessage(outgoingMediaMessage), threadId, false, null, null);
if (isStory && slideDeck.getSlides().size() > 1) {
for (final Slide slide : slideDeck.getSlides()) {
SlideDeck singletonDeck = new SlideDeck();
singletonDeck.addSlide(slide);
OutgoingMediaMessage outgoingMediaMessage = new OutgoingMediaMessage(recipient,
singletonDeck,
body,
System.currentTimeMillis(),
subscriptionId,
expiresIn,
isViewOnce,
ThreadDatabase.DistributionTypes.DEFAULT,
true,
null,
null,
Collections.emptyList(),
multiShareArgs.getLinkPreview() != null ? Collections.singletonList(multiShareArgs.getLinkPreview())
: Collections.emptyList(),
validatedMentions);
outgoingMessages.add(outgoingMediaMessage);
// XXX We must do this to avoid sending out messages to the same recipient with the same
// sentTimestamp. If we do this, they'll be considered dupes by the receiver.
ThreadUtil.sleep(5);
}
} else {
MessageSender.send(context, outgoingMediaMessage, threadId, forceSms, null, null);
OutgoingMediaMessage outgoingMediaMessage = new OutgoingMediaMessage(recipient,
slideDeck,
body,
System.currentTimeMillis(),
subscriptionId,
expiresIn,
isViewOnce,
ThreadDatabase.DistributionTypes.DEFAULT,
isStory,
null,
null,
Collections.emptyList(),
multiShareArgs.getLinkPreview() != null ? Collections.singletonList(multiShareArgs.getLinkPreview())
: Collections.emptyList(),
validatedMentions);
outgoingMessages.add(outgoingMediaMessage);
}
if (recipient.isRegistered() && !forceSms) {
for (final OutgoingMediaMessage outgoingMessage : outgoingMessages) {
MessageSender.send(context, new OutgoingSecureMediaMessage(outgoingMessage), threadId, false, null, null);
}
} else {
for (final OutgoingMediaMessage outgoingMessage : outgoingMessages) {
MessageSender.send(context, new OutgoingSecureMediaMessage(outgoingMessage), threadId, forceSms, null, null);
}
}
}
private static void sendTextMessage(@NonNull Context context,
@@ -280,6 +321,7 @@ public final class MultiShareSender {
private enum Type {
GENERIC_ERROR,
INVALID_SHARE_TO_STORY,
MMS_NOT_ENABLED,
SUCCESS
}

View File

@@ -188,7 +188,7 @@ public class ShareActivity extends PassphraseRequiredActivity
}
@Override
public void onBeforeContactSelected(Optional<RecipientId> recipientId, String number, java.util.function.Consumer<Boolean> callback) {
public void onBeforeContactSelected(@NonNull Optional<RecipientId> recipientId, String number, @NonNull java.util.function.Consumer<Boolean> callback) {
if (disallowMultiShare) {
Toast.makeText(this, R.string.ShareActivity__sharing_to_multiple_chats_is, Toast.LENGTH_LONG).show();
callback.accept(false);
@@ -527,7 +527,7 @@ public class ShareActivity extends PassphraseRequiredActivity
.toArray(RecipientId[]::new));
return Stream.of(recipients)
.map(recipient -> new ShareContactAndThread(recipient.getId(), Util.getOrDefault(existingThreads, recipient.getId(), -1L), recipient.isForceSmsSelection() || !recipient.isRegistered()))
.map(recipient -> new ShareContactAndThread(recipient.getId(), Util.getOrDefault(existingThreads, recipient.getId(), -1L), recipient.isForceSmsSelection() || !recipient.isRegistered(), recipient.isDistributionList()))
.collect(Collectors.toSet());
}
@@ -542,7 +542,7 @@ public class ShareActivity extends PassphraseRequiredActivity
}
long existingThread = SignalDatabase.threads().getThreadIdIfExistsFor(recipient.getId());
return new ShareContactAndThread(recipient.getId(), existingThread, recipient.isForceSmsSelection() || !recipient.isRegistered());
return new ShareContactAndThread(recipient.getId(), existingThread, recipient.isForceSmsSelection() || !recipient.isRegistered(), recipient.isDistributionList());
}
private void validateAvailableRecipients() {

View File

@@ -12,6 +12,11 @@ public final class ShareContact {
private final Optional<RecipientId> recipientId;
private final String number;
public ShareContact(@NonNull RecipientId recipientId) {
this.recipientId = Optional.of(recipientId);
this.number = null;
}
public ShareContact(@NonNull Optional<RecipientId> recipientId, @Nullable String number) {
this.recipientId = recipientId;
this.number = number;

View File

@@ -13,17 +13,20 @@ public final class ShareContactAndThread implements Parcelable {
private final RecipientId recipientId;
private final long threadId;
private final boolean forceSms;
private final boolean isStory;
public ShareContactAndThread(@NonNull RecipientId recipientId, long threadId, boolean forceSms) {
public ShareContactAndThread(@NonNull RecipientId recipientId, long threadId, boolean forceSms, boolean isStory) {
this.recipientId = recipientId;
this.threadId = threadId;
this.forceSms = forceSms;
this.isStory = isStory;
}
protected ShareContactAndThread(@NonNull Parcel in) {
recipientId = in.readParcelable(RecipientId.class.getClassLoader());
threadId = in.readLong();
forceSms = in.readByte() == 1;
isStory = in.readByte() == 1;
}
public @NonNull RecipientId getRecipientId() {
@@ -38,6 +41,10 @@ public final class ShareContactAndThread implements Parcelable {
return forceSms;
}
public boolean isStory() {
return isStory;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -45,12 +52,13 @@ public final class ShareContactAndThread implements Parcelable {
ShareContactAndThread that = (ShareContactAndThread) o;
return threadId == that.threadId &&
forceSms == that.forceSms &&
isStory == that.isStory &&
recipientId.equals(that.recipientId);
}
@Override
public int hashCode() {
return Objects.hash(recipientId, threadId, forceSms);
return Objects.hash(recipientId, threadId, forceSms, isStory);
}
@Override
@@ -63,6 +71,7 @@ public final class ShareContactAndThread implements Parcelable {
dest.writeParcelable(recipientId, flags);
dest.writeLong(threadId);
dest.writeByte((byte) (forceSms ? 1 : 0));
dest.writeByte((byte) (isStory ? 1 : 0));
}
public static final Creator<ShareContactAndThread> CREATOR = new Creator<ShareContactAndThread>() {