Mark previous messages in thread as read when receiving a read sync message.
This commit is contained in:
parent
d46a9f6d1d
commit
ec63dd704a
5 changed files with 40 additions and 16 deletions
|
@ -49,6 +49,7 @@ import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -120,7 +121,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
|
||||||
public abstract void markIncomingNotificationReceived(long threadId);
|
public abstract void markIncomingNotificationReceived(long threadId);
|
||||||
|
|
||||||
public abstract Set<ThreadUpdate> incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType);
|
public abstract Set<ThreadUpdate> incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType);
|
||||||
public abstract List<Pair<Long, Long>> setTimestampRead(SyncMessageId messageId, long proposedExpireStarted);
|
public abstract List<Pair<Long, Long>> setTimestampRead(SyncMessageId messageId, long proposedExpireStarted, @NonNull Map<Long, Long> threadToLatestRead);
|
||||||
public abstract List<MarkedMessageInfo> setEntireThreadRead(long threadId);
|
public abstract List<MarkedMessageInfo> setEntireThreadRead(long threadId);
|
||||||
public abstract List<MarkedMessageInfo> setMessagesReadSince(long threadId, long timestamp);
|
public abstract List<MarkedMessageInfo> setMessagesReadSince(long threadId, long timestamp);
|
||||||
public abstract List<MarkedMessageInfo> setAllMessagesRead();
|
public abstract List<MarkedMessageInfo> setAllMessagesRead();
|
||||||
|
|
|
@ -66,6 +66,7 @@ import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.QuoteModel;
|
import org.thoughtcrime.securesms.mms.QuoteModel;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
|
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo;
|
import org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo;
|
||||||
|
@ -951,7 +952,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Pair<Long, Long>> setTimestampRead(SyncMessageId messageId, long proposedExpireStarted) {
|
public List<Pair<Long, Long>> setTimestampRead(SyncMessageId messageId, long proposedExpireStarted, @NonNull Map<Long, Long> threadToLatestRead) {
|
||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
List<Pair<Long, Long>> expiring = new LinkedList<>();
|
List<Pair<Long, Long>> expiring = new LinkedList<>();
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
@ -986,6 +987,9 @@ public class MmsDatabase extends MessageDatabase {
|
||||||
DatabaseFactory.getThreadDatabase(context).updateReadState(threadId);
|
DatabaseFactory.getThreadDatabase(context).updateReadState(threadId);
|
||||||
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
||||||
notifyConversationListeners(threadId);
|
notifyConversationListeners(threadId);
|
||||||
|
|
||||||
|
Long latest = threadToLatestRead.get(threadId);
|
||||||
|
threadToLatestRead.put(threadId, (latest != null) ? Math.max(latest, messageId.getTimetamp()) : messageId.getTimetamp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -47,6 +47,7 @@ import org.thoughtcrime.securesms.jobs.TrimThreadJob;
|
||||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
|
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo;
|
import org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo;
|
||||||
|
@ -510,7 +511,7 @@ public class SmsDatabase extends MessageDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Pair<Long, Long>> setTimestampRead(SyncMessageId messageId, long proposedExpireStarted) {
|
public List<Pair<Long, Long>> setTimestampRead(SyncMessageId messageId, long proposedExpireStarted, @NonNull Map<Long, Long> threadToLatestRead) {
|
||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
List<Pair<Long, Long>> expiring = new LinkedList<>();
|
List<Pair<Long, Long>> expiring = new LinkedList<>();
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
@ -547,6 +548,9 @@ public class SmsDatabase extends MessageDatabase {
|
||||||
DatabaseFactory.getThreadDatabase(context).updateReadState(threadId);
|
DatabaseFactory.getThreadDatabase(context).updateReadState(threadId);
|
||||||
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
||||||
notifyConversationListeners(threadId);
|
notifyConversationListeners(threadId);
|
||||||
|
|
||||||
|
Long latest = threadToLatestRead.get(threadId);
|
||||||
|
threadToLatestRead.put(threadId, (latest != null) ? Math.max(latest, messageId.getTimetamp()) : messageId.getTimetamp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import android.net.Uri;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.annimon.stream.Collectors;
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
@ -368,18 +369,18 @@ public class ThreadDatabase extends Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MarkedMessageInfo> setRead(long threadId, boolean lastSeen) {
|
public List<MarkedMessageInfo> setRead(long threadId, boolean lastSeen) {
|
||||||
return setReadInternal(Collections.singletonList(threadId), lastSeen, -1);
|
return setReadSince(Collections.singletonMap(threadId, -1L), lastSeen);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MarkedMessageInfo> setReadSince(long threadId, boolean lastSeen, long sinceTimestamp) {
|
public List<MarkedMessageInfo> setReadSince(long threadId, boolean lastSeen, long sinceTimestamp) {
|
||||||
return setReadInternal(Collections.singletonList(threadId), lastSeen, sinceTimestamp);
|
return setReadSince(Collections.singletonMap(threadId, sinceTimestamp), lastSeen);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MarkedMessageInfo> setRead(Collection<Long> threadIds, boolean lastSeen) {
|
public List<MarkedMessageInfo> setRead(Collection<Long> threadIds, boolean lastSeen) {
|
||||||
return setReadInternal(threadIds, lastSeen, -1);
|
return setReadSince(Stream.of(threadIds).collect(Collectors.toMap(t -> t, t -> -1L)), lastSeen);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MarkedMessageInfo> setReadInternal(Collection<Long> threadIds, boolean lastSeen, long sinceTimestamp) {
|
public List<MarkedMessageInfo> setReadSince(Map<Long, Long> threadIdToSinceTimestamp, boolean lastSeen) {
|
||||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
|
|
||||||
List<MarkedMessageInfo> smsRecords = new LinkedList<>();
|
List<MarkedMessageInfo> smsRecords = new LinkedList<>();
|
||||||
|
@ -392,11 +393,14 @@ public class ThreadDatabase extends Database {
|
||||||
ContentValues contentValues = new ContentValues(2);
|
ContentValues contentValues = new ContentValues(2);
|
||||||
contentValues.put(READ, ReadStatus.READ.serialize());
|
contentValues.put(READ, ReadStatus.READ.serialize());
|
||||||
|
|
||||||
|
for (Map.Entry<Long, Long> entry : threadIdToSinceTimestamp.entrySet()) {
|
||||||
|
long threadId = entry.getKey();
|
||||||
|
long sinceTimestamp = entry.getValue();
|
||||||
|
|
||||||
if (lastSeen) {
|
if (lastSeen) {
|
||||||
contentValues.put(LAST_SEEN, sinceTimestamp == -1 ? System.currentTimeMillis() : sinceTimestamp);
|
contentValues.put(LAST_SEEN, sinceTimestamp == -1 ? System.currentTimeMillis() : sinceTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (long threadId : threadIds) {
|
|
||||||
ThreadRecord previous = getThreadRecord(threadId);
|
ThreadRecord previous = getThreadRecord(threadId);
|
||||||
|
|
||||||
smsRecords.addAll(DatabaseFactory.getSmsDatabase(context).setMessagesReadSince(threadId, sinceTimestamp));
|
smsRecords.addAll(DatabaseFactory.getSmsDatabase(context).setMessagesReadSince(threadId, sinceTimestamp));
|
||||||
|
@ -422,7 +426,7 @@ public class ThreadDatabase extends Database {
|
||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyConversationListeners(new HashSet<>(threadIds));
|
notifyConversationListeners(threadIdToSinceTimestamp.keySet());
|
||||||
notifyConversationListListeners();
|
notifyConversationListListeners();
|
||||||
|
|
||||||
if (needsSync) {
|
if (needsSync) {
|
||||||
|
|
|
@ -14,13 +14,11 @@ import com.annimon.stream.Stream;
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.signal.ringrtc.CallId;
|
import org.signal.ringrtc.CallId;
|
||||||
import org.signal.zkgroup.profiles.ProfileKey;
|
import org.signal.zkgroup.profiles.ProfileKey;
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
|
||||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
||||||
import org.thoughtcrime.securesms.attachments.PointerAttachment;
|
import org.thoughtcrime.securesms.attachments.PointerAttachment;
|
||||||
import org.thoughtcrime.securesms.attachments.TombstoneAttachment;
|
import org.thoughtcrime.securesms.attachments.TombstoneAttachment;
|
||||||
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
||||||
import org.thoughtcrime.securesms.components.emoji.Emoji;
|
|
||||||
import org.thoughtcrime.securesms.components.emoji.EmojiUtil;
|
import org.thoughtcrime.securesms.components.emoji.EmojiUtil;
|
||||||
import org.thoughtcrime.securesms.contactshare.Contact;
|
import org.thoughtcrime.securesms.contactshare.Contact;
|
||||||
import org.thoughtcrime.securesms.contactshare.ContactModelMapper;
|
import org.thoughtcrime.securesms.contactshare.ContactModelMapper;
|
||||||
|
@ -84,6 +82,7 @@ import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.QuoteModel;
|
import org.thoughtcrime.securesms.mms.QuoteModel;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
import org.thoughtcrime.securesms.mms.StickerSlide;
|
import org.thoughtcrime.securesms.mms.StickerSlide;
|
||||||
|
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||||
import org.thoughtcrime.securesms.payments.MobileCoinPublicAddress;
|
import org.thoughtcrime.securesms.payments.MobileCoinPublicAddress;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
@ -143,6 +142,7 @@ import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -987,9 +987,14 @@ public final class MessageContentProcessor {
|
||||||
|
|
||||||
private void handleSynchronizeReadMessage(@NonNull List<ReadMessage> readMessages, long envelopeTimestamp)
|
private void handleSynchronizeReadMessage(@NonNull List<ReadMessage> readMessages, long envelopeTimestamp)
|
||||||
{
|
{
|
||||||
|
Map<Long, Long> threadToLatestRead = new HashMap<>();
|
||||||
for (ReadMessage readMessage : readMessages) {
|
for (ReadMessage readMessage : readMessages) {
|
||||||
List<Pair<Long, Long>> expiringText = DatabaseFactory.getSmsDatabase(context).setTimestampRead(new SyncMessageId(Recipient.externalPush(context, readMessage.getSender()).getId(), readMessage.getTimestamp()), envelopeTimestamp);
|
List<Pair<Long, Long>> expiringText = DatabaseFactory.getSmsDatabase(context).setTimestampRead(new SyncMessageId(Recipient.externalPush(context, readMessage.getSender()).getId(), readMessage.getTimestamp()),
|
||||||
List<Pair<Long, Long>> expiringMedia = DatabaseFactory.getMmsDatabase(context).setTimestampRead(new SyncMessageId(Recipient.externalPush(context, readMessage.getSender()).getId(), readMessage.getTimestamp()), envelopeTimestamp);
|
envelopeTimestamp,
|
||||||
|
threadToLatestRead);
|
||||||
|
List<Pair<Long, Long>> expiringMedia = DatabaseFactory.getMmsDatabase(context).setTimestampRead(new SyncMessageId(Recipient.externalPush(context, readMessage.getSender()).getId(), readMessage.getTimestamp()),
|
||||||
|
envelopeTimestamp,
|
||||||
|
threadToLatestRead);
|
||||||
|
|
||||||
for (Pair<Long, Long> expiringMessage : expiringText) {
|
for (Pair<Long, Long> expiringMessage : expiringText) {
|
||||||
ApplicationDependencies.getExpiringMessageManager()
|
ApplicationDependencies.getExpiringMessageManager()
|
||||||
|
@ -1002,6 +1007,12 @@ public final class MessageContentProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<MessageDatabase.MarkedMessageInfo> markedMessages = DatabaseFactory.getThreadDatabase(context).setReadSince(threadToLatestRead, false);
|
||||||
|
if (Util.hasItems(markedMessages)) {
|
||||||
|
Log.i(TAG, "Updating past messages: " + markedMessages.size());
|
||||||
|
MarkReadReceiver.process(context, markedMessages);
|
||||||
|
}
|
||||||
|
|
||||||
MessageNotifier messageNotifier = ApplicationDependencies.getMessageNotifier();
|
MessageNotifier messageNotifier = ApplicationDependencies.getMessageNotifier();
|
||||||
messageNotifier.setLastDesktopActivityTimestamp(envelopeTimestamp);
|
messageNotifier.setLastDesktopActivityTimestamp(envelopeTimestamp);
|
||||||
messageNotifier.cancelDelayedNotifications();
|
messageNotifier.cancelDelayedNotifications();
|
||||||
|
|
Loading…
Add table
Reference in a new issue