diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseObserver.java b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseObserver.java index 3ccf809ef4..eddf93e30f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseObserver.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseObserver.java @@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.util.concurrent.SerialExecutor; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -281,6 +282,14 @@ public class DatabaseObserver { }); } + public void notifyStoryObservers(@NonNull Collection recipientIds) { + for (RecipientId recipientId : recipientIds) { + runPostSuccessfulTransaction(KEY_STORY_OBSERVER, () -> { + notifyMapped(storyObservers, recipientId); + }); + } + } + private void runPostSuccessfulTransaction(@NonNull String dedupeKey, @NonNull Runnable runnable) { SignalDatabase.runPostSuccessfulTransaction(dedupeKey, () -> { executor.execute(runnable); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.java b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.java index fdcd9b9504..cc0ee04970 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.java @@ -497,8 +497,9 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie RecipientId recipientId = RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID)); long dateSent = CursorUtil.requireLong(cursor, DATE_SENT); SyncMessageId syncMessageId = new SyncMessageId(recipientId, dateSent); + StoryType storyType = StoryType.fromCode(CursorUtil.requireInt(cursor, STORY_TYPE)); - results.add(new MarkedMessageInfo(threadId, syncMessageId, new MessageId(messageId), null)); + results.add(new MarkedMessageInfo(threadId, syncMessageId, new MessageId(messageId), null, storyType)); } return results; @@ -535,8 +536,9 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie RecipientId recipientId = RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID)); long dateSent = CursorUtil.requireLong(cursor, DATE_SENT); SyncMessageId syncMessageId = new SyncMessageId(recipientId, dateSent); + StoryType storyType = StoryType.fromCode(CursorUtil.requireInt(cursor, STORY_TYPE)); - results.add(new MarkedMessageInfo(threadId, syncMessageId, new MessageId(messageId), null)); + results.add(new MarkedMessageInfo(threadId, syncMessageId, new MessageId(messageId), null, storyType)); ContentValues contentValues = new ContentValues(); contentValues.put(VIEWED_RECEIPT_COUNT, 1); @@ -554,9 +556,17 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie .map(MarkedMessageInfo::getThreadId) .collect(Collectors.toSet()); + Set storyRecipientsUpdated = results.stream() + .filter(it -> it.storyType.isStory()) + .map(it -> SignalDatabase.threads().getRecipientIdForThreadId(it.getThreadId())) + .filter(it -> it != null) + .collect(java.util.stream.Collectors.toSet()); + notifyConversationListeners(threadsUpdated); notifyConversationListListeners(); + ApplicationDependencies.getDatabaseObserver().notifyStoryObservers(storyRecipientsUpdated); + return results; } @@ -573,8 +583,9 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie RecipientId recipientId = RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID)); long dateSent = CursorUtil.requireLong(cursor, DATE_SENT); SyncMessageId syncMessageId = new SyncMessageId(recipientId, dateSent); + StoryType storyType = StoryType.fromCode(CursorUtil.requireInt(cursor, STORY_TYPE)); - results.add(new MarkedMessageInfo(threadId, syncMessageId, new MessageId(messageId), null)); + results.add(new MarkedMessageInfo(threadId, syncMessageId, new MessageId(messageId), null, storyType)); ContentValues contentValues = new ContentValues(); contentValues.put(VIEWED_RECEIPT_COUNT, 1); @@ -2021,9 +2032,10 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie long expireStarted = CursorUtil.requireLong(cursor, EXPIRE_STARTED); SyncMessageId syncMessageId = new SyncMessageId(recipientId, dateSent); ExpirationInfo expirationInfo = new ExpirationInfo(messageId, expiresIn, expireStarted, true); + StoryType storyType = StoryType.fromCode(CursorUtil.requireInt(cursor, STORY_TYPE)); if (!recipientId.equals(releaseChannelId)) { - result.add(new MarkedMessageInfo(threadId, syncMessageId, new MessageId(messageId), expirationInfo)); + result.add(new MarkedMessageInfo(threadId, syncMessageId, new MessageId(messageId), expirationInfo, storyType)); } } } @@ -2400,6 +2412,10 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie notifyConversationListeners(threadId); + if (retrieved.getStoryType().isStory()) { + ApplicationDependencies.getDatabaseObserver().notifyStoryObservers(Objects.requireNonNull(SignalDatabase.threads().getRecipientIdForThreadId(threadId))); + } + return Optional.of(new InsertResult(messageId, threadId)); } @@ -4126,6 +4142,10 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie for (MessageUpdate update : messageUpdates) { ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(update.getMessageId()); ApplicationDependencies.getDatabaseObserver().notifyVerboseConversationListeners(Collections.singleton(update.getThreadId())); + + if (messageQualifier == MessageQualifier.STORY) { + ApplicationDependencies.getDatabaseObserver().notifyStoryObservers(Objects.requireNonNull(threadTable.getRecipientIdForThreadId(update.getThreadId()))); + } } if (messageUpdates.size() > 0) { @@ -4613,12 +4633,14 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie private final SyncMessageId syncMessageId; private final MessageId messageId; private final ExpirationInfo expirationInfo; + private final StoryType storyType; - public MarkedMessageInfo(long threadId, @NonNull SyncMessageId syncMessageId, @NonNull MessageId messageId, @Nullable ExpirationInfo expirationInfo) { + public MarkedMessageInfo(long threadId, @NonNull SyncMessageId syncMessageId, @NonNull MessageId messageId, @Nullable ExpirationInfo expirationInfo, @NonNull StoryType storyType) { this.threadId = threadId; this.syncMessageId = syncMessageId; this.messageId = messageId; this.expirationInfo = expirationInfo; + this.storyType = storyType; } public long getThreadId() { @@ -4636,6 +4658,10 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie public @Nullable ExpirationInfo getExpirationInfo() { return expirationInfo; } + + public @NonNull StoryType getStoryType() { + return storyType; + } } public static class InsertResult { 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 df1f90d34a..bcd215b00e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt @@ -1126,7 +1126,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa } } - private fun getRecipientIdForThreadId(threadId: Long): RecipientId? { + fun getRecipientIdForThreadId(threadId: Long): RecipientId? { return readableDatabase .select(RECIPIENT_ID) .from(TABLE_NAME) diff --git a/app/src/test/java/org/thoughtcrime/securesms/notifications/MarkReadReceiverTest.java b/app/src/test/java/org/thoughtcrime/securesms/notifications/MarkReadReceiverTest.java index 9f0966f2b7..0f0f355271 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/notifications/MarkReadReceiverTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/notifications/MarkReadReceiverTest.java @@ -17,6 +17,7 @@ import org.mockito.stubbing.Answer; import org.signal.libsignal.protocol.util.Pair; import org.thoughtcrime.securesms.database.MessageTable; import org.thoughtcrime.securesms.database.model.MessageId; +import org.thoughtcrime.securesms.database.model.StoryType; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; @@ -108,6 +109,7 @@ public class MarkReadReceiverTest { return new MessageTable.MarkedMessageInfo(threadId, new MessageTable.SyncMessageId(recipientId, 0), new MessageId(1), - new MessageTable.ExpirationInfo(0, 0, 0, false)); + new MessageTable.ExpirationInfo(0, 0, 0, false), + StoryType.NONE); } } \ No newline at end of file