Fix in-memory message updates.

We can also switch to using the message-specific update route for
receipts too.
fork-5.53.8
Greyson Parrelli 2022-01-03 18:46:10 -05:00
rodzic 0dd2397fb4
commit 0d0c74f358
6 zmienionych plików z 61 dodań i 63 usunięć

Wyświetl plik

@ -51,10 +51,6 @@ public abstract class Database {
ApplicationDependencies.getDatabaseObserver().notifyVerboseConversationListeners(threadIds); ApplicationDependencies.getDatabaseObserver().notifyVerboseConversationListeners(threadIds);
} }
protected void notifyVerboseConversationListeners(long threadId) {
ApplicationDependencies.getDatabaseObserver().notifyVerboseConversationListeners(threadId);
}
protected void notifyConversationListListeners() { protected void notifyConversationListListeners() {
ApplicationDependencies.getDatabaseObserver().notifyConversationListListeners(); ApplicationDependencies.getDatabaseObserver().notifyConversationListListeners();
} }

Wyświetl plik

@ -120,7 +120,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
public abstract void markDownloadState(long messageId, long state); public abstract void markDownloadState(long messageId, long state);
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<MessageUpdate> incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType);
abstract @NonNull MmsSmsDatabase.TimestampReadResult setTimestampRead(SyncMessageId messageId, long proposedExpireStarted, @NonNull Map<Long, Long> threadToLatestRead); abstract @NonNull MmsSmsDatabase.TimestampReadResult 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);
@ -647,35 +647,34 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
} }
} }
static class ThreadUpdate { static class MessageUpdate {
private final long threadId; private final long threadId;
private final boolean verbose; private final MessageId messageId;
ThreadUpdate(long threadId, boolean verbose) { MessageUpdate(long threadId, @NonNull MessageId messageId) {
this.threadId = threadId; this.threadId = threadId;
this.verbose = verbose; this.messageId = messageId;
} }
public long getThreadId() { public long getThreadId() {
return threadId; return threadId;
} }
public boolean isVerbose() { public @NonNull MessageId getMessageId() {
return verbose; return messageId;
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
ThreadUpdate that = (ThreadUpdate) o; final MessageUpdate that = (MessageUpdate) o;
return threadId == that.threadId && return threadId == that.threadId && messageId.equals(that.messageId);
verbose == that.verbose;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(threadId, verbose); return Objects.hash(threadId, messageId);
} }
} }

Wyświetl plik

@ -607,9 +607,9 @@ public class MmsDatabase extends MessageDatabase {
} }
@Override @Override
public Set<ThreadUpdate> incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType) { public Set<MessageUpdate> incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType) {
SQLiteDatabase database = databaseHelper.getSignalWritableDatabase(); SQLiteDatabase database = databaseHelper.getSignalWritableDatabase();
Set<ThreadUpdate> threadUpdates = new HashSet<>(); Set<MessageUpdate> messageUpdates = new HashSet<>();
try (Cursor cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, MESSAGE_BOX, RECIPIENT_ID, receiptType.getColumnName(), RECEIPT_TIMESTAMP}, try (Cursor cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, MESSAGE_BOX, RECIPIENT_ID, receiptType.getColumnName(), RECEIPT_TIMESTAMP},
DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())}, DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())},
@ -637,16 +637,16 @@ public class MmsDatabase extends MessageDatabase {
SignalDatabase.groupReceipts().update(ourRecipientId, id, status, timestamp); SignalDatabase.groupReceipts().update(ourRecipientId, id, status, timestamp);
threadUpdates.add(new ThreadUpdate(threadId, !isFirstIncrement)); messageUpdates.add(new MessageUpdate(threadId, new MessageId(id, true)));
} }
} }
} }
if (threadUpdates.size() > 0 && receiptType == ReceiptType.DELIVERY) { if (messageUpdates.size() > 0 && receiptType == ReceiptType.DELIVERY) {
earlyDeliveryReceiptCache.increment(messageId.getTimetamp(), messageId.getRecipientId(), timestamp); earlyDeliveryReceiptCache.increment(messageId.getTimetamp(), messageId.getRecipientId(), timestamp);
} }
return threadUpdates; return messageUpdates;
} }
} }

Wyświetl plik

@ -29,7 +29,7 @@ import net.zetetic.database.sqlcipher.SQLiteQueryBuilder;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId; import org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.MessageDatabase.ThreadUpdate; import org.thoughtcrime.securesms.database.MessageDatabase.MessageUpdate;
import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.notifications.v2.MessageNotifierV2; import org.thoughtcrime.securesms.notifications.v2.MessageNotifierV2;
@ -405,32 +405,28 @@ public class MmsSmsDatabase extends Database {
* @return Whether or not some thread was updated. * @return Whether or not some thread was updated.
*/ */
private boolean incrementReceiptCount(SyncMessageId syncMessageId, long timestamp, @NonNull MessageDatabase.ReceiptType receiptType) { private boolean incrementReceiptCount(SyncMessageId syncMessageId, long timestamp, @NonNull MessageDatabase.ReceiptType receiptType) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
ThreadDatabase threadDatabase = SignalDatabase.threads(); ThreadDatabase threadDatabase = SignalDatabase.threads();
Set<ThreadUpdate> threadUpdates = new HashSet<>(); Set<MessageUpdate> messageUpdates = new HashSet<>();
db.beginTransaction(); db.beginTransaction();
try { try {
threadUpdates = incrementReceiptCountInternal(syncMessageId, timestamp, receiptType); messageUpdates = incrementReceiptCountInternal(syncMessageId, timestamp, receiptType);
for (ThreadUpdate threadUpdate : threadUpdates) { for (MessageUpdate messageUpdate : messageUpdates) {
threadDatabase.update(threadUpdate.getThreadId(), false); threadDatabase.update(messageUpdate.getThreadId(), false);
} }
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();
for (ThreadUpdate threadUpdate : threadUpdates) { for (MessageUpdate threadUpdate : messageUpdates) {
if (threadUpdate.isVerbose()) { ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(threadUpdate.getMessageId());
notifyVerboseConversationListeners(threadUpdate.getThreadId());
} else {
notifyConversationListeners(threadUpdate.getThreadId());
}
} }
} }
return threadUpdates.size() > 0; return messageUpdates.size() > 0;
} }
/** /**
@ -441,22 +437,22 @@ public class MmsSmsDatabase extends Database {
private @NonNull Collection<SyncMessageId> incrementReceiptCounts(@NonNull List<SyncMessageId> syncMessageIds, long timestamp, @NonNull MessageDatabase.ReceiptType receiptType) { private @NonNull Collection<SyncMessageId> incrementReceiptCounts(@NonNull List<SyncMessageId> syncMessageIds, long timestamp, @NonNull MessageDatabase.ReceiptType receiptType) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
ThreadDatabase threadDatabase = SignalDatabase.threads(); ThreadDatabase threadDatabase = SignalDatabase.threads();
Set<ThreadUpdate> threadUpdates = new HashSet<>(); Set<MessageUpdate> messageUpdates = new HashSet<>();
Collection<SyncMessageId> unhandled = new HashSet<>(); Collection<SyncMessageId> unhandled = new HashSet<>();
db.beginTransaction(); db.beginTransaction();
try { try {
for (SyncMessageId id : syncMessageIds) { for (SyncMessageId id : syncMessageIds) {
Set<ThreadUpdate> updates = incrementReceiptCountInternal(id, timestamp, receiptType); Set<MessageUpdate> updates = incrementReceiptCountInternal(id, timestamp, receiptType);
if (updates.size() > 0) { if (updates.size() > 0) {
threadUpdates.addAll(updates); messageUpdates.addAll(updates);
} else { } else {
unhandled.add(id); unhandled.add(id);
} }
} }
for (ThreadUpdate update : threadUpdates) { for (MessageUpdate update : messageUpdates) {
threadDatabase.updateSilently(update.getThreadId(), false); threadDatabase.updateSilently(update.getThreadId(), false);
} }
@ -464,15 +460,11 @@ public class MmsSmsDatabase extends Database {
} finally { } finally {
db.endTransaction(); db.endTransaction();
for (ThreadUpdate threadUpdate : threadUpdates) { for (MessageUpdate messageUpdate : messageUpdates) {
if (threadUpdate.isVerbose()) { ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(messageUpdate.getMessageId());
notifyVerboseConversationListeners(threadUpdate.getThreadId());
} else {
notifyConversationListeners(threadUpdate.getThreadId());
}
} }
if (threadUpdates.size() > 0) { if (messageUpdates.size() > 0) {
notifyConversationListListeners(); notifyConversationListListeners();
} }
} }
@ -484,13 +476,13 @@ public class MmsSmsDatabase extends Database {
/** /**
* Doesn't do any transactions or updates, so we can re-use the method safely. * Doesn't do any transactions or updates, so we can re-use the method safely.
*/ */
private @NonNull Set<ThreadUpdate> incrementReceiptCountInternal(SyncMessageId syncMessageId, long timestamp, MessageDatabase.ReceiptType receiptType) { private @NonNull Set<MessageUpdate> incrementReceiptCountInternal(SyncMessageId syncMessageId, long timestamp, MessageDatabase.ReceiptType receiptType) {
Set<ThreadUpdate> threadUpdates = new HashSet<>(); Set<MessageUpdate> messageUpdates = new HashSet<>();
threadUpdates.addAll(SignalDatabase.sms().incrementReceiptCount(syncMessageId, timestamp, receiptType)); messageUpdates.addAll(SignalDatabase.sms().incrementReceiptCount(syncMessageId, timestamp, receiptType));
threadUpdates.addAll(SignalDatabase.mms().incrementReceiptCount(syncMessageId, timestamp, receiptType)); messageUpdates.addAll(SignalDatabase.mms().incrementReceiptCount(syncMessageId, timestamp, receiptType));
return threadUpdates; return messageUpdates;
} }

Wyświetl plik

@ -481,18 +481,18 @@ public class SmsDatabase extends MessageDatabase {
} }
@Override @Override
public @NonNull Set<ThreadUpdate> incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType) { public @NonNull Set<MessageUpdate> incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType) {
if (receiptType == ReceiptType.VIEWED) { if (receiptType == ReceiptType.VIEWED) {
return Collections.emptySet(); return Collections.emptySet();
} }
SQLiteDatabase database = databaseHelper.getSignalWritableDatabase(); SQLiteDatabase database = databaseHelper.getSignalWritableDatabase();
Set<ThreadUpdate> threadUpdates = new HashSet<>(); Set<MessageUpdate> messageUpdates = new HashSet<>();
try (Cursor cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, RECIPIENT_ID, TYPE, DELIVERY_RECEIPT_COUNT, READ_RECEIPT_COUNT, RECEIPT_TIMESTAMP}, try (Cursor cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, RECIPIENT_ID, TYPE, DELIVERY_RECEIPT_COUNT, READ_RECEIPT_COUNT, RECEIPT_TIMESTAMP},
DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())}, DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())},
null, null, null, null)) { null, null, null, null))
{
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
if (Types.isOutgoingMessageType(CursorUtil.requireLong(cursor, TYPE))) { if (Types.isOutgoingMessageType(CursorUtil.requireLong(cursor, TYPE))) {
RecipientId theirRecipientId = messageId.getRecipientId(); RecipientId theirRecipientId = messageId.getRecipientId();
@ -512,16 +512,16 @@ public class SmsDatabase extends MessageDatabase {
ID + " = ?", ID + " = ?",
SqlUtil.buildArgs(updatedTimestamp, id)); SqlUtil.buildArgs(updatedTimestamp, id));
threadUpdates.add(new ThreadUpdate(threadId, !isFirstIncrement)); messageUpdates.add(new MessageUpdate(threadId, new MessageId(id, false)));
} }
} }
} }
if (threadUpdates.isEmpty() && receiptType == ReceiptType.DELIVERY) { if (messageUpdates.isEmpty() && receiptType == ReceiptType.DELIVERY) {
earlyDeliveryReceiptCache.increment(messageId.getTimetamp(), messageId.getRecipientId(), timestamp); earlyDeliveryReceiptCache.increment(messageId.getTimetamp(), messageId.getRecipientId(), timestamp);
} }
return threadUpdates; return messageUpdates;
} }
} }

Wyświetl plik

@ -195,13 +195,24 @@ class FixedSizePagingController<Key, Data> implements PagingController<Key> {
List<Data> updatedList = new CompressedList<>(data); List<Data> updatedList = new CompressedList<>(data);
updatedList.add(position, item); updatedList.add(position, item);
keyToPosition.put(dataSource.getKey(item), position); rebuildKeyToPositionMap(keyToPosition, updatedList, dataSource);
data = updatedList; data = updatedList;
liveData.postValue(updatedList); liveData.postValue(updatedList);
}); });
} }
private void rebuildKeyToPositionMap(@NonNull Map<Key, Integer> map, @NonNull List<Data> dataList, @NonNull PagedDataSource<Key, Data> dataSource) {
map.clear();
for (int i = 0, len = dataList.size(); i < len; i++) {
Data item = dataList.get(i);
if (item != null) {
map.put(dataSource.getKey(item), i);
}
}
}
private static String buildLog(int aroundIndex, String message) { private static String buildLog(int aroundIndex, String message) {
return "onDataNeededAroundIndex(" + aroundIndex + ") " + message; return "onDataNeededAroundIndex(" + aroundIndex + ") " + message;
} }