From d5fd424b95371cb6ef3971e7f79f93157314b689 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Mon, 28 Feb 2022 12:37:37 -0400 Subject: [PATCH] Fix several over-the-wire story issues. Co-authored-by: Rashad Sookram --- .../securesms/database/MmsDatabase.java | 19 ++++---- .../securesms/database/MmsSmsDatabase.java | 13 +++--- .../securesms/database/model/ParentStoryId.kt | 45 +++++++++++++++++++ .../securesms/jobs/PushGroupSendJob.java | 6 +-- .../securesms/jobs/PushMediaSendJob.java | 6 +-- .../messages/MessageContentProcessor.java | 22 ++++++--- .../securesms/mms/IncomingMediaMessage.kt | 6 +-- .../securesms/mms/OutgoingMediaMessage.java | 10 ++--- .../mms/OutgoingSecureMediaMessage.java | 4 +- .../viewer/page/StoryViewerPageViewModel.kt | 18 +------- .../direct/StoryDirectReplyRepository.kt | 3 +- .../reply/group/StoryGroupReplySender.kt | 4 +- 12 files changed, 98 insertions(+), 58 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/database/model/ParentStoryId.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java index 748ba87db0..b884a8fd86 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -54,6 +54,7 @@ import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord; import org.thoughtcrime.securesms.database.model.Quote; import org.thoughtcrime.securesms.database.model.SmsMessageRecord; import org.thoughtcrime.securesms.database.model.StoryViewState; +import org.thoughtcrime.securesms.database.model.ParentStoryId; import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange; @@ -813,7 +814,7 @@ public class MmsDatabase extends MessageDatabase { public int getMessageCountForThread(long threadId) { SQLiteDatabase db = databaseHelper.getSignalReadableDatabase(); - String query = THREAD_ID + " = ? AND " + IS_STORY + " = ? AND " + PARENT_STORY_ID + " = ?"; + String query = THREAD_ID + " = ? AND " + IS_STORY + " = ? AND " + PARENT_STORY_ID + " <= ?"; String[] args = SqlUtil.buildArgs(threadId, 0, 0); try (Cursor cursor = db.query(TABLE_NAME, COUNT, query, args, null, null, null)) { @@ -829,7 +830,7 @@ public class MmsDatabase extends MessageDatabase { public int getMessageCountForThread(long threadId, long beforeTime) { SQLiteDatabase db = databaseHelper.getSignalReadableDatabase(); - String query = THREAD_ID + " = ? AND " + DATE_RECEIVED + " < ? AND " + IS_STORY + " = ? AND " + PARENT_STORY_ID + " = ?"; + String query = THREAD_ID + " = ? AND " + DATE_RECEIVED + " < ? AND " + IS_STORY + " = ? AND " + PARENT_STORY_ID + " <= ?"; String[] args = SqlUtil.buildArgs(threadId, beforeTime, 0, 0); try (Cursor cursor = db.query(TABLE_NAME, COUNT, query, args, null, null, null)) { @@ -1207,20 +1208,20 @@ public class MmsDatabase extends MessageDatabase { @Override public List setMessagesReadSince(long threadId, long sinceTimestamp) { if (sinceTimestamp == -1) { - return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " = 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND (" + getOutgoingTypeClause() + ")))", new String[] {String.valueOf(threadId)}); + return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " <= 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND (" + getOutgoingTypeClause() + ")))", new String[] {String.valueOf(threadId)}); } else { - return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " = 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND ( " + getOutgoingTypeClause() + " ))) AND " + DATE_RECEIVED + " <= ?", new String[]{String.valueOf(threadId), String.valueOf(sinceTimestamp)}); + return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " <= 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND ( " + getOutgoingTypeClause() + " ))) AND " + DATE_RECEIVED + " <= ?", new String[]{String.valueOf(threadId), String.valueOf(sinceTimestamp)}); } } @Override public List setEntireThreadRead(long threadId) { - return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " = 0", new String[] {String.valueOf(threadId)}); + return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " <= 0", new String[] {String.valueOf(threadId)}); } @Override public List setAllMessagesRead() { - return setMessagesRead(IS_STORY+ " = 0 AND " + PARENT_STORY_ID + " = 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND (" + getOutgoingTypeClause() + ")))", null); + return setMessagesRead(IS_STORY+ " = 0 AND " + PARENT_STORY_ID + " <= 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND (" + getOutgoingTypeClause() + ")))", null); } private List setMessagesRead(String where, String[] arguments) { @@ -1419,7 +1420,7 @@ public class MmsDatabase extends MessageDatabase { String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES)); String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE)); boolean isStory = CursorUtil.requireBoolean(cursor, IS_STORY); - MessageId parentStoryId = MessageId.fromNullable(CursorUtil.requireLong(cursor, PARENT_STORY_ID), true); + ParentStoryId parentStoryId = ParentStoryId.deserialize(CursorUtil.requireLong(cursor, PARENT_STORY_ID)); long quoteId = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_ID)); long quoteAuthor = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_AUTHOR)); @@ -1590,7 +1591,7 @@ public class MmsDatabase extends MessageDatabase { contentValues.put(EXPIRES_IN, retrieved.getExpiresIn()); contentValues.put(VIEW_ONCE, retrieved.isViewOnce() ? 1 : 0); contentValues.put(IS_STORY, retrieved.isStory() ? 1 : 0); - contentValues.put(PARENT_STORY_ID, retrieved.getParentStoryId() != null ? retrieved.getParentStoryId().getId() : 0); + contentValues.put(PARENT_STORY_ID, retrieved.getParentStoryId() != null ? retrieved.getParentStoryId().serialize() : 0); contentValues.put(READ, retrieved.isExpirationUpdate() ? 1 : 0); contentValues.put(UNIDENTIFIED, retrieved.isUnidentified()); contentValues.put(SERVER_GUID, retrieved.getServerGuid()); @@ -1785,7 +1786,7 @@ public class MmsDatabase extends MessageDatabase { contentValues.put(DELIVERY_RECEIPT_COUNT, Stream.of(earlyDeliveryReceipts.values()).mapToLong(EarlyReceiptCache.Receipt::getCount).sum()); contentValues.put(RECEIPT_TIMESTAMP, Stream.of(earlyDeliveryReceipts.values()).mapToLong(EarlyReceiptCache.Receipt::getTimestamp).max().orElse(-1)); contentValues.put(IS_STORY, message.isStory() ? 1 : 0); - contentValues.put(PARENT_STORY_ID, message.getParentStoryId() != null ? message.getParentStoryId().getId() : 0); + contentValues.put(PARENT_STORY_ID, message.getParentStoryId() != null ? message.getParentStoryId().serialize() : 0); if (message.getRecipient().isSelf() && hasAudioAttachment(message.getAttachments())) { contentValues.put(VIEWED_RECEIPT_COUNT, 1L); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java index f86d74bc99..ae627258ff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java @@ -118,7 +118,7 @@ public class MmsSmsDatabase extends Database { "WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ", " + SmsDatabase.Types.CHANGE_NUMBER_TYPE + ", " + SmsDatabase.Types.BOOST_REQUEST_TYPE + ") AND " + SmsDatabase.TYPE + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " " + "UNION ALL " + "SELECT " + MmsSmsColumns.ID + ", 1 AS " + TRANSPORT + ", " + MmsDatabase.MESSAGE_BOX + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + MmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + MmsDatabase.TABLE_NAME + " " + - "WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + MmsDatabase.MESSAGE_BOX + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " = 0 " + + "WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + MmsDatabase.MESSAGE_BOX + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " <= 0 " + "ORDER BY " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC " + "LIMIT 1"; @@ -202,7 +202,7 @@ public class MmsSmsDatabase extends Database { public Cursor getConversation(long threadId, long offset, long limit) { SQLiteDatabase db = databaseHelper.getSignalReadableDatabase(); String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC"; - String selection = MmsSmsColumns.THREAD_ID + " = " + threadId + " AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " = 0"; + String selection = MmsSmsColumns.THREAD_ID + " = " + threadId + " AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " <= 0"; String limitStr = limit > 0 || offset > 0 ? offset + ", " + limit : null; String query = buildQuery(PROJECTION, selection, order, limitStr, false); @@ -264,19 +264,16 @@ public class MmsSmsDatabase extends Database { } String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC"; - String selection = MmsSmsColumns.NOTIFIED + " = 0 AND (" + MmsSmsColumns.READ + " = 0 OR " + MmsSmsColumns.REACTIONS_UNREAD + " = 1" + (stickyQuery.length() > 0 ? " OR (" + stickyQuery.toString() + ")" : "") + ")"; + String selection = MmsSmsColumns.NOTIFIED + " = 0 AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " <= 0 AND (" + MmsSmsColumns.READ + " = 0 OR " + MmsSmsColumns.REACTIONS_UNREAD + " = 1" + (stickyQuery.length() > 0 ? " OR (" + stickyQuery.toString() + ")" : "") + ")"; return queryTables(PROJECTION, selection, order, null); } public int getUnreadCount(long threadId) { - String selection = MmsSmsColumns.READ + " = 0 AND " + MmsSmsColumns.THREAD_ID + " = " + threadId; - Cursor cursor = queryTables(PROJECTION, selection, null, null); + String selection = MmsSmsColumns.READ + " = 0 AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsSmsColumns.THREAD_ID + " = " + threadId + " AND " + MmsDatabase.PARENT_STORY_ID + " <= 0"; - try { + try (Cursor cursor = queryTables(PROJECTION, selection, null, null)) { return cursor != null ? cursor.getCount() : 0; - } finally { - if (cursor != null) cursor.close(); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/ParentStoryId.kt b/app/src/main/java/org/thoughtcrime/securesms/database/model/ParentStoryId.kt new file mode 100644 index 0000000000..fc4f4b9f09 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/ParentStoryId.kt @@ -0,0 +1,45 @@ +package org.thoughtcrime.securesms.database.model + +import kotlin.math.abs + +/** + * Abstract representation of a message id for a story. + * + * At the database layer, the sign of the id is dependant on whether a reply is meant for + * a group thread or a direct reply. This class facilitates that, while still allowing for + * normal behaviour elsewhere. + */ +sealed class ParentStoryId(protected val id: Long) { + abstract fun serialize(): Long + + fun asMessageId(): MessageId = MessageId(abs(id), true) + + /** + * A parent story who's child should be displayed in a group reply thread. + */ + class GroupReply(id: Long) : ParentStoryId(id) { + override fun serialize(): Long = abs(id) + } + + /** + * A parent story who's child should be displayed in a 1:1 conversation. + */ + class DirectReply(id: Long) : ParentStoryId(id) { + override fun serialize(): Long = -abs(id) + } + + companion object { + /** + * Takes a long stored in the database and converts it to an appropriate subclass of ParentStoryId. + * If the passed value is 0L, null is returned. + */ + @JvmStatic + fun deserialize(id: Long): ParentStoryId? { + return when { + id > 0L -> GroupReply(id) + id < 0L -> DirectReply(id) + else -> null + } + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index 5110fd15ab..de013b37cd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -222,7 +222,6 @@ public final class PushGroupSendJob extends PushSendJob { GroupId.Push groupId = groupRecipient.requireGroupId().requirePush(); Optional profileKey = getProfileKey(groupRecipient); - Optional quote = getQuoteFor(message); Optional sticker = getStickerFor(message); List sharedContacts = getSharedContactsFor(message); List previews = getPreviewsFor(message); @@ -290,7 +289,6 @@ public final class PushGroupSendJob extends PushSendJob { .withViewOnce(message.isViewOnce()) .asExpirationUpdate(message.isExpirationUpdate()) .withProfileKey(profileKey.orNull()) - .withQuote(quote.orNull()) .withSticker(sticker.orNull()) .withSharedContacts(sharedContacts) .withPreviews(previews) @@ -298,7 +296,7 @@ public final class PushGroupSendJob extends PushSendJob { if (message.getParentStoryId() != null) { try { - MessageRecord storyRecord = SignalDatabase.mms().getMessageRecord(message.getParentStoryId().getId()); + MessageRecord storyRecord = SignalDatabase.mms().getMessageRecord(message.getParentStoryId().asMessageId().getId()); Recipient recipient = storyRecord.isOutgoing() ? Recipient.self() : storyRecord.getIndividualRecipient(); groupMessageBuilder.withStoryContext(new SignalServiceDataMessage.StoryContext(recipient.requireServiceId(), storyRecord.getDateSent())); @@ -307,6 +305,8 @@ public final class PushGroupSendJob extends PushSendJob { // TODO [stories] check what should happen in this case throw new UndeliverableMessageException(e); } + } else { + groupMessageBuilder.withQuote(getQuoteFor(message).orNull()); } Log.i(TAG, JobLogger.format(this, "Beginning message send.")); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java index 61beac1f3f..34a135f2ff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java @@ -208,7 +208,6 @@ public class PushMediaSendJob extends PushSendJob { List attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList(); List serviceAttachments = getAttachmentPointersFor(attachments); Optional profileKey = getProfileKey(messageRecipient); - Optional quote = getQuoteFor(message); Optional sticker = getStickerFor(message); List sharedContacts = getSharedContactsFor(message); List previews = getPreviewsFor(message); @@ -219,7 +218,6 @@ public class PushMediaSendJob extends PushSendJob { .withExpiration((int)(message.getExpiresIn() / 1000)) .withViewOnce(message.isViewOnce()) .withProfileKey(profileKey.orNull()) - .withQuote(quote.orNull()) .withSticker(sticker.orNull()) .withSharedContacts(sharedContacts) .withPreviews(previews) @@ -227,13 +225,15 @@ public class PushMediaSendJob extends PushSendJob { if (message.getParentStoryId() != null) { try { - MessageRecord storyRecord = SignalDatabase.mms().getMessageRecord(message.getParentStoryId().getId()); + MessageRecord storyRecord = SignalDatabase.mms().getMessageRecord(message.getParentStoryId().asMessageId().getId()); mediaMessageBuilder.withStoryContext(new SignalServiceDataMessage.StoryContext(address.getServiceId(), storyRecord.getDateSent())); } catch (NoSuchMessageException e) { // The story has probably expired // TODO [stories] check what should happen in this case throw new UndeliverableMessageException(e); } + } else { + mediaMessageBuilder.withQuote(getQuoteFor(message).orNull()); } SignalServiceDataMessage mediaMessage = mediaMessageBuilder.build(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java index a1c12db1b6..b3d344a4b1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java @@ -46,6 +46,7 @@ import org.thoughtcrime.securesms.database.model.MessageId; import org.thoughtcrime.securesms.database.model.MessageLogEntry; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MmsMessageRecord; +import org.thoughtcrime.securesms.database.model.ParentStoryId; import org.thoughtcrime.securesms.database.model.PendingRetryReceiptModel; import org.thoughtcrime.securesms.database.model.ReactionRecord; import org.thoughtcrime.securesms.database.model.StickerRecord; @@ -1376,11 +1377,20 @@ public final class MessageContentProcessor { database.beginTransaction(); try { - // TODO [stories] check if this works for group stories - RecipientId storyAuthorRecipient = RecipientId.from(storyContext.getAuthorServiceId(), null); - MessageId storyId; + RecipientId storyAuthorRecipient = RecipientId.from(storyContext.getAuthorServiceId(), null); + ParentStoryId parentStoryId; + QuoteModel quoteModel = null; try { - storyId = database.getStoryId(storyAuthorRecipient, storyContext.getSentTimestamp()); + MessageId storyMessageId = database.getStoryId(storyAuthorRecipient, storyContext.getSentTimestamp()); + + if (message.getGroupContext().isPresent()) { + parentStoryId = new ParentStoryId.GroupReply(storyMessageId.getId()); + } else { + MmsMessageRecord story = (MmsMessageRecord) database.getMessageRecord(storyMessageId.getId()); + + parentStoryId = new ParentStoryId.DirectReply(storyMessageId.getId()); + quoteModel = new QuoteModel(storyContext.getSentTimestamp(), storyAuthorRecipient, "", false, story.getSlideDeck().asAttachments(), Collections.emptyList()); + } } catch (NoSuchMessageException e) { warn(content.getTimestamp(), "Couldn't find story for reply.", e); return; @@ -1391,7 +1401,7 @@ public final class MessageContentProcessor { content.getServerReceivedTimestamp(), System.currentTimeMillis(), false, - storyId, + parentStoryId, -1, 0, false, @@ -1400,7 +1410,7 @@ public final class MessageContentProcessor { message.getBody(), Optional.fromNullable(GroupUtil.getGroupContextIfPresent(content)), Optional.absent(), - Optional.absent(), + Optional.fromNullable(quoteModel), Optional.absent(), Optional.absent(), Optional.absent(), diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt b/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt index 8914324ea3..654d454554 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt @@ -4,7 +4,7 @@ import org.thoughtcrime.securesms.attachments.Attachment import org.thoughtcrime.securesms.attachments.PointerAttachment import org.thoughtcrime.securesms.contactshare.Contact import org.thoughtcrime.securesms.database.model.Mention -import org.thoughtcrime.securesms.database.model.MessageId +import org.thoughtcrime.securesms.database.model.ParentStoryId import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.linkpreview.LinkPreview @@ -20,7 +20,7 @@ class IncomingMediaMessage( val body: String? = null, val isPushMessage: Boolean = false, val isStory: Boolean = false, - val parentStoryId: MessageId? = null, + val parentStoryId: ParentStoryId? = null, val sentTimeMillis: Long, val serverTimeMillis: Long, val receivedTimeMillis: Long, @@ -84,7 +84,7 @@ class IncomingMediaMessage( serverTimeMillis: Long, receivedTimeMillis: Long, isStory: Boolean, - parentStoryId: MessageId?, + parentStoryId: ParentStoryId?, subscriptionId: Int, expiresIn: Long, expirationUpdate: Boolean, diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingMediaMessage.java b/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingMediaMessage.java index 65b4ba9e69..40b34515fd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingMediaMessage.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingMediaMessage.java @@ -10,7 +10,7 @@ import org.thoughtcrime.securesms.contactshare.Contact; import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch; import org.thoughtcrime.securesms.database.documents.NetworkFailure; import org.thoughtcrime.securesms.database.model.Mention; -import org.thoughtcrime.securesms.database.model.MessageId; +import org.thoughtcrime.securesms.database.model.ParentStoryId; import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.recipients.Recipient; @@ -31,7 +31,7 @@ public class OutgoingMediaMessage { private final boolean viewOnce; private final QuoteModel outgoingQuote; private final boolean isStory; - private final MessageId parentStoryId; + private final ParentStoryId parentStoryId; private final Set networkFailures = new HashSet<>(); private final Set identityKeyMismatches = new HashSet<>(); @@ -48,7 +48,7 @@ public class OutgoingMediaMessage { boolean viewOnce, int distributionType, boolean isStory, - @Nullable MessageId parentStoryId, + @Nullable ParentStoryId parentStoryId, @Nullable QuoteModel outgoingQuote, @NonNull List contacts, @NonNull List linkPreviews, @@ -84,7 +84,7 @@ public class OutgoingMediaMessage { boolean viewOnce, int distributionType, boolean isStory, - @Nullable MessageId parentStoryId, + @Nullable ParentStoryId parentStoryId, @Nullable QuoteModel outgoingQuote, @NonNull List contacts, @NonNull List linkPreviews, @@ -197,7 +197,7 @@ public class OutgoingMediaMessage { return isStory; } - public @Nullable MessageId getParentStoryId() { + public @Nullable ParentStoryId getParentStoryId() { return parentStoryId; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingSecureMediaMessage.java b/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingSecureMediaMessage.java index 5b3a81078d..de81b58108 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingSecureMediaMessage.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingSecureMediaMessage.java @@ -6,7 +6,7 @@ import androidx.annotation.Nullable; import org.thoughtcrime.securesms.attachments.Attachment; import org.thoughtcrime.securesms.contactshare.Contact; import org.thoughtcrime.securesms.database.model.Mention; -import org.thoughtcrime.securesms.database.model.MessageId; +import org.thoughtcrime.securesms.database.model.ParentStoryId; import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.recipients.Recipient; @@ -23,7 +23,7 @@ public class OutgoingSecureMediaMessage extends OutgoingMediaMessage { long expiresIn, boolean viewOnce, boolean isStory, - @Nullable MessageId parentStoryId, + @Nullable ParentStoryId parentStoryId, @Nullable QuoteModel quote, @NonNull List contacts, @NonNull List previews, diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageViewModel.kt index 17131eefe7..8eeae989c1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageViewModel.kt @@ -8,7 +8,6 @@ import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.kotlin.plusAssign -import io.reactivex.rxjava3.subjects.BehaviorSubject import io.reactivex.rxjava3.subjects.PublishSubject import io.reactivex.rxjava3.subjects.Subject import org.thoughtcrime.securesms.recipients.RecipientId @@ -26,26 +25,13 @@ class StoryViewerPageViewModel( private val store = Store(StoryViewerPageState()) private val disposables = CompositeDisposable() - private val storyViewerDialogSubject: Subject> = BehaviorSubject.createDefault(Optional.empty()) - private val dismissSubject = PublishSubject.create() + private val storyViewerDialogSubject: Subject> = PublishSubject.create() private val storyViewerPlaybackStore = Store(StoryViewerPlaybackState()) val storyViewerPlaybackState: LiveData = storyViewerPlaybackStore.stateLiveData - val groupDirectReplyObservable: Observable> = Observable.combineLatest(storyViewerDialogSubject, dismissSubject) { sheet, dismissed -> - if (sheet.isPresent && sheet.get().type != dismissed) { - sheet - } else { - Optional.empty() - } - }.distinctUntilChanged { previous, current -> - if (current.isPresent) { - previous == current - } else { - false - } - } + val groupDirectReplyObservable: Observable> = storyViewerDialogSubject val state: LiveData = store.stateLiveData diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/reply/direct/StoryDirectReplyRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/reply/direct/StoryDirectReplyRepository.kt index e3f1c53222..0d6448d06c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/reply/direct/StoryDirectReplyRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/reply/direct/StoryDirectReplyRepository.kt @@ -7,6 +7,7 @@ import io.reactivex.rxjava3.schedulers.Schedulers import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord import org.thoughtcrime.securesms.database.model.MessageRecord +import org.thoughtcrime.securesms.database.model.ParentStoryId import org.thoughtcrime.securesms.mms.OutgoingMediaMessage import org.thoughtcrime.securesms.mms.QuoteModel import org.thoughtcrime.securesms.recipients.Recipient @@ -53,7 +54,7 @@ class StoryDirectReplyRepository { false, 0, false, - null, + ParentStoryId.DirectReply(storyId), QuoteModel(message.dateSent, quoteAuthor.id, "", false, message.slideDeck.asAttachments(), null), emptyList(), emptyList(), diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/reply/group/StoryGroupReplySender.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/reply/group/StoryGroupReplySender.kt index e90162194c..183f7c4c8b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/reply/group/StoryGroupReplySender.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/reply/group/StoryGroupReplySender.kt @@ -5,7 +5,7 @@ import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.schedulers.Schedulers import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.model.Mention -import org.thoughtcrime.securesms.database.model.MessageId +import org.thoughtcrime.securesms.database.model.ParentStoryId import org.thoughtcrime.securesms.mms.OutgoingMediaMessage import org.thoughtcrime.securesms.sms.MessageSender @@ -31,7 +31,7 @@ object StoryGroupReplySender { false, 0, false, - MessageId.fromNullable(message.id, true), + ParentStoryId.GroupReply(message.id), null, emptyList(), emptyList(),