diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MessageDatabase.java index 14daaf2b4..91b88946e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageDatabase.java @@ -122,6 +122,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns public abstract void markIncomingNotificationReceived(long threadId); public abstract Set incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType); + public abstract Set incrementStoryReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType); abstract @NonNull MmsSmsDatabase.TimestampReadResult setTimestampRead(SyncMessageId messageId, long proposedExpireStarted, @NonNull Map threadToLatestRead); public abstract List setEntireThreadRead(long threadId); public abstract List setMessagesReadSince(long threadId, long timestamp); 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 d6a0d74f9..9e67ce209 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -932,7 +932,17 @@ public class MmsDatabase extends MessageDatabase { } } - String columnName = receiptType.getColumnName(); + messageUpdates.addAll(incrementStoryReceiptCount(messageId, timestamp, receiptType)); + + return messageUpdates; + } + + @Override + public Set incrementStoryReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType) { + SQLiteDatabase database = databaseHelper.getSignalWritableDatabase(); + Set messageUpdates = new HashSet<>(); + String columnName = receiptType.getColumnName(); + for (MessageId storyMessageId : SignalDatabase.storySends().getStoryMessagesFor(messageId)) { database.execSQL("UPDATE " + TABLE_NAME + " SET " + columnName + " = " + columnName + " + 1, " + @@ -2461,7 +2471,7 @@ public class MmsDatabase extends MessageDatabase { if (!TextSecurePreferences.isReadReceiptsEnabled(context)) { readReceiptCount = 0; - if (MmsSmsColumns.Types.isOutgoingMessageType(box)) { + if (MmsSmsColumns.Types.isOutgoingMessageType(box) && !storyType.isStory()) { viewedReceiptCount = 0; } } 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 d89ed604e..9b87b5b87 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java @@ -401,6 +401,40 @@ public class MmsSmsDatabase extends Database { return incrementReceiptCount(syncMessageId, timestamp, MessageDatabase.ReceiptType.VIEWED); } + public @NonNull Collection incrementViewedStoryReceiptCounts(@NonNull List syncMessageIds, long timestamp) { + SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); + Set messageUpdates = new HashSet<>(); + Collection unhandled = new HashSet<>(); + + db.beginTransaction(); + try { + for (SyncMessageId id : syncMessageIds) { + Set updates = incrementStoryReceiptCountInternal(id, timestamp, MessageDatabase.ReceiptType.VIEWED); + + if (updates.size() > 0) { + messageUpdates.addAll(updates); + } else { + unhandled.add(id); + } + } + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + + for (MessageUpdate update : messageUpdates) { + ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(update.getMessageId()); + ApplicationDependencies.getDatabaseObserver().notifyVerboseConversationListeners(Collections.singleton(update.getThreadId())); + } + + if (messageUpdates.size() > 0) { + notifyConversationListListeners(); + } + } + + return unhandled; + } + /** * Wraps a single receipt update in a transaction and triggers the proper updates. * @@ -488,6 +522,13 @@ public class MmsSmsDatabase extends Database { return messageUpdates; } + /** + * Doesn't do any transactions or updates, so we can re-use the method safely. + */ + private @NonNull Set incrementStoryReceiptCountInternal(@NonNull SyncMessageId syncMessageId, long timestamp, @NonNull MessageDatabase.ReceiptType receiptType) { + return SignalDatabase.mms().incrementStoryReceiptCount(syncMessageId, timestamp, receiptType); + } + public void setTimestampRead(@NonNull Recipient senderRecipient, @NonNull List readMessages, long proposedExpireStarted, @NonNull Map threadToLatestRead) { SQLiteDatabase db = getWritableDatabase(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 7478f4e23..f5062fcf0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -529,6 +529,11 @@ public class SmsDatabase extends MessageDatabase { } } + @Override + public Set incrementStoryReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType) { + throw new UnsupportedOperationException(); + } + @Override @NonNull MmsSmsDatabase.TimestampReadResult setTimestampRead(SyncMessageId messageId, long proposedExpireStarted, @NonNull Map threadToLatestRead) { SQLiteDatabase database = databaseHelper.getSignalWritableDatabase(); 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 4277df9a8..937aea115 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java @@ -2129,19 +2129,21 @@ public final class MessageContentProcessor { @NonNull SignalServiceReceiptMessage message, @NonNull Recipient senderRecipient) { - if (!TextSecurePreferences.isReadReceiptsEnabled(context)) { + boolean shouldOnlyProcessStories = FeatureFlags.stories() && !SignalStore.storyValues().isFeatureDisabled() && !TextSecurePreferences.isReadReceiptsEnabled(context); + + if (!TextSecurePreferences.isReadReceiptsEnabled(context) && !shouldOnlyProcessStories) { log("Ignoring viewed receipts for IDs: " + Util.join(message.getTimestamps(), ", ")); return; } - log(TAG, "Processing viewed receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", ")); + log(TAG, "Processing viewed receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Only Stories: " + shouldOnlyProcessStories + ", Timestamps: " + Util.join(message.getTimestamps(), ", ")); List ids = Stream.of(message.getTimestamps()) .map(t -> new SyncMessageId(senderRecipient.getId(), t)) .toList(); - Collection unhandled = SignalDatabase.mmsSms() - .incrementViewedReceiptCounts(ids, content.getTimestamp()); + Collection unhandled = shouldOnlyProcessStories ? SignalDatabase.mmsSms().incrementViewedStoryReceiptCounts(ids, content.getTimestamp()) + : SignalDatabase.mmsSms().incrementViewedReceiptCounts(ids, content.getTimestamp()); for (SyncMessageId id : unhandled) { warn(String.valueOf(content.getTimestamp()), "[handleViewedReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + senderRecipient.getId());