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 a596705b7..c633f3a14 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -81,7 +81,6 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.util.Pair; import org.whispersystems.libsignal.util.guava.Optional; -import org.whispersystems.signalservice.api.push.ACI; import org.whispersystems.signalservice.api.push.ServiceId; import java.io.IOException; @@ -650,8 +649,8 @@ public class MmsDatabase extends MessageDatabase { @Override public long getUnreadStoryCount() { String[] columns = new String[]{"COUNT(*)"}; - String where = IS_STORY_CLAUSE + " AND NOT (" + getOutgoingTypeClause() + ") AND " + READ_RECEIPT_COUNT + " = ?"; - String[] whereArgs = SqlUtil.buildArgs(1, 0, 0); + String where = IS_STORY_CLAUSE + " AND NOT (" + getOutgoingTypeClause() + ") AND " + VIEWED_RECEIPT_COUNT + " = 0"; + String[] whereArgs = SqlUtil.buildArgs(1, 0); try (Cursor cursor = getReadableDatabase().query(TABLE_NAME, columns, where, whereArgs, null, null, null, null)) { return cursor != null && cursor.moveToFirst() ? cursor.getInt(0) : 0; @@ -1165,20 +1164,20 @@ public class MmsDatabase extends MessageDatabase { @Override public List setMessagesReadSince(long threadId, long sinceTimestamp) { if (sinceTimestamp == -1) { - return setMessagesRead(THREAD_ID + " = ? 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 (" + 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 + " = ?", 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(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) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java index 5015377a0..68310c095 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java @@ -114,7 +114,7 @@ public class MultiDeviceReadUpdateJob extends BaseJob { for (SerializableSyncMessageId messageId : messageIds) { Recipient recipient = Recipient.resolved(RecipientId.from(messageId.recipientId)); - if (!recipient.isGroup() && recipient.isMaybeRegistered()) { + if (!recipient.isGroup() && !recipient.isDistributionList() && recipient.isMaybeRegistered()) { readMessages.add(new ReadMessage(RecipientUtil.toSignalServiceAddress(context, recipient), messageId.timestamp)); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java index 9e1ed3fae..a2aaf1fed 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java @@ -166,6 +166,11 @@ public class SendReadReceiptJob extends BaseJob { return; } + if (recipient.isDistributionList()) { + Log.w(TAG, "Refusing to send receipts to distribution list"); + return; + } + if (recipient.isUnregistered()) { Log.w(TAG, recipient.getId() + " not registered!"); return; 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 ca429c1dd..0ea7c099c 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 @@ -66,7 +66,7 @@ class StoriesLandingRepository(context: Context) { fun refresh() { val itemData = StoriesLandingItemData( storyRecipient = sender, - hasUnreadStory = messageRecords.any { it.readReceiptCount == 0 && !it.isOutgoing }, + hasUnreadStory = messageRecords.any { it.viewedReceiptCount == 0 && !it.isOutgoing }, hasReplies = messageRecords.any { SignalDatabase.mms.getNumberOfStoryReplies(it.id) > 0 }, hasRepliesFromSelf = messageRecords.any { SignalDatabase.mms.hasSelfReplyInStory(it.id) }, isHidden = Recipient.resolved(messageRecords.first().recipient.id).shouldHideStory(), 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 574dd5601..47a552f72 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 @@ -9,9 +9,12 @@ import org.thoughtcrime.securesms.conversation.ConversationMessage import org.thoughtcrime.securesms.database.DatabaseObserver import org.thoughtcrime.securesms.database.NoSuchMessageException import org.thoughtcrime.securesms.database.SignalDatabase +import org.thoughtcrime.securesms.database.model.MessageId import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.database.model.MmsMessageRecord import org.thoughtcrime.securesms.dependencies.ApplicationDependencies +import org.thoughtcrime.securesms.jobs.MultiDeviceViewedUpdateJob +import org.thoughtcrime.securesms.jobs.SendViewedReceiptJob import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId @@ -130,9 +133,23 @@ class StoryViewerPageRepository(context: Context) { }.subscribeOn(Schedulers.io()) } - fun markRead(storyPost: StoryPost) { - // TODO [stories] -- Implementation - SignalExecutors.BOUNDED.execute { + fun markViewed(storyPost: StoryPost) { + if (!storyPost.conversationMessage.messageRecord.isOutgoing) { + SignalExecutors.BOUNDED.execute { + val markedMessageInfo = SignalDatabase.mms.setIncomingMessageViewed(storyPost.id) + if (markedMessageInfo != null) { + ApplicationDependencies.getDatabaseObserver().notifyConversationListListeners() + ApplicationDependencies.getJobManager().add( + SendViewedReceiptJob( + markedMessageInfo.threadId, + storyPost.sender.id, + markedMessageInfo.syncMessageId.timetamp, + MessageId(storyPost.id, true) + ) + ) + MultiDeviceViewedUpdateJob.enqueue(listOf(markedMessageInfo.syncMessageId)) + } + } } } } 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 3417fc221..2ce46f6e9 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 @@ -82,6 +82,7 @@ class StoryViewerPageViewModel( } fun setSelectedPostIndex(index: Int) { + repository.markViewed(getPostAt(index)) store.update { it.copy( selectedPostIndex = index,