From e80b7cf0a27fb607aa3b3e77ce1ff30beedf2722 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 14 Nov 2023 09:16:56 -0800 Subject: [PATCH] Store receipt fields as booleans instead of counts. --- .../test/ConversationElementGenerator.kt | 6 +- .../components/ConversationItemFooter.java | 4 +- .../conversation/ConversationItem.java | 2 +- .../V2ConversationItemTextOnlyViewHolder.kt | 2 +- .../ConversationListItem.java | 2 +- .../securesms/database/MessageTable.kt | 220 ++++++++++-------- .../securesms/database/ThreadBodyUtil.java | 2 +- .../securesms/database/ThreadTable.kt | 40 ++-- .../helpers/SignalDatabaseMigrations.kt | 7 +- .../migration/V211_ReceiptColumnRenames.kt | 23 ++ .../database/model/DisplayRecord.java | 43 ++-- .../database/model/InMemoryMessageRecord.java | 6 +- .../database/model/MessageRecord.java | 10 +- .../database/model/MmsMessageRecord.java | 42 ++-- .../securesms/database/model/StatusUtil.java | 4 +- .../database/model/ThreadRecord.java | 34 +-- .../MessageDetailsRepository.java | 4 +- .../messages/ReceiptMessageProcessor.kt | 13 +- .../revealable/ViewOnceMessageView.java | 2 +- .../landing/StoriesLandingRepository.kt | 2 +- .../securesms/stories/my/MyStoriesItem.kt | 2 +- .../viewer/page/StoryViewerPageRepository.kt | 2 +- .../securesms/database/TestMms.kt | 4 +- .../securesms/database/FakeMessageRecords.kt | 12 +- 24 files changed, 275 insertions(+), 213 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V211_ReceiptColumnRenames.kt diff --git a/app/src/debug/java/org/thoughtcrime/securesms/components/settings/app/internal/conversation/test/ConversationElementGenerator.kt b/app/src/debug/java/org/thoughtcrime/securesms/components/settings/app/internal/conversation/test/ConversationElementGenerator.kt index 9b462c574f..9fb49d98ef 100644 --- a/app/src/debug/java/org/thoughtcrime/securesms/components/settings/app/internal/conversation/test/ConversationElementGenerator.kt +++ b/app/src/debug/java/org/thoughtcrime/securesms/components/settings/app/internal/conversation/test/ConversationElementGenerator.kt @@ -86,7 +86,7 @@ class ConversationElementGenerator { now, now, now, - 1, + true, 1, testMessage, SlideDeck(), @@ -97,7 +97,7 @@ class ConversationElementGenerator { 0, 0, false, - 1, + true, null, emptyList(), emptyList(), @@ -106,7 +106,7 @@ class ConversationElementGenerator { false, false, now, - 1, + true, now, null, StoryType.NONE, diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemFooter.java b/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemFooter.java index 8fbde58284..a78c9437ae 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemFooter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemFooter.java @@ -416,7 +416,7 @@ public class ConversationItemFooter extends ConstraintLayout { deliveryStatusView.setNone(); } else if (messageRecord.isPending()) { deliveryStatusView.setPending(); - } else if (messageRecord.isRemoteRead()) { + } else if (messageRecord.hasReadReceipt()) { deliveryStatusView.setRead(); } else if (messageRecord.isDelivered()) { deliveryStatusView.setDelivered(); @@ -433,7 +433,7 @@ public class ConversationItemFooter extends ConstraintLayout { if (mmsMessageRecord.getSlideDeck().getAudioSlide() != null) { showAudioDurationViews(); - if (messageRecord.getViewedReceiptCount() > 0 || (messageRecord.isOutgoing() && Objects.equals(messageRecord.getToRecipient(), Recipient.self()))) { + if (messageRecord.isViewed() || (messageRecord.isOutgoing() && Objects.equals(messageRecord.getToRecipient(), Recipient.self()))) { revealDot.setProgress(1f); } else { revealDot.setProgress(0f); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java index d45cac36c5..52600d9d5d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java @@ -2243,7 +2243,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo @Override public @Nullable Projection getOpenableGiftProjection(boolean isAnimating) { - if (!isGiftMessage(messageRecord) || messageRecord.isRemoteDelete() || (messageRecord.getViewedReceiptCount() > 0 && !isAnimating)) { + if (!isGiftMessage(messageRecord) || messageRecord.isRemoteDelete() || (messageRecord.isViewed() && !isAnimating)) { return null; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt index d4bfe295e3..9f0da5a09b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt @@ -700,7 +700,7 @@ open class V2ConversationItemTextOnlyViewHolder>( when { record.isPending -> deliveryStatus.setPending() - record.isRemoteRead -> deliveryStatus.setRead() + record.hasReadReceipt() -> deliveryStatus.setRead() record.isDelivered -> deliveryStatus.setDelivered() else -> deliveryStatus.setSent() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java index cf5c7e11fe..2ccfb89dea 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java @@ -516,7 +516,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind } else { if (thread.isPending()) { deliveryStatusIndicator.setPending(); - } else if (thread.isRemoteRead()) { + } else if (thread.hasReadReceipt()) { deliveryStatusIndicator.setRead(); } else if (thread.isDelivered()) { deliveryStatusIndicator.setDelivered(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt index 08b70e4406..5ba7c3d6d5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt @@ -37,6 +37,7 @@ import org.signal.core.util.SqlUtil.buildCustomCollectionQuery import org.signal.core.util.SqlUtil.buildSingleCollectionQuery import org.signal.core.util.SqlUtil.buildTrueUpdateQuery import org.signal.core.util.SqlUtil.getNextAutoIncrementId +import org.signal.core.util.Stopwatch import org.signal.core.util.count import org.signal.core.util.delete import org.signal.core.util.exists @@ -164,9 +165,9 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat const val FROM_RECIPIENT_ID = "from_recipient_id" const val FROM_DEVICE_ID = "from_device_id" const val TO_RECIPIENT_ID = "to_recipient_id" - const val DELIVERY_RECEIPT_COUNT = "delivery_receipt_count" - const val READ_RECEIPT_COUNT = "read_receipt_count" - const val VIEWED_RECEIPT_COUNT = "viewed_receipt_count" + const val HAS_DELIVERY_RECEIPT = "has_delivery_receipt" + const val HAS_READ_RECEIPT = "has_read_receipt" + const val VIEWED_COLUMN = "viewed" const val MISMATCHED_IDENTITIES = "mismatched_identities" const val SMS_SUBSCRIPTION_ID = "subscription_id" const val EXPIRES_IN = "expires_in" @@ -227,9 +228,9 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat $MMS_TRANSACTION_ID TEXT, $SMS_SUBSCRIPTION_ID INTEGER DEFAULT -1, $RECEIPT_TIMESTAMP INTEGER DEFAULT -1, - $DELIVERY_RECEIPT_COUNT INTEGER DEFAULT 0, - $READ_RECEIPT_COUNT INTEGER DEFAULT 0, - $VIEWED_RECEIPT_COUNT INTEGER DEFAULT 0, + $HAS_DELIVERY_RECEIPT INTEGER DEFAULT 0, + $HAS_READ_RECEIPT INTEGER DEFAULT 0, + $VIEWED_COLUMN INTEGER DEFAULT 0, $MISMATCHED_IDENTITIES TEXT DEFAULT NULL, $NETWORK_FAILURES TEXT DEFAULT NULL, $EXPIRES_IN INTEGER DEFAULT 0, @@ -307,8 +308,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat FROM_RECIPIENT_ID, FROM_DEVICE_ID, TO_RECIPIENT_ID, - DELIVERY_RECEIPT_COUNT, - READ_RECEIPT_COUNT, + HAS_DELIVERY_RECEIPT, + HAS_READ_RECEIPT, MISMATCHED_IDENTITIES, NETWORK_FAILURES, SMS_SUBSCRIPTION_ID, @@ -330,7 +331,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat REMOTE_DELETED, MENTIONS_SELF, NOTIFIED_TIMESTAMP, - VIEWED_RECEIPT_COUNT, + VIEWED_COLUMN, RECEIPT_TIMESTAMP, MESSAGE_RANGES, STORY_TYPE, @@ -665,7 +666,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat return readableDatabase .select(ID, FROM_RECIPIENT_ID, DATE_SENT, TYPE, THREAD_ID, STORY_TYPE) .from(TABLE_NAME) - .where("$THREAD_ID = ? AND $VIEWED_RECEIPT_COUNT > 0 AND $TYPE & ${MessageTypes.BASE_INBOX_TYPE} = ${MessageTypes.BASE_INBOX_TYPE}", threadId) + .where("$THREAD_ID = ? AND $VIEWED_COLUMN > 0 AND $TYPE & ${MessageTypes.BASE_INBOX_TYPE} = ${MessageTypes.BASE_INBOX_TYPE}", threadId) .run() .readToList { it.toMarkedMessageInfo(outgoing = false) } } @@ -687,7 +688,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat val results: List = readableDatabase .select(ID, FROM_RECIPIENT_ID, DATE_SENT, TYPE, THREAD_ID, STORY_TYPE) .from(TABLE_NAME) - .where("$ID IN (${Util.join(messageIds, ",")}) AND $VIEWED_RECEIPT_COUNT = 0") + .where("$ID IN (${Util.join(messageIds, ",")}) AND $VIEWED_COLUMN = 0") .run() .readToList { cursor -> val type = cursor.requireLong(TYPE) @@ -707,7 +708,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat writableDatabase .update(TABLE_NAME) .values( - VIEWED_RECEIPT_COUNT to 1, + VIEWED_COLUMN to 1, RECEIPT_TIMESTAMP to currentTime ) .where(query.where, query.whereArgs) @@ -734,7 +735,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat val results: List = readableDatabase .select(ID, TO_RECIPIENT_ID, DATE_SENT, THREAD_ID, STORY_TYPE) .from(TABLE_NAME) - .where("""$ID IN (${Util.join(messageIds, ",")}) AND ($outgoingTypeClause) AND ($TYPE & ${MessageTypes.SPECIAL_TYPES_MASK} = ${MessageTypes.SPECIAL_TYPE_GIFT_BADGE}) AND $VIEWED_RECEIPT_COUNT = 0""") + .where("""$ID IN (${Util.join(messageIds, ",")}) AND ($outgoingTypeClause) AND ($TYPE & ${MessageTypes.SPECIAL_TYPES_MASK} = ${MessageTypes.SPECIAL_TYPE_GIFT_BADGE}) AND $VIEWED_COLUMN = 0""") .run() .readToList { it.toMarkedMessageInfo(outgoing = true) } @@ -745,7 +746,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat writableDatabase .update(TABLE_NAME) .values( - VIEWED_RECEIPT_COUNT to 1, + VIEWED_COLUMN to 1, RECEIPT_TIMESTAMP to currentTime ) .where(query.where, query.whereArgs) @@ -1259,7 +1260,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat fun getUnreadStories(recipientId: RecipientId, limit: Int): Reader { val threadId = threads.getThreadIdIfExistsFor(recipientId) - val query = "$IS_STORY_CLAUSE AND NOT ($outgoingTypeClause) AND $THREAD_ID = ? AND $VIEWED_RECEIPT_COUNT = ?" + val query = "$IS_STORY_CLAUSE AND NOT ($outgoingTypeClause) AND $THREAD_ID = ? AND $VIEWED_COLUMN = ?" val args = buildArgs(threadId, 0) return MmsReader(rawQueryWithAttachments(query, args, false, limit.toLong())) } @@ -1312,7 +1313,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat writableDatabase.withinTransaction { db -> db.select(FROM_RECIPIENT_ID) .from(TABLE_NAME) - .where("$IS_STORY_CLAUSE AND $DATE_SENT IN ($timestamps) AND NOT ($outgoingTypeClause) AND $VIEWED_RECEIPT_COUNT > 0") + .where("$IS_STORY_CLAUSE AND $DATE_SENT IN ($timestamps) AND NOT ($outgoingTypeClause) AND $VIEWED_COLUMN > 0") .run() .readToList { cursor -> RecipientId.from(cursor.requireLong(FROM_RECIPIENT_ID)) } .forEach { id -> recipients.updateLastStoryViewTimestamp(id) } @@ -1332,7 +1333,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat val hasUnviewedStories = readableDatabase .exists(TABLE_NAME) - .where("$IS_STORY_CLAUSE AND $THREAD_ID = ? AND $VIEWED_RECEIPT_COUNT = ? AND NOT ($outgoingTypeClause)", threadId, 0) + .where("$IS_STORY_CLAUSE AND $THREAD_ID = ? AND $VIEWED_COLUMN = ? AND NOT ($outgoingTypeClause)", threadId, 0) .run() return if (hasUnviewedStories) { @@ -1369,7 +1370,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat WHERE $IS_STORY_CLAUSE AND ($outgoingTypeClause) = 0 AND - $VIEWED_RECEIPT_COUNT = 0 AND + $VIEWED_COLUMN = 0 AND $TABLE_NAME.$READ = 0 """ @@ -1390,10 +1391,10 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat $TABLE_NAME.$ID AS mms_id, ${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID}, ($outgoingTypeClause) AS is_outgoing, - $VIEWED_RECEIPT_COUNT, + $VIEWED_COLUMN, $TABLE_NAME.$DATE_SENT, $RECEIPT_TIMESTAMP, - ($outgoingTypeClause) = 0 AND $VIEWED_RECEIPT_COUNT = 0 AS is_unread + ($outgoingTypeClause) = 0 AND $VIEWED_COLUMN = 0 AS is_unread FROM $TABLE_NAME JOIN ${ThreadTable.TABLE_NAME} ON $TABLE_NAME.$THREAD_ID = ${ThreadTable.TABLE_NAME}.${ThreadTable.ID} WHERE @@ -1403,8 +1404,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat ORDER BY is_unread DESC, CASE - WHEN is_outgoing = 0 AND $VIEWED_RECEIPT_COUNT = 0 THEN $TABLE_NAME.$DATE_SENT - WHEN is_outgoing = 0 AND viewed_receipt_count > 0 THEN $RECEIPT_TIMESTAMP + WHEN is_outgoing = 0 AND $VIEWED_COLUMN = 0 THEN $TABLE_NAME.$DATE_SENT + WHEN is_outgoing = 0 AND $VIEWED_COLUMN > 0 THEN $RECEIPT_TIMESTAMP WHEN is_outgoing = 1 THEN $TABLE_NAME.$DATE_SENT END DESC """ @@ -1686,7 +1687,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat val query = buildMeaningfulMessagesQuery(threadId) return readableDatabase - .select(ID, DELIVERY_RECEIPT_COUNT, READ_RECEIPT_COUNT, VIEWED_RECEIPT_COUNT, TYPE) + .select(ID, HAS_DELIVERY_RECEIPT, HAS_READ_RECEIPT, TYPE) .from(TABLE_NAME) .where(query.where, query.whereArgs) .orderBy("$DATE_RECEIVED DESC") @@ -1699,9 +1700,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat } return MessageReceiptStatus( - deliveryCount = cursor.requireInt(DELIVERY_RECEIPT_COUNT), - readCount = cursor.requireInt(READ_RECEIPT_COUNT), - viewedCount = cursor.requireInt(VIEWED_RECEIPT_COUNT), + hasDeliveryReceipt = cursor.requireBoolean(HAS_DELIVERY_RECEIPT), + hasReadReceipt = cursor.requireBoolean(HAS_READ_RECEIPT), type = cursor.requireLong(TYPE) ) } else { @@ -2817,7 +2817,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat contentValues.put(FROM_RECIPIENT_ID, Recipient.self().id.serialize()) contentValues.put(FROM_DEVICE_ID, SignalStore.account().deviceId) contentValues.put(TO_RECIPIENT_ID, message.threadRecipient.id.serialize()) - contentValues.put(DELIVERY_RECEIPT_COUNT, earlyDeliveryReceipts.values.sumOf { it.count }) + contentValues.put(HAS_DELIVERY_RECEIPT, earlyDeliveryReceipts.values.sumOf { it.count }) contentValues.put(RECEIPT_TIMESTAMP, earlyDeliveryReceipts.values.map { it.timestamp }.maxOrNull() ?: -1L) contentValues.put(STORY_TYPE, message.storyType.code) contentValues.put(PARENT_STORY_ID, if (message.parentStoryId != null) message.parentStoryId.serialize() else 0) @@ -2832,7 +2832,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat } if (message.threadRecipient.isSelf && hasAudioAttachment(message.attachments)) { - contentValues.put(VIEWED_RECEIPT_COUNT, 1L) + contentValues.put(VIEWED_COLUMN, 1L) } val quoteAttachments: MutableList = mutableListOf() @@ -4074,8 +4074,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat .run() } - fun incrementDeliveryReceiptCounts(targetTimestamps: List, receiptAuthor: RecipientId, receiptSentTimestamp: Long): Set { - return incrementReceiptCounts(targetTimestamps, receiptAuthor, receiptSentTimestamp, ReceiptType.DELIVERY) + fun incrementDeliveryReceiptCounts(targetTimestamps: List, receiptAuthor: RecipientId, receiptSentTimestamp: Long, stopwatch: Stopwatch? = null): Set { + return incrementReceiptCounts(targetTimestamps, receiptAuthor, receiptSentTimestamp, ReceiptType.DELIVERY, stopwatch = stopwatch) } fun incrementDeliveryReceiptCount(targetTimestamps: Long, receiptAuthor: RecipientId, receiptSentTimestamp: Long): Boolean { @@ -4164,13 +4164,13 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat * * @return All of the target timestamps that couldn't be found in the table. */ - private fun incrementReceiptCounts(targetTimestamps: List, receiptAuthor: RecipientId, receiptSentTimestamp: Long, receiptType: ReceiptType, messageQualifier: MessageQualifier = MessageQualifier.ALL): Set { + private fun incrementReceiptCounts(targetTimestamps: List, receiptAuthor: RecipientId, receiptSentTimestamp: Long, receiptType: ReceiptType, messageQualifier: MessageQualifier = MessageQualifier.ALL, stopwatch: Stopwatch? = null): Set { val messageUpdates: MutableSet = HashSet() val missingTargetTimestamps: MutableSet = HashSet() writableDatabase.withinTransaction { for (targetTimestamp in targetTimestamps) { - val updates: Set = incrementReceiptCountInternal(targetTimestamp, receiptAuthor, receiptSentTimestamp, receiptType, messageQualifier) + val updates: Set = incrementReceiptCountInternal(targetTimestamp, receiptAuthor, receiptSentTimestamp, receiptType, messageQualifier, stopwatch) if (updates.isNotEmpty()) { messageUpdates += updates } else { @@ -4180,7 +4180,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat for (update in messageUpdates) { if (update.shouldUpdateSnippet) { - threads.updateReceiptStatus(update.messageId.id, update.threadId) + threads.updateReceiptStatus(update.messageId.id, update.threadId, stopwatch) } } } @@ -4198,71 +4198,94 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat notifyConversationListListeners() } + stopwatch?.split("observers") + return missingTargetTimestamps } - private fun incrementReceiptCountInternal(targetTimestamp: Long, receiptAuthor: RecipientId, receiptSentTimestamp: Long, receiptType: ReceiptType, messageQualifier: MessageQualifier): Set { - val messageUpdates: MutableSet = HashSet() - + private fun incrementReceiptCountInternal(targetTimestamp: Long, receiptAuthor: RecipientId, receiptSentTimestamp: Long, receiptType: ReceiptType, messageQualifier: MessageQualifier, stopwatch: Stopwatch? = null): Set { val qualifierWhere: String = when (messageQualifier) { MessageQualifier.NORMAL -> " AND NOT ($IS_STORY_CLAUSE)" MessageQualifier.STORY -> " AND $IS_STORY_CLAUSE" MessageQualifier.ALL -> "" } - var found = false - var hasStory = false - writableDatabase.rawQuery( - """ + // Note: While it is true that multiple messages can have the same (sent, author) pair, this should only happen for stories, which are handled below. + val receiptData: ReceiptData? = readableDatabase + .select(ID, THREAD_ID, STORY_TYPE, receiptType.columnName, TO_RECIPIENT_ID) + .from(TABLE_NAME) + .where( + """ + $DATE_SENT = $targetTimestamp AND + $FROM_RECIPIENT_ID = ? AND + ( + $TO_RECIPIENT_ID = ? OR + EXISTS ( + SELECT 1 + FROM ${RecipientTable.TABLE_NAME} + WHERE + ${RecipientTable.TABLE_NAME}.${RecipientTable.ID} = $TO_RECIPIENT_ID AND + ${RecipientTable.TABLE_NAME}.${RecipientTable.TYPE} != ${RecipientTable.RecipientType.INDIVIDUAL.id} + ) + ) + $qualifierWhere + """, + Recipient.self().id, + receiptAuthor + ) + .limit(1) + .run() + .readToSingleObject { cursor -> + ReceiptData( + messageId = cursor.requireLong(ID), + threadId = cursor.requireLong(THREAD_ID), + storyType = StoryType.fromCode(cursor.requireInt(STORY_TYPE)), + marked = cursor.requireBoolean(receiptType.columnName), + forIndividualChat = cursor.requireLong(TO_RECIPIENT_ID) == receiptAuthor.toLong() + ) + } + + stopwatch?.split("receipt-query") + + if (receiptData == null) { + if (receiptType == ReceiptType.DELIVERY) { + earlyDeliveryReceiptCache.increment(targetTimestamp, receiptAuthor, receiptSentTimestamp) + } + + return emptySet() + } + + if (!receiptData.marked) { + // We set the receipt_timestamp to the max of the two values because that single column represents the timestamp of the last receipt of any type. + // That means we want to update it for each new receipt type, but we never want the time to go backwards. + writableDatabase.execSQL( + """ UPDATE $TABLE_NAME SET - ${receiptType.columnName} = ${receiptType.columnName} + 1, - $RECEIPT_TIMESTAMP = CASE - WHEN ${receiptType.columnName} = 0 THEN MAX($RECEIPT_TIMESTAMP, $receiptSentTimestamp) - ELSE $RECEIPT_TIMESTAMP - END + ${receiptType.columnName} = 1, + $RECEIPT_TIMESTAMP = MAX($RECEIPT_TIMESTAMP, $receiptSentTimestamp) WHERE - $DATE_SENT = $targetTimestamp AND - $FROM_RECIPIENT_ID = ? AND - ( - $TO_RECIPIENT_ID = ? OR - EXISTS ( - SELECT 1 - FROM ${RecipientTable.TABLE_NAME} - WHERE - ${RecipientTable.TABLE_NAME}.${RecipientTable.ID} = $TO_RECIPIENT_ID AND - ${RecipientTable.TABLE_NAME}.${RecipientTable.TYPE} != ${RecipientTable.RecipientType.INDIVIDUAL.id} - ) - ) - $qualifierWhere - RETURNING $ID, $THREAD_ID, $STORY_TYPE, ${receiptType.columnName} - """, - buildArgs(Recipient.self().id, receiptAuthor) - ).forEach { cursor -> - val messageId = cursor.requireLong(ID) - val threadId = cursor.requireLong(THREAD_ID) - val storyType = StoryType.fromCode(cursor.requireInt(STORY_TYPE)) - val receiptCount = cursor.requireInt(receiptType.columnName) + $ID = ${receiptData.messageId} + """ + ) + } + stopwatch?.split("receipt-update") - groupReceipts.update(receiptAuthor, messageId, receiptType.groupStatus, receiptSentTimestamp) - messageUpdates += MessageReceiptUpdate(threadId, MessageId(messageId), receiptType != ReceiptType.VIEWED && receiptCount == 1) - - found = true - hasStory = storyType != StoryType.NONE + if (!receiptData.forIndividualChat) { + groupReceipts.update(receiptAuthor, receiptData.messageId, receiptType.groupStatus, receiptSentTimestamp) } - if (!found && receiptType == ReceiptType.DELIVERY) { - earlyDeliveryReceiptCache.increment(targetTimestamp, receiptAuthor, receiptSentTimestamp) - } + stopwatch?.split("group-receipt") - if (hasStory) { - for (messageId in storySends.getStoryMessagesFor(receiptAuthor, targetTimestamp)) { - groupReceipts.update(receiptAuthor, messageId.id, receiptType.groupStatus, receiptSentTimestamp) - messageUpdates += MessageReceiptUpdate(-1, messageId, false) - } + return if (receiptData.storyType != StoryType.NONE) { + val storyMessageIds = storySends.getStoryMessagesFor(receiptAuthor, targetTimestamp) + storyMessageIds.forEach { messageId -> groupReceipts.update(receiptAuthor, messageId.id, receiptType.groupStatus, receiptSentTimestamp) } + storyMessageIds.map { messageId -> MessageReceiptUpdate(-1, messageId, false) }.toSet() + } else { + setOf(MessageReceiptUpdate(receiptData.threadId, MessageId(receiptData.messageId), shouldUpdateSnippet = receiptType != ReceiptType.VIEWED && !receiptData.marked)) + }.also { + stopwatch?.split("stories") } - - return messageUpdates } /** @@ -4736,15 +4759,22 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat } protected enum class ReceiptType(val columnName: String, val groupStatus: Int) { - READ(READ_RECEIPT_COUNT, GroupReceiptTable.STATUS_READ), - DELIVERY(DELIVERY_RECEIPT_COUNT, GroupReceiptTable.STATUS_DELIVERED), - VIEWED(VIEWED_RECEIPT_COUNT, GroupReceiptTable.STATUS_VIEWED) + READ(HAS_READ_RECEIPT, GroupReceiptTable.STATUS_READ), + DELIVERY(HAS_DELIVERY_RECEIPT, GroupReceiptTable.STATUS_DELIVERED), + VIEWED(VIEWED_COLUMN, GroupReceiptTable.STATUS_VIEWED) } + data class ReceiptData( + val messageId: Long, + val threadId: Long, + val storyType: StoryType, + val marked: Boolean, + val forIndividualChat: Boolean + ) + data class MessageReceiptStatus( - val readCount: Int, - val deliveryCount: Int, - val viewedCount: Int, + val hasReadReceipt: Boolean, + val hasDeliveryReceipt: Boolean, val type: Long ) @@ -4942,8 +4972,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat val fromRecipientId = cursor.requireLong(FROM_RECIPIENT_ID) val fromDeviceId = cursor.requireInt(FROM_DEVICE_ID) val toRecipientId = cursor.requireLong(TO_RECIPIENT_ID) - val deliveryReceiptCount = cursor.requireInt(DELIVERY_RECEIPT_COUNT) - var readReceiptCount = cursor.requireInt(READ_RECEIPT_COUNT) + val hasDeliveryReceipt = cursor.requireBoolean(HAS_DELIVERY_RECEIPT) + var hasReadReceipt = cursor.requireBoolean(HAS_READ_RECEIPT) val body = cursor.requireString(BODY) val mismatchDocument = cursor.requireString(MISMATCHED_IDENTITIES) val networkDocument = cursor.requireString(NETWORK_FAILURES) @@ -4955,7 +4985,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat val remoteDelete = cursor.requireBoolean(REMOTE_DELETED) val mentionsSelf = cursor.requireBoolean(MENTIONS_SELF) val notifiedTimestamp = cursor.requireLong(NOTIFIED_TIMESTAMP) - var viewedReceiptCount = cursor.requireInt(VIEWED_RECEIPT_COUNT) + var isViewed = cursor.requireBoolean(VIEWED_COLUMN) val receiptTimestamp = cursor.requireLong(RECEIPT_TIMESTAMP) val messageRangesData = cursor.requireBlob(MESSAGE_RANGES) val storyType = StoryType.fromCode(cursor.requireInt(STORY_TYPE)) @@ -4966,9 +4996,9 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat val editCount = cursor.requireInt(REVISION_NUMBER) if (!TextSecurePreferences.isReadReceiptsEnabled(context)) { - readReceiptCount = 0 + hasReadReceipt = false if (MessageTypes.isOutgoingMessageType(box) && !storyType.isStory) { - viewedReceiptCount = 0 + isViewed = false } } @@ -5019,7 +5049,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat dateSent, dateReceived, dateServer, - deliveryReceiptCount, + hasDeliveryReceipt, threadId, body, slideDeck, @@ -5030,7 +5060,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat expiresIn, expireStarted, isViewOnce, - readReceiptCount, + hasReadReceipt, quote, contacts, previews, @@ -5039,7 +5069,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat remoteDelete, mentionsSelf, notifiedTimestamp, - viewedReceiptCount, + isViewed, receiptTimestamp, messageRanges, storyType, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadBodyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadBodyUtil.java index b1c07c05fc..1f00b92cdb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadBodyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadBodyUtil.java @@ -92,7 +92,7 @@ public final class ThreadBodyUtil { private static @NonNull String getGiftSummary(@NonNull Context context, @NonNull MessageRecord messageRecord) { if (messageRecord.isOutgoing()) { return context.getString(R.string.ThreadRecord__you_donated_for_s, messageRecord.getToRecipient().getShortDisplayName(context)); - } else if (messageRecord.getViewedReceiptCount() > 0) { + } else if (messageRecord.isViewed()) { return context.getString(R.string.ThreadRecord__you_redeemed_a_badge); } else { return context.getString(R.string.ThreadRecord__s_donated_for_you, messageRecord.getFromRecipient().getShortDisplayName(context)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt index 6cd2a63dcc..a04d0208fd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt @@ -13,6 +13,7 @@ import org.json.JSONObject import org.jsoup.helper.StringUtil import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil +import org.signal.core.util.Stopwatch import org.signal.core.util.delete import org.signal.core.util.exists import org.signal.core.util.logging.Log @@ -23,6 +24,7 @@ import org.signal.core.util.requireInt import org.signal.core.util.requireLong import org.signal.core.util.requireString import org.signal.core.util.select +import org.signal.core.util.toInt import org.signal.core.util.update import org.signal.core.util.withinTransaction import org.signal.libsignal.zkgroup.InvalidInputException @@ -97,8 +99,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa const val SNIPPET_EXTRAS = "snippet_extras" const val ARCHIVED = "archived" const val STATUS = "status" - const val DELIVERY_RECEIPT_COUNT = "delivery_receipt_count" - const val READ_RECEIPT_COUNT = "read_receipt_count" + const val HAS_DELIVERY_RECEIPT = "has_delivery_receipt" + const val HAS_READ_RECEIPT = "has_read_receipt" const val EXPIRES_IN = "expires_in" const val LAST_SEEN = "last_seen" const val HAS_SENT = "has_sent" @@ -127,8 +129,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa $UNREAD_COUNT INTEGER DEFAULT 0, $ARCHIVED INTEGER DEFAULT 0, $STATUS INTEGER DEFAULT 0, - $DELIVERY_RECEIPT_COUNT INTEGER DEFAULT 0, - $READ_RECEIPT_COUNT INTEGER DEFAULT 0, + $HAS_DELIVERY_RECEIPT INTEGER DEFAULT 0, + $HAS_READ_RECEIPT INTEGER DEFAULT 0, $EXPIRES_IN INTEGER DEFAULT 0, $LAST_SEEN INTEGER DEFAULT 0, $HAS_SENT INTEGER DEFAULT 0, @@ -164,10 +166,10 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa SNIPPET_EXTRAS, ARCHIVED, STATUS, - DELIVERY_RECEIPT_COUNT, + HAS_DELIVERY_RECEIPT, EXPIRES_IN, LAST_SEEN, - READ_RECEIPT_COUNT, + HAS_READ_RECEIPT, LAST_SCROLLED, PINNED, UNREAD_SELF_MENTION_COUNT @@ -242,8 +244,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa SNIPPET_EXTRAS to extraSerialized, MEANINGFUL_MESSAGES to if (meaningfulMessages) 1 else 0, STATUS to status, - DELIVERY_RECEIPT_COUNT to deliveryReceiptCount, - READ_RECEIPT_COUNT to readReceiptCount, + HAS_DELIVERY_RECEIPT to deliveryReceiptCount, + HAS_READ_RECEIPT to readReceiptCount, EXPIRES_IN to expiresIn, ACTIVE to 1, UNREAD_COUNT to unreadCount, @@ -1406,16 +1408,17 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa * The idea here is that if it _is_ the most meaningful message, we can set the new status. If it's not, there's no need to update * the thread at all. */ - fun updateReceiptStatus(messageId: Long, threadId: Long) { + fun updateReceiptStatus(messageId: Long, threadId: Long, stopwatch: Stopwatch? = null) { val status = messages.getReceiptStatusIfItsTheMostRecentMeaningfulMessage(messageId, threadId) + stopwatch?.split("thread-query") if (status != null) { Log.d(TAG, "Updating receipt status for thread $threadId") writableDatabase .update(TABLE_NAME) .values( - DELIVERY_RECEIPT_COUNT to status.deliveryCount, - READ_RECEIPT_COUNT to status.readCount, + HAS_DELIVERY_RECEIPT to status.hasDeliveryReceipt.toInt(), + HAS_READ_RECEIPT to status.hasReadReceipt.toInt(), STATUS to when { MessageTypes.isFailedMessageType(status.type) -> MessageTable.Status.STATUS_FAILED MessageTypes.isSentType(status.type) -> MessageTable.Status.STATUS_COMPLETE @@ -1428,6 +1431,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa } else { Log.d(TAG, "Receipt was for an old message, not updating thread.") } + stopwatch?.split("thread-update") } private fun update(threadId: Long, unarchive: Boolean, allowDeletion: Boolean, notifyListeners: Boolean): Boolean { @@ -1506,11 +1510,11 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa extra = getExtrasFor(record, threadBody), date = record.timestamp, status = record.deliveryStatus, - deliveryReceiptCount = record.deliveryReceiptCount, + deliveryReceiptCount = record.hasDeliveryReceipt().toInt(), type = record.type, unarchive = unarchive, expiresIn = record.expiresIn, - readReceiptCount = record.readReceiptCount, + readReceiptCount = record.hasReadReceipt().toInt(), unreadCount = unreadCount, unreadMentionCount = unreadMentionCount ) @@ -1675,8 +1679,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa UNREAD_COUNT to 0, ARCHIVED to 0, STATUS to 0, - DELIVERY_RECEIPT_COUNT to 0, - READ_RECEIPT_COUNT to 0, + HAS_DELIVERY_RECEIPT to 0, + HAS_READ_RECEIPT to 0, EXPIRES_IN to 0, LAST_SEEN to 0, HAS_SENT to 0, @@ -1890,7 +1894,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa Recipient(recipientId, details, true) } - val readReceiptCount = if (TextSecurePreferences.isReadReceiptsEnabled(context)) cursor.requireInt(READ_RECEIPT_COUNT) else 0 + val hasReadReceipt = TextSecurePreferences.isReadReceiptsEnabled(context) && cursor.requireBoolean(HAS_READ_RECEIPT) val extraString = cursor.getString(cursor.getColumnIndexOrThrow(SNIPPET_EXTRAS)) val extra: Extra? = if (extraString != null) { try { @@ -1924,8 +1928,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa .setDate(cursor.requireLong(DATE)) .setArchived(cursor.requireBoolean(ARCHIVED)) .setDeliveryStatus(cursor.requireInt(STATUS).toLong()) - .setDeliveryReceiptCount(cursor.requireInt(DELIVERY_RECEIPT_COUNT)) - .setReadReceiptCount(readReceiptCount) + .setHasDeliveryReceipt(cursor.requireBoolean(HAS_DELIVERY_RECEIPT)) + .setHasReadReceipt(hasReadReceipt) .setExpiresIn(cursor.requireLong(EXPIRES_IN)) .setLastSeen(cursor.requireLong(LAST_SEEN)) .setSnippetUri(getSnippetUri(cursor)) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt index 00bf93a7fb..50f068beb3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt @@ -65,6 +65,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V206_AddConversatio import org.thoughtcrime.securesms.database.helpers.migration.V207_AddChunkSizeColumn import org.thoughtcrime.securesms.database.helpers.migration.V209_ClearRecipientPniFromAciColumn import org.thoughtcrime.securesms.database.helpers.migration.V210_FixPniPossibleColumns +import org.thoughtcrime.securesms.database.helpers.migration.V211_ReceiptColumnRenames /** * Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness. @@ -73,7 +74,7 @@ object SignalDatabaseMigrations { val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass) - const val DATABASE_VERSION = 210 + const val DATABASE_VERSION = 211 @JvmStatic fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { @@ -324,6 +325,10 @@ object SignalDatabaseMigrations { if (oldVersion < 210) { V210_FixPniPossibleColumns.migrate(context, db, oldVersion, newVersion) } + + if (oldVersion < 211) { + V211_ReceiptColumnRenames.migrate(context, db, oldVersion, newVersion) + } } @JvmStatic diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V211_ReceiptColumnRenames.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V211_ReceiptColumnRenames.kt new file mode 100644 index 0000000000..da42267046 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V211_ReceiptColumnRenames.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.database.helpers.migration + +import android.app.Application +import net.zetetic.database.sqlcipher.SQLiteDatabase + +/** + */ +@Suppress("ClassName") +object V211_ReceiptColumnRenames : SignalDatabaseMigration { + override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + db.execSQL("ALTER TABLE message RENAME COLUMN delivery_receipt_count TO has_delivery_receipt") + db.execSQL("ALTER TABLE message RENAME COLUMN read_receipt_count TO has_read_receipt") + db.execSQL("ALTER TABLE message RENAME COLUMN viewed_receipt_count TO viewed") + + db.execSQL("ALTER TABLE thread RENAME COLUMN delivery_receipt_count TO has_delivery_receipt") + db.execSQL("ALTER TABLE thread RENAME COLUMN read_receipt_count TO has_read_receipt") + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java index 7837619cbe..2193327e0d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java @@ -46,13 +46,13 @@ public abstract class DisplayRecord { private final long threadId; private final String body; private final int deliveryStatus; - private final int deliveryReceiptCount; - private final int readReceiptCount; - private final int viewReceiptCount; + private final boolean hasDeliveryReceipt; + private final boolean hasReadReceipt; + private final boolean viewed; DisplayRecord(String body, Recipient fromRecipient, Recipient toRecipient, long dateSent, - long dateReceived, long threadId, int deliveryStatus, int deliveryReceiptCount, - long type, int readReceiptCount, int viewReceiptCount) + long dateReceived, long threadId, int deliveryStatus, boolean hasDeliveryReceipt, + long type, boolean hasReadReceipt, boolean viewed) { this.threadId = threadId; this.fromRecipient = fromRecipient; @@ -61,10 +61,10 @@ public abstract class DisplayRecord { this.dateReceived = dateReceived; this.type = type; this.body = body; - this.deliveryReceiptCount = deliveryReceiptCount; - this.readReceiptCount = readReceiptCount; + this.hasDeliveryReceipt = hasDeliveryReceipt; + this.hasReadReceipt = hasReadReceipt; + this.viewed = viewed; this.deliveryStatus = deliveryStatus; - this.viewReceiptCount = viewReceiptCount; } public @NonNull String getBody() { @@ -203,36 +203,25 @@ public abstract class DisplayRecord { return deliveryStatus; } - public int getDeliveryReceiptCount() { - return deliveryReceiptCount; + public boolean hasDeliveryReceipt() { + return hasDeliveryReceipt; } - public int getReadReceiptCount() { - return readReceiptCount; - } /** - * For outgoing messages, this is incremented whenever a remote recipient has viewed our message - * and sends us a VIEWED receipt. For incoming messages, this is an indication of whether local - * user has viewed a piece of content. - * - * @return the number of times this has been viewed. + * Either the outgoing message has a viewed receipt, or an incoming message has been viewed by the local user. */ - public int getViewedReceiptCount() { - return viewReceiptCount; + public boolean isViewed() { + return viewed; } public boolean isDelivered() { return (deliveryStatus >= Status.STATUS_COMPLETE && - deliveryStatus < Status.STATUS_PENDING) || deliveryReceiptCount > 0; + deliveryStatus < Status.STATUS_PENDING) || hasDeliveryReceipt; } - public boolean isRemoteViewed() { - return viewReceiptCount > 0; - } - - public boolean isRemoteRead() { - return readReceiptCount > 0; + public boolean hasReadReceipt() { + return hasReadReceipt; } public boolean isPendingInsecureSmsFallback() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/InMemoryMessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/InMemoryMessageRecord.java index 5f0978a918..2613298c2c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/InMemoryMessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/InMemoryMessageRecord.java @@ -41,19 +41,19 @@ public class InMemoryMessageRecord extends MessageRecord { System.currentTimeMillis(), threadId, 0, - 0, + false, type, Collections.emptySet(), Collections.emptySet(), -1, 0, System.currentTimeMillis(), - 0, + false, false, Collections.emptyList(), false, 0, - 0, + false, -1, null, 0); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index 9698f3d7e2..ff5fbb97dd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -109,25 +109,25 @@ public abstract class MessageRecord extends DisplayRecord { MessageRecord(long id, String body, Recipient fromRecipient, int fromDeviceId, Recipient toRecipient, long dateSent, long dateReceived, long dateServer, long threadId, - int deliveryStatus, int deliveryReceiptCount, long type, + int deliveryStatus, boolean hasDeliveryReceipt, long type, Set mismatches, Set networkFailures, int subscriptionId, long expiresIn, long expireStarted, - int readReceiptCount, + boolean hasReadReceipt, boolean unidentified, @NonNull List reactions, boolean remoteDelete, long notifiedTimestamp, - int viewedReceiptCount, + boolean viewed, long receiptTimestamp, @Nullable MessageId originalMessageId, int revisionNumber) { super(body, fromRecipient, toRecipient, dateSent, dateReceived, - threadId, deliveryStatus, deliveryReceiptCount, type, - readReceiptCount, viewedReceiptCount); + threadId, deliveryStatus, hasDeliveryReceipt, type, + hasReadReceipt, viewed); this.id = id; this.authorDeviceId = fromDeviceId; this.mismatches = mismatches; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java index c25cc9937c..99266b1880 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java @@ -78,7 +78,7 @@ public class MmsMessageRecord extends MessageRecord { long dateSent, long dateReceived, long dateServer, - int deliveryReceiptCount, + boolean hasDeliveryReceipt, long threadId, String body, @NonNull SlideDeck slideDeck, @@ -89,7 +89,7 @@ public class MmsMessageRecord extends MessageRecord { long expiresIn, long expireStarted, boolean viewOnce, - int readReceiptCount, + boolean hasReadReceipt, @Nullable Quote quote, @NonNull List contacts, @NonNull List linkPreviews, @@ -98,7 +98,7 @@ public class MmsMessageRecord extends MessageRecord { boolean remoteDelete, boolean mentionsSelf, long notifiedTimestamp, - int viewedReceiptCount, + boolean viewed, long receiptTimestamp, @Nullable BodyRangeList messageRanges, @NonNull StoryType storyType, @@ -112,9 +112,9 @@ public class MmsMessageRecord extends MessageRecord { int revisionNumber) { super(id, body, fromRecipient, fromDeviceId, toRecipient, - dateSent, dateReceived, dateServer, threadId, Status.STATUS_NONE, deliveryReceiptCount, - mailbox, mismatches, failures, subscriptionId, expiresIn, expireStarted, readReceiptCount, - unidentified, reactions, remoteDelete, notifiedTimestamp, viewedReceiptCount, receiptTimestamp, originalMessageId, revisionNumber); + dateSent, dateReceived, dateServer, threadId, Status.STATUS_NONE, hasDeliveryReceipt, + mailbox, mismatches, failures, subscriptionId, expiresIn, expireStarted, hasReadReceipt, + unidentified, reactions, remoteDelete, notifiedTimestamp, viewed, receiptTimestamp, originalMessageId, revisionNumber); this.slideDeck = slideDeck; this.quote = quote; @@ -276,18 +276,18 @@ public class MmsMessageRecord extends MessageRecord { } public @NonNull MmsMessageRecord withReactions(@NonNull List reactions) { - return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(), + return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), getSlideDeck(), getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(), - getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), reactions, isRemoteDelete(), mentionsSelf, - getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate(), getLatestRevisionId(), + hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), reactions, isRemoteDelete(), mentionsSelf, + getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate(), getLatestRevisionId(), getOriginalMessageId(), getRevisionNumber()); } public @NonNull MmsMessageRecord withoutQuote() { - return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(), + return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), getSlideDeck(), getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(), - getReadReceiptCount(), null, getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf, - getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate(), getLatestRevisionId(), + hasReadReceipt(), null, getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf, + getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate(), getLatestRevisionId(), getOriginalMessageId(), getRevisionNumber()); } @@ -306,27 +306,27 @@ public class MmsMessageRecord extends MessageRecord { List slideAttachments = attachments.stream().filter(a -> !contactAttachments.contains(a)).filter(a -> !linkPreviewAttachments.contains(a)).collect(Collectors.toList()); SlideDeck slideDeck = MessageTable.MmsReader.buildSlideDeck(slideAttachments); - return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), slideDeck, + return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), slideDeck, getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(), - getReadReceiptCount(), quote, contacts, linkPreviews, isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf, - getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate(), getLatestRevisionId(), + hasReadReceipt(), quote, contacts, linkPreviews, isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf, + getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate(), getLatestRevisionId(), getOriginalMessageId(), getRevisionNumber()); } public @NonNull MmsMessageRecord withPayment(@NonNull Payment payment) { - return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(), + return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), getSlideDeck(), getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(), - getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf, - getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), payment, getCall(), getScheduledDate(), getLatestRevisionId(), + hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf, + getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), payment, getCall(), getScheduledDate(), getLatestRevisionId(), getOriginalMessageId(), getRevisionNumber()); } public @NonNull MmsMessageRecord withCall(@Nullable CallTable.Call call) { - return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(), + return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), getSlideDeck(), getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(), - getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf, - getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), call, getScheduledDate(), getLatestRevisionId(), + hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf, + getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), call, getScheduledDate(), getLatestRevisionId(), getOriginalMessageId(), getRevisionNumber()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/StatusUtil.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/StatusUtil.java index f77d7a93c6..a9230188f2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/StatusUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/StatusUtil.java @@ -6,9 +6,9 @@ import org.thoughtcrime.securesms.database.MessageTypes; final class StatusUtil { private StatusUtil() {} - static boolean isDelivered(long deliveryStatus, int deliveryReceiptCount) { + static boolean isDelivered(long deliveryStatus, boolean hasDeliveryReceipt) { return (deliveryStatus >= MessageTable.Status.STATUS_COMPLETE && - deliveryStatus < MessageTable.Status.STATUS_PENDING) || deliveryReceiptCount > 0; + deliveryStatus < MessageTable.Status.STATUS_PENDING) || hasDeliveryReceipt; } static boolean isPending(long type) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java index c6cc3eef93..abc1d4709d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java @@ -43,8 +43,8 @@ public final class ThreadRecord { private final long type; private final long date; private final long deliveryStatus; - private final int deliveryReceiptCount; - private final int readReceiptCount; + private final boolean hasDeliveryReceipt; + private final boolean hasReadReceipt; private final Uri snippetUri; private final String contentType; private final Extra extra; @@ -65,8 +65,8 @@ public final class ThreadRecord { this.date = builder.date; this.type = builder.type; this.deliveryStatus = builder.deliveryStatus; - this.deliveryReceiptCount = builder.deliveryReceiptCount; - this.readReceiptCount = builder.readReceiptCount; + this.hasDeliveryReceipt = builder.hasDeliveryReceipt; + this.hasReadReceipt = builder.hasReadReceipt; this.snippetUri = builder.snippetUri; this.contentType = builder.contentType; this.extra = builder.extra; @@ -173,8 +173,8 @@ public final class ThreadRecord { return StatusUtil.isFailed(type, deliveryStatus); } - public boolean isRemoteRead() { - return readReceiptCount > 0; + public boolean hasReadReceipt() { + return hasReadReceipt; } public boolean isPendingInsecureSmsFallback() { @@ -182,7 +182,7 @@ public final class ThreadRecord { } public boolean isDelivered() { - return StatusUtil.isDelivered(deliveryStatus, deliveryReceiptCount); + return StatusUtil.isDelivered(deliveryStatus, hasDeliveryReceipt); } public boolean isScheduledMessage() { @@ -244,8 +244,8 @@ public final class ThreadRecord { type == that.type && date == that.date && deliveryStatus == that.deliveryStatus && - deliveryReceiptCount == that.deliveryReceiptCount && - readReceiptCount == that.readReceiptCount && + hasDeliveryReceipt == that.hasDeliveryReceipt && + hasReadReceipt == that.hasReadReceipt && meaningfulMessages == that.meaningfulMessages && unreadCount == that.unreadCount && forcedUnread == that.forcedUnread && @@ -270,8 +270,8 @@ public final class ThreadRecord { type, date, deliveryStatus, - deliveryReceiptCount, - readReceiptCount, + hasDeliveryReceipt, + hasReadReceipt, snippetUri, contentType, extra, @@ -293,8 +293,8 @@ public final class ThreadRecord { private long type; private long date; private long deliveryStatus; - private int deliveryReceiptCount; - private int readReceiptCount; + private boolean hasDeliveryReceipt; + private boolean hasReadReceipt; private Uri snippetUri; private String contentType; private Extra extra; @@ -342,13 +342,13 @@ public final class ThreadRecord { return this; } - public Builder setDeliveryReceiptCount(int deliveryReceiptCount) { - this.deliveryReceiptCount = deliveryReceiptCount; + public Builder setHasDeliveryReceipt(boolean hasDeliveryReceipt) { + this.hasDeliveryReceipt = hasDeliveryReceipt; return this; } - public Builder setReadReceiptCount(int readReceiptCount) { - this.readReceiptCount = readReceiptCount; + public Builder setHasReadReceipt(boolean hasReadReceipt) { + this.hasReadReceipt = hasReadReceipt; return this; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsRepository.java b/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsRepository.java index bcddf58f3d..f66e3a7b9f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsRepository.java @@ -158,8 +158,8 @@ public final class MessageDetailsRepository { } private @NonNull RecipientDeliveryStatus.Status getStatusFor(MessageRecord messageRecord) { - if (messageRecord.isRemoteViewed()) return RecipientDeliveryStatus.Status.VIEWED; - if (messageRecord.isRemoteRead()) return RecipientDeliveryStatus.Status.READ; + if (messageRecord.isViewed()) return RecipientDeliveryStatus.Status.VIEWED; + if (messageRecord.hasReadReceipt()) return RecipientDeliveryStatus.Status.READ; if (messageRecord.isDelivered()) return RecipientDeliveryStatus.Status.DELIVERED; if (messageRecord.isSent()) return RecipientDeliveryStatus.Status.SENT; if (messageRecord.isPending()) return RecipientDeliveryStatus.Status.PENDING; diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/ReceiptMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/ReceiptMessageProcessor.kt index ffcf9e941e..bf4ac20b41 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/ReceiptMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/ReceiptMessageProcessor.kt @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.messages import android.annotation.SuppressLint import android.content.Context +import org.signal.core.util.Stopwatch import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.jobs.PushProcessEarlyMessagesJob @@ -18,6 +19,10 @@ import org.whispersystems.signalservice.internal.push.Envelope import org.whispersystems.signalservice.internal.push.ReceiptMessage object ReceiptMessageProcessor { + private val TAG = MessageContentProcessor.TAG + + private const val VERBOSE = false + fun process(context: Context, senderRecipient: Recipient, envelope: Envelope, content: Content, metadata: EnvelopeMetadata, earlyMessageCacheEntry: EarlyMessageCacheEntry?) { val receiptMessage = content.receiptMessage!! @@ -37,8 +42,9 @@ object ReceiptMessageProcessor { senderRecipientId: RecipientId ) { log(envelope.timestamp!!, "Processing delivery receipts. Sender: $senderRecipientId, Device: ${metadata.sourceDeviceId}, Timestamps: ${deliveryReceipt.timestamp.joinToString(", ")}") + val stopwatch: Stopwatch? = if (VERBOSE) Stopwatch("delivery-receipt", decimalPlaces = 2) else null - val missingTargetTimestamps: Set = SignalDatabase.messages.incrementDeliveryReceiptCounts(deliveryReceipt.timestamp, senderRecipientId, envelope.timestamp!!) + val missingTargetTimestamps: Set = SignalDatabase.messages.incrementDeliveryReceiptCounts(deliveryReceipt.timestamp, senderRecipientId, envelope.timestamp!!, stopwatch) for (targetTimestamp in missingTargetTimestamps) { warn(envelope.timestamp!!, "[handleDeliveryReceipt] Could not find matching message! targetTimestamp: $targetTimestamp, receiptAuthor: $senderRecipientId") @@ -50,7 +56,12 @@ object ReceiptMessageProcessor { } SignalDatabase.pendingPniSignatureMessages.acknowledgeReceipts(senderRecipientId, deliveryReceipt.timestamp, metadata.sourceDeviceId) + stopwatch?.split("pni-signatures") + SignalDatabase.messageLog.deleteEntriesForRecipient(deliveryReceipt.timestamp, senderRecipientId, metadata.sourceDeviceId) + stopwatch?.split("msl") + + stopwatch?.stop(TAG) } @SuppressLint("DefaultLocale") diff --git a/app/src/main/java/org/thoughtcrime/securesms/revealable/ViewOnceMessageView.java b/app/src/main/java/org/thoughtcrime/securesms/revealable/ViewOnceMessageView.java index 387bcf9c27..6b46bdc9af 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/revealable/ViewOnceMessageView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/revealable/ViewOnceMessageView.java @@ -119,7 +119,7 @@ public class ViewOnceMessageView extends LinearLayout { icon.setImageResource(0); showProgress = true; } else if (messageRecord.isOutgoing()) { - if (messageRecord.isRemoteViewed()) { + if (messageRecord.isViewed()) { iconColor = openedIconColor; text.setText(R.string.RevealableMessageView_viewed); icon.setImageResource(R.drawable.ic_viewed_once_24); diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingRepository.kt index 9a467e8ad4..9f77606679 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingRepository.kt @@ -105,7 +105,7 @@ class StoriesLandingRepository(context: Context) { private fun createStoriesLandingItemData(sender: Recipient, messageRecords: List, sendingCount: Long, failureCount: Long): Observable { val itemDataObservable = Observable.create { emitter -> fun refresh(sender: Recipient) { - val primaryIndex = messageRecords.indexOfFirst { !it.isOutgoing && it.viewedReceiptCount == 0 }.takeIf { it > -1 } ?: 0 + val primaryIndex = messageRecords.indexOfFirst { !it.isOutgoing && !it.isViewed }.takeIf { it > -1 } ?: 0 val itemData = StoriesLandingItemData( storyRecipient = sender, storyViewState = StoryViewState.NONE, diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/my/MyStoriesItem.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/my/MyStoriesItem.kt index ffa3533ba8..193599409f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/my/MyStoriesItem.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/my/MyStoriesItem.kt @@ -51,7 +51,7 @@ object MyStoriesItem { override fun areContentsTheSame(newItem: Model): Boolean { return distributionStory == newItem.distributionStory && !hasStatusChange(newItem) && - distributionStory.messageRecord.viewedReceiptCount == newItem.distributionStory.messageRecord.viewedReceiptCount && + distributionStory.messageRecord.isViewed == newItem.distributionStory.messageRecord.isViewed && super.areContentsTheSame(newItem) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageRepository.kt index f81170bc0b..8544bcf6c6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageRepository.kt @@ -90,7 +90,7 @@ open class StoryViewerPageRepository(context: Context, private val storyViewStat content = getContent(record as MmsMessageRecord), conversationMessage = ConversationMessage.ConversationMessageFactory.createWithUnresolvedData(context, record, recipient), allowsReplies = record.storyType.isStoryWithReplies, - hasSelfViewed = storyViewStateCache.getOrPut(record.id, if (record.isOutgoing) true else record.viewedReceiptCount > 0) + hasSelfViewed = storyViewStateCache.getOrPut(record.id, if (record.isOutgoing) true else record.isViewed()) ) emitter.onNext(story) diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/TestMms.kt b/app/src/test/java/org/thoughtcrime/securesms/database/TestMms.kt index 3d5e138987..30a9aaf3a4 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/TestMms.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/database/TestMms.kt @@ -86,9 +86,9 @@ object TestMms { put(MessageTable.VIEW_ONCE, message.isViewOnce) put(MessageTable.FROM_RECIPIENT_ID, recipientId.serialize()) put(MessageTable.TO_RECIPIENT_ID, recipientId.serialize()) - put(MessageTable.DELIVERY_RECEIPT_COUNT, 0) + put(MessageTable.HAS_DELIVERY_RECEIPT, 0) put(MessageTable.RECEIPT_TIMESTAMP, 0) - put(MessageTable.VIEWED_RECEIPT_COUNT, if (viewed) 1 else 0) + put(MessageTable.VIEWED_COLUMN, if (viewed) 1 else 0) put(MessageTable.STORY_TYPE, message.storyType.code) put(MessageTable.BODY, body) diff --git a/app/src/testShared/org/thoughtcrime/securesms/database/FakeMessageRecords.kt b/app/src/testShared/org/thoughtcrime/securesms/database/FakeMessageRecords.kt index 12d8fb1103..177c78be13 100644 --- a/app/src/testShared/org/thoughtcrime/securesms/database/FakeMessageRecords.kt +++ b/app/src/testShared/org/thoughtcrime/securesms/database/FakeMessageRecords.kt @@ -114,7 +114,7 @@ object FakeMessageRecords { dateSent: Long = 200, dateReceived: Long = 400, dateServer: Long = 300, - deliveryReceiptCount: Int = 0, + hasDeliveryReceipt: Boolean = false, threadId: Long = 1, body: String = "body", slideDeck: SlideDeck = SlideDeck(), @@ -126,7 +126,7 @@ object FakeMessageRecords { expiresIn: Long = -1, expireStarted: Long = -1, viewOnce: Boolean = false, - readReceiptCount: Int = 0, + hasReadReceipt: Boolean = false, quote: Quote? = null, contacts: List = emptyList(), linkPreviews: List = emptyList(), @@ -135,7 +135,7 @@ object FakeMessageRecords { remoteDelete: Boolean = false, mentionsSelf: Boolean = false, notifiedTimestamp: Long = 350, - viewedReceiptCount: Int = 0, + viewed: Boolean = false, receiptTimestamp: Long = 0, messageRanges: BodyRangeList? = null, storyType: StoryType = StoryType.NONE, @@ -152,7 +152,7 @@ object FakeMessageRecords { dateSent, dateReceived, dateServer, - deliveryReceiptCount, + hasDeliveryReceipt, threadId, body, slideDeck, @@ -163,7 +163,7 @@ object FakeMessageRecords { expiresIn, expireStarted, viewOnce, - readReceiptCount, + hasReadReceipt, quote, contacts, linkPreviews, @@ -172,7 +172,7 @@ object FakeMessageRecords { remoteDelete, mentionsSelf, notifiedTimestamp, - viewedReceiptCount, + viewed, receiptTimestamp, messageRanges, storyType,