Allow forwarding of Text Stories.

fork-5.53.8
Alex Hart 2022-03-17 16:03:26 -03:00 zatwierdzone przez Cody Henthorne
rodzic 43ad0b2294
commit e3c491860a
5 zmienionych plików z 103 dodań i 46 usunięć

Wyświetl plik

@ -130,13 +130,15 @@ class MultiselectForwardFragment :
container.addView(bottomBar)
contactSearchMediator.getSelectionState().observe(viewLifecycleOwner) {
shareSelectionAdapter.submitList(it.mapIndexed { index, key -> ShareSelectionMappingModel(key.requireShareContact(), index == 0) })
contactSearchMediator.getSelectionState().observe(viewLifecycleOwner) { contactSelection ->
shareSelectionAdapter.submitList(contactSelection.mapIndexed { index, key -> ShareSelectionMappingModel(key.requireShareContact(), index == 0) })
if (it.isNotEmpty() && !bottomBar.isVisible) {
addMessage.visible = contactSelection.any { key -> key !is ContactSearchKey.Story } && getMultiShareArgs().isNotEmpty()
if (contactSelection.isNotEmpty() && !bottomBar.isVisible) {
bottomBar.animation = AnimationUtils.loadAnimation(requireContext(), R.anim.slide_fade_from_bottom)
bottomBar.visible = true
} else if (it.isEmpty() && bottomBar.isVisible) {
} else if (contactSelection.isEmpty() && bottomBar.isVisible) {
bottomBar.animation = AnimationUtils.loadAnimation(requireContext(), R.anim.slide_fade_to_bottom)
bottomBar.visible = false
}
@ -162,8 +164,6 @@ class MultiselectForwardFragment :
sendButton.isEnabled = it.stage == MultiselectForwardState.Stage.Selection
}
addMessage.visible = getMultiShareArgs().isNotEmpty()
setFragmentResultListener(CreateStoryWithViewersFragment.REQUEST_KEY) { _, bundle ->
val recipientId: RecipientId = bundle.getParcelable(CreateStoryWithViewersFragment.STORY_RECIPIENT)!!
contactSearchMediator.setKeysSelected(setOf(ContactSearchKey.Story(recipientId)))
@ -282,40 +282,48 @@ class MultiselectForwardFragment :
query = contactSearchState.query
if (Stories.isFeatureEnabled() && isSelectedMediaValidForStories()) {
val expandedConfig: ContactSearchConfiguration.ExpandConfig? = if (isSelectedMediaValidForNonStories()) {
ContactSearchConfiguration.ExpandConfig(
isExpanded = contactSearchState.expandedSections.contains(ContactSearchConfiguration.SectionKey.STORIES)
)
} else {
null
}
addSection(
ContactSearchConfiguration.Section.Stories(
groupStories = contactSearchState.groupStories,
includeHeader = true,
headerAction = getHeaderAction(childFragmentManager),
expandConfig = ContactSearchConfiguration.ExpandConfig(
isExpanded = contactSearchState.expandedSections.contains(ContactSearchConfiguration.SectionKey.STORIES)
expandConfig = expandedConfig
)
)
}
if (isSelectedMediaValidForNonStories()) {
if (query.isNullOrEmpty()) {
addSection(
ContactSearchConfiguration.Section.Recents(
includeHeader = true
)
)
)
}
}
if (query.isNullOrEmpty()) {
addSection(
ContactSearchConfiguration.Section.Recents(
includeHeader = true
ContactSearchConfiguration.Section.Individuals(
includeHeader = true,
transportType = if (includeSms()) ContactSearchConfiguration.TransportType.ALL else ContactSearchConfiguration.TransportType.PUSH,
includeSelf = true
)
)
addSection(
ContactSearchConfiguration.Section.Groups(
includeHeader = true,
includeMms = includeSms()
)
)
}
addSection(
ContactSearchConfiguration.Section.Individuals(
includeHeader = true,
transportType = if (includeSms()) ContactSearchConfiguration.TransportType.ALL else ContactSearchConfiguration.TransportType.PUSH,
includeSelf = true
)
)
addSection(
ContactSearchConfiguration.Section.Groups(
includeHeader = true,
includeMms = includeSms()
)
)
}
}
@ -327,6 +335,10 @@ class MultiselectForwardFragment :
return getMultiShareArgs().all { it.isValidForStories }
}
private fun isSelectedMediaValidForNonStories(): Boolean {
return getMultiShareArgs().all { it.isValidForNonStories }
}
override fun onGroupStoryClicked() {
ChooseGroupStoryBottomSheet().show(parentFragmentManager, ChooseGroupStoryBottomSheet.GROUP_STORY)
}

Wyświetl plik

@ -72,6 +72,7 @@ class MultiselectForwardFragmentArgs(
val linkPreview = mediaMessage?.linkPreviews?.firstOrNull()
builder.withLinkPreview(linkPreview)
builder.asTextStory(mediaMessage?.storyType?.isTextStory ?: false)
}
if (conversationMessage.messageRecord.isMms && conversationMessage.multiselectCollection.isMediaSelected(selectedParts)) {

Wyświetl plik

@ -61,13 +61,17 @@ class MultiselectForwardRepository(context: Context) {
val results = mappedArgs.sortedBy { it.timestamp }.map { MultiShareSender.sendSync(it) }
if (additionalMessage.isNotEmpty()) {
val additional = MultiShareArgs.Builder(sharedContactsAndThreads)
val additional = MultiShareArgs.Builder(sharedContactsAndThreads.filterNot { it.isStory }.toSet())
.withDraftText(additionalMessage)
.build()
val additionalResult: MultiShareSender.MultiShareSendResultCollection = MultiShareSender.sendSync(additional)
if (additional.shareContactAndThreads.isNotEmpty()) {
val additionalResult: MultiShareSender.MultiShareSendResultCollection = MultiShareSender.sendSync(additional)
handleResults(results + additionalResult, resultHandlers)
handleResults(results + additionalResult, resultHandlers)
} else {
handleResults(results, resultHandlers)
}
} else {
handleResults(results, resultHandlers)
}

Wyświetl plik

@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.stickers.StickerLocator;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ParcelUtil;
import java.io.IOException;
import java.util.ArrayList;
@ -37,6 +38,7 @@ public final class MultiShareArgs implements Parcelable {
private final List<Mention> mentions;
private final long timestamp;
private final long expiresAt;
private final boolean isTextStory;
private MultiShareArgs(@NonNull Builder builder) {
shareContactAndThreads = builder.shareContactAndThreads;
@ -51,6 +53,7 @@ public final class MultiShareArgs implements Parcelable {
mentions = builder.mentions == null ? new ArrayList<>() : new ArrayList<>(builder.mentions);
timestamp = builder.timestamp;
expiresAt = builder.expiresAt;
isTextStory = builder.isTextStory;
}
protected MultiShareArgs(Parcel in) {
@ -65,6 +68,7 @@ public final class MultiShareArgs implements Parcelable {
mentions = in.createTypedArrayList(Mention.CREATOR);
timestamp = in.readLong();
expiresAt = in.readLong();
isTextStory = ParcelUtil.readBoolean(in);
String linkedPreviewString = in.readString();
LinkPreview preview;
@ -109,6 +113,10 @@ public final class MultiShareArgs implements Parcelable {
return viewOnce;
}
public boolean isTextStory() {
return isTextStory;
}
public @Nullable LinkPreview getLinkPreview() {
return linkPreview;
}
@ -126,7 +134,11 @@ public final class MultiShareArgs implements Parcelable {
}
public boolean isValidForStories() {
return !media.isEmpty() && media.stream().allMatch(m -> MediaUtil.isImageOrVideoType(m.getMimeType()) && !MediaUtil.isGif(m.getMimeType()));
return isTextStory || !media.isEmpty() && media.stream().allMatch(m -> MediaUtil.isImageOrVideoType(m.getMimeType()) && !MediaUtil.isGif(m.getMimeType()));
}
public boolean isValidForNonStories() {
return !isTextStory;
}
public @NonNull InterstitialContentType getInterstitialContentType() {
@ -174,6 +186,7 @@ public final class MultiShareArgs implements Parcelable {
dest.writeTypedList(mentions);
dest.writeLong(timestamp);
dest.writeLong(expiresAt);
ParcelUtil.writeBoolean(dest, isTextStory);
if (linkPreview != null) {
try {
@ -201,7 +214,8 @@ public final class MultiShareArgs implements Parcelable {
.withStickerLocator(stickerLocator)
.withMentions(mentions)
.withTimestamp(timestamp)
.withExpiration(expiresAt);
.withExpiration(expiresAt)
.asTextStory(isTextStory);
}
private boolean requiresInterstitial() {
@ -224,6 +238,7 @@ public final class MultiShareArgs implements Parcelable {
private List<Mention> mentions;
private long timestamp;
private long expiresAt;
private boolean isTextStory;
public Builder(@NonNull Set<ShareContactAndThread> shareContactAndThreads) {
this.shareContactAndThreads = shareContactAndThreads;
@ -284,6 +299,11 @@ public final class MultiShareArgs implements Parcelable {
return this;
}
public @NonNull Builder asTextStory(boolean isTextStory) {
this.isTextStory = isTextStory;
return this;
}
public @NonNull MultiShareArgs build() {
return new MultiShareArgs(this);
}

Wyświetl plik

@ -104,7 +104,7 @@ public final class MultiShareSender {
if ((recipient.isMmsGroup() || recipient.getEmail().isPresent()) && !isMmsEnabled) {
results.add(new MultiShareSendResult(shareContactAndThread, MultiShareSendResult.Type.MMS_NOT_ENABLED));
} else if (hasMmsMedia && transport.isSms() || hasPushMedia && !transport.isSms()) {
} else if (hasMmsMedia && transport.isSms() || hasPushMedia && !transport.isSms() || multiShareArgs.isTextStory()) {
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()) {
@ -184,32 +184,52 @@ public final class MultiShareSender {
SignalDatabase.groups().markDisplayAsStory(recipient.requireGroupId());
}
for (final Slide slide : slideDeck.getSlides()) {
SlideDeck singletonDeck = new SlideDeck();
singletonDeck.addSlide(slide);
if (multiShareArgs.isTextStory()) {
OutgoingMediaMessage outgoingMediaMessage = new OutgoingMediaMessage(recipient,
singletonDeck,
new SlideDeck(),
body,
System.currentTimeMillis(),
subscriptionId,
expiresIn,
isViewOnce,
0L,
false,
ThreadDatabase.DistributionTypes.DEFAULT,
storyType,
storyType.toTextStoryType(),
null,
false,
null,
Collections.emptyList(),
multiShareArgs.getLinkPreview() != null ? Collections.singletonList(multiShareArgs.getLinkPreview())
: Collections.emptyList(),
validatedMentions);
Collections.emptyList());
outgoingMessages.add(outgoingMediaMessage);
} else {
for (final Slide slide : slideDeck.getSlides()) {
SlideDeck singletonDeck = new SlideDeck();
singletonDeck.addSlide(slide);
// 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);
OutgoingMediaMessage outgoingMediaMessage = new OutgoingMediaMessage(recipient,
singletonDeck,
body,
System.currentTimeMillis(),
subscriptionId,
0L,
false,
ThreadDatabase.DistributionTypes.DEFAULT,
storyType,
null,
false,
null,
Collections.emptyList(),
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 {
OutgoingMediaMessage outgoingMediaMessage = new OutgoingMediaMessage(recipient,