Fix story send issues due to insertion of story sends to database.

This commit is contained in:
Alex Hart
2022-05-02 14:29:14 -03:00
committed by Greyson Parrelli
parent 38b6362b25
commit 5d16d1cd23
6 changed files with 123 additions and 34 deletions

View File

@@ -47,6 +47,7 @@ import org.thoughtcrime.securesms.util.Util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -78,6 +79,7 @@ public final class MultiShareSender {
boolean isMmsEnabled = Util.isMmsCapable(context);
String message = multiShareArgs.getDraftText();
SlideDeck slideDeck;
List<OutgoingMediaMessage> storiesBatch = new LinkedList<>();
try {
slideDeck = buildSlideDeck(context, multiShareArgs);
@@ -118,7 +120,7 @@ public final class MultiShareSender {
if ((recipient.isMmsGroup() || recipient.getEmail().isPresent()) && !isMmsEnabled) {
results.add(new MultiShareSendResult(recipientSearchKey, MultiShareSendResult.Type.MMS_NOT_ENABLED));
} else if (hasMmsMedia && transport.isSms() || hasPushMedia && !transport.isSms() || canSendAsTextStory) {
sendMediaMessage(context, multiShareArgs, recipient, slideDeck, transport, threadId, forceSms, expiresIn, multiShareArgs.isViewOnce(), subscriptionId, mentions, recipientSearchKey.isStory(), sentTimestamp, canSendAsTextStory);
sendMediaMessageOrCollectStoryToBatch(context, multiShareArgs, recipient, slideDeck, transport, threadId, forceSms, expiresIn, multiShareArgs.isViewOnce(), subscriptionId, mentions, recipientSearchKey.isStory(), sentTimestamp, canSendAsTextStory, storiesBatch);
results.add(new MultiShareSendResult(recipientSearchKey, MultiShareSendResult.Type.SUCCESS));
} else if (recipientSearchKey.isStory()) {
results.add(new MultiShareSendResult(recipientSearchKey, MultiShareSendResult.Type.INVALID_SHARE_TO_STORY));
@@ -132,6 +134,15 @@ public final class MultiShareSender {
ThreadUtil.sleep(5);
}
if (!storiesBatch.isEmpty()) {
MessageSender.sendStories(context,
storiesBatch.stream()
.map(OutgoingSecureMediaMessage::new)
.collect(Collectors.toList()),
null,
null);
}
return new MultiShareSendResultCollection(results);
}
@@ -160,20 +171,21 @@ public final class MultiShareSender {
}
}
private static void sendMediaMessage(@NonNull Context context,
@NonNull MultiShareArgs multiShareArgs,
@NonNull Recipient recipient,
@NonNull SlideDeck slideDeck,
@NonNull TransportOption transportOption,
long threadId,
boolean forceSms,
long expiresIn,
boolean isViewOnce,
int subscriptionId,
@NonNull List<Mention> validatedMentions,
boolean isStory,
long sentTimestamp,
boolean canSendAsTextStory)
private static void sendMediaMessageOrCollectStoryToBatch(@NonNull Context context,
@NonNull MultiShareArgs multiShareArgs,
@NonNull Recipient recipient,
@NonNull SlideDeck slideDeck,
@NonNull TransportOption transportOption,
long threadId,
boolean forceSms,
long expiresIn,
boolean isViewOnce,
int subscriptionId,
@NonNull List<Mention> validatedMentions,
boolean isStory,
long sentTimestamp,
boolean canSendAsTextStory,
@NonNull List<OutgoingMediaMessage> storiesToBatchSend)
{
String body = multiShareArgs.getDraftText();
if (transportOption.isType(TransportOption.Type.TEXTSECURE) && !forceSms && body != null) {
@@ -270,8 +282,9 @@ public final class MultiShareSender {
outgoingMessages.add(outgoingMediaMessage);
}
if (shouldSendAsPush(recipient, forceSms))
{
if (isStory) {
storiesToBatchSend.addAll(outgoingMessages);
} else if (shouldSendAsPush(recipient, forceSms)) {
for (final OutgoingMediaMessage outgoingMessage : outgoingMessages) {
MessageSender.send(context, new OutgoingSecureMediaMessage(outgoingMessage), threadId, false, null, null);
}

View File

@@ -130,6 +130,67 @@ public class MessageSender {
return allocatedThreadId;
}
public static void sendStories(@NonNull final Context context,
@NonNull final List<OutgoingSecureMediaMessage> messages,
@Nullable final String metricId,
@Nullable final SmsDatabase.InsertListener insertListener)
{
Log.i(TAG, "Sending story messages to " + messages.size() + " targets.");
ThreadDatabase threadDatabase = SignalDatabase.threads();
MessageDatabase database = SignalDatabase.mms();
List<Long> messageIds = new ArrayList<>(messages.size());
List<Long> threads = new ArrayList<>(messages.size());
try {
database.beginTransaction();
for (OutgoingMediaMessage message : messages) {
long allocatedThreadId = threadDatabase.getOrCreateValidThreadId(message.getRecipient(), -1L, message.getDistributionType());
Recipient recipient = message.getRecipient();
long messageId = database.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, recipient, message, allocatedThreadId), allocatedThreadId, false, insertListener);
messageIds.add(messageId);
threads.add(allocatedThreadId);
if (message.getRecipient().isGroup() && message.getAttachments().isEmpty() && message.getLinkPreviews().isEmpty() && message.getSharedContacts().isEmpty()) {
SignalLocalMetrics.GroupMessageSend.onInsertedIntoDatabase(messageId, metricId);
} else {
SignalLocalMetrics.GroupMessageSend.cancel(metricId);
}
}
for (int i = 0; i < messageIds.size(); i++) {
long messageId = messageIds.get(i);
OutgoingSecureMediaMessage message = messages.get(i);
Recipient recipient = message.getRecipient();
if (recipient.isDistributionList()) {
List<RecipientId> members = SignalDatabase.distributionLists().getMembers(recipient.requireDistributionListId());
SignalDatabase.storySends().insert(messageId, members, message.getSentTimeMillis(), message.getStoryType().isStoryWithReplies());
}
}
database.setTransactionSuccessful();
} catch (MmsException e) {
Log.w(TAG, e);
} finally {
database.endTransaction();
}
for (int i = 0; i < messageIds.size(); i++) {
long messageId = messageIds.get(i);
OutgoingSecureMediaMessage message = messages.get(i);
Recipient recipient = message.getRecipient();
sendMediaMessage(context, recipient, false, messageId, Collections.emptyList());
}
onMessageSent();
for (long threadId : threads) {
threadDatabase.update(threadId, true);
}
}
public static long send(final Context context,
final OutgoingMediaMessage message,
final long threadId,

View File

@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.stories
import androidx.annotation.WorkerThread
import androidx.fragment.app.FragmentManager
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.schedulers.Schedulers
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.contacts.HeaderAction
import org.thoughtcrime.securesms.database.AttachmentDatabase
@@ -21,6 +22,7 @@ import org.thoughtcrime.securesms.sms.MessageSender
import org.thoughtcrime.securesms.storage.StorageSyncHelper
import org.thoughtcrime.securesms.util.BottomSheetUtil
import org.thoughtcrime.securesms.util.FeatureFlags
import org.thoughtcrime.securesms.util.hasLinkPreview
import java.util.concurrent.TimeUnit
object Stories {
@@ -49,10 +51,9 @@ object Stories {
}
}
@WorkerThread
fun sendTextStories(messages: List<OutgoingSecureMediaMessage>): Completable {
return Completable.create { emitter ->
MessageSender.sendMediaBroadcast(ApplicationDependencies.getApplication(), messages, listOf(), listOf())
MessageSender.sendStories(ApplicationDependencies.getApplication(), messages, null, null)
emitter.onComplete()
}
}
@@ -87,12 +88,29 @@ object Stories {
val unreadStoriesReader = SignalDatabase.mms.getUnreadStories(recipientId, FeatureFlags.storiesAutoDownloadMaximum())
while (unreadStoriesReader.next != null) {
val record = unreadStoriesReader.current as MmsMessageRecord
SignalDatabase.attachments.getAttachmentsForMessage(record.id).filterNot { it.isSticker }.forEach {
if (it.transferState == AttachmentDatabase.TRANSFER_PROGRESS_PENDING) {
val job = AttachmentDownloadJob(record.id, it.attachmentId, ignoreAutoDownloadConstraints)
ApplicationDependencies.getJobManager().add(job)
}
enqueueAttachmentsFromStoryForDownloadSync(record, ignoreAutoDownloadConstraints)
}
}
fun enqueueAttachmentsFromStoryForDownload(record: MmsMessageRecord, ignoreAutoDownloadConstraints: Boolean): Completable {
return Completable.fromAction {
enqueueAttachmentsFromStoryForDownloadSync(record, ignoreAutoDownloadConstraints)
}.subscribeOn(Schedulers.io())
}
@WorkerThread
private fun enqueueAttachmentsFromStoryForDownloadSync(record: MmsMessageRecord, ignoreAutoDownloadConstraints: Boolean) {
SignalDatabase.attachments.getAttachmentsForMessage(record.id).filterNot { it.isSticker }.forEach {
if (it.transferState == AttachmentDatabase.TRANSFER_PROGRESS_PENDING) {
val job = AttachmentDownloadJob(record.id, it.attachmentId, ignoreAutoDownloadConstraints)
ApplicationDependencies.getJobManager().add(job)
}
}
if (record.hasLinkPreview()) {
ApplicationDependencies.getJobManager().add(
AttachmentDownloadJob(record.id, record.linkPreviews[0].attachmentId, true)
)
}
}
}

View File

@@ -7,7 +7,6 @@ import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.schedulers.Schedulers
import org.signal.core.util.BreakIteratorCompat
import org.signal.core.util.concurrent.SignalExecutors
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.conversation.ConversationMessage
import org.thoughtcrime.securesms.database.DatabaseObserver
import org.thoughtcrime.securesms.database.NoSuchMessageException
@@ -17,7 +16,6 @@ import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.database.model.databaseprotos.StoryTextPost
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob
import org.thoughtcrime.securesms.jobs.MultiDeviceViewedUpdateJob
import org.thoughtcrime.securesms.jobs.SendViewedReceiptJob
import org.thoughtcrime.securesms.recipients.Recipient
@@ -133,12 +131,8 @@ open class StoryViewerPageRepository(context: Context) {
}
}
fun forceDownload(post: StoryPost) {
if (post.content is StoryPost.Content.AttachmentContent) {
ApplicationDependencies.getJobManager().add(
AttachmentDownloadJob(post.id, (post.content.attachment as DatabaseAttachment).attachmentId, true)
)
}
fun forceDownload(post: StoryPost): Completable {
return Stories.enqueueAttachmentsFromStoryForDownload(post.conversationMessage.messageRecord as MmsMessageRecord, true)
}
fun getStoryPostsFor(recipientId: RecipientId): Observable<List<StoryPost>> {

View File

@@ -85,7 +85,7 @@ class StoryViewerPageViewModel(
val selectedPost = getPostAt(index)
if (selectedPost != null && selectedPost.content.transferState != AttachmentDatabase.TRANSFER_PROGRESS_DONE) {
repository.forceDownload(selectedPost)
disposables += repository.forceDownload(selectedPost).subscribe()
}
store.update {
@@ -136,7 +136,7 @@ class StoryViewerPageViewModel(
}
fun forceDownloadSelectedPost() {
repository.forceDownload(getPost())
disposables += repository.forceDownload(getPost()).subscribe()
}
fun startDirectReply(storyId: Long, recipientId: RecipientId) {