Fix in-memory message updates.
We can also switch to using the message-specific update route for receipts too.
This commit is contained in:
parent
0dd2397fb4
commit
0d0c74f358
6 changed files with 61 additions and 63 deletions
|
@ -51,10 +51,6 @@ public abstract class Database {
|
|||
ApplicationDependencies.getDatabaseObserver().notifyVerboseConversationListeners(threadIds);
|
||||
}
|
||||
|
||||
protected void notifyVerboseConversationListeners(long threadId) {
|
||||
ApplicationDependencies.getDatabaseObserver().notifyVerboseConversationListeners(threadId);
|
||||
}
|
||||
|
||||
protected void notifyConversationListListeners() {
|
||||
ApplicationDependencies.getDatabaseObserver().notifyConversationListListeners();
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
|
|||
public abstract void markDownloadState(long messageId, long state);
|
||||
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);
|
||||
public abstract List<MarkedMessageInfo> setEntireThreadRead(long threadId);
|
||||
public abstract List<MarkedMessageInfo> setMessagesReadSince(long threadId, long timestamp);
|
||||
|
@ -647,35 +647,34 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
|
|||
}
|
||||
}
|
||||
|
||||
static class ThreadUpdate {
|
||||
private final long threadId;
|
||||
private final boolean verbose;
|
||||
static class MessageUpdate {
|
||||
private final long threadId;
|
||||
private final MessageId messageId;
|
||||
|
||||
ThreadUpdate(long threadId, boolean verbose) {
|
||||
this.threadId = threadId;
|
||||
this.verbose = verbose;
|
||||
MessageUpdate(long threadId, @NonNull MessageId messageId) {
|
||||
this.threadId = threadId;
|
||||
this.messageId = messageId;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
return threadId;
|
||||
}
|
||||
|
||||
public boolean isVerbose() {
|
||||
return verbose;
|
||||
public @NonNull MessageId getMessageId() {
|
||||
return messageId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ThreadUpdate that = (ThreadUpdate) o;
|
||||
return threadId == that.threadId &&
|
||||
verbose == that.verbose;
|
||||
final MessageUpdate that = (MessageUpdate) o;
|
||||
return threadId == that.threadId && messageId.equals(that.messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(threadId, verbose);
|
||||
return Objects.hash(threadId, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -607,9 +607,9 @@ public class MmsDatabase extends MessageDatabase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<ThreadUpdate> incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType) {
|
||||
SQLiteDatabase database = databaseHelper.getSignalWritableDatabase();
|
||||
Set<ThreadUpdate> threadUpdates = new HashSet<>();
|
||||
public Set<MessageUpdate> incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType) {
|
||||
SQLiteDatabase database = databaseHelper.getSignalWritableDatabase();
|
||||
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},
|
||||
DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())},
|
||||
|
@ -637,16 +637,16 @@ public class MmsDatabase extends MessageDatabase {
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
return threadUpdates;
|
||||
return messageUpdates;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ import net.zetetic.database.sqlcipher.SQLiteQueryBuilder;
|
|||
|
||||
import org.signal.core.util.logging.Log;
|
||||
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.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.notifications.v2.MessageNotifierV2;
|
||||
|
@ -405,32 +405,28 @@ public class MmsSmsDatabase extends Database {
|
|||
* @return Whether or not some thread was updated.
|
||||
*/
|
||||
private boolean incrementReceiptCount(SyncMessageId syncMessageId, long timestamp, @NonNull MessageDatabase.ReceiptType receiptType) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
ThreadDatabase threadDatabase = SignalDatabase.threads();
|
||||
Set<ThreadUpdate> threadUpdates = new HashSet<>();
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
ThreadDatabase threadDatabase = SignalDatabase.threads();
|
||||
Set<MessageUpdate> messageUpdates = new HashSet<>();
|
||||
|
||||
db.beginTransaction();
|
||||
try {
|
||||
threadUpdates = incrementReceiptCountInternal(syncMessageId, timestamp, receiptType);
|
||||
messageUpdates = incrementReceiptCountInternal(syncMessageId, timestamp, receiptType);
|
||||
|
||||
for (ThreadUpdate threadUpdate : threadUpdates) {
|
||||
threadDatabase.update(threadUpdate.getThreadId(), false);
|
||||
for (MessageUpdate messageUpdate : messageUpdates) {
|
||||
threadDatabase.update(messageUpdate.getThreadId(), false);
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
||||
for (ThreadUpdate threadUpdate : threadUpdates) {
|
||||
if (threadUpdate.isVerbose()) {
|
||||
notifyVerboseConversationListeners(threadUpdate.getThreadId());
|
||||
} else {
|
||||
notifyConversationListeners(threadUpdate.getThreadId());
|
||||
}
|
||||
for (MessageUpdate threadUpdate : messageUpdates) {
|
||||
ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(threadUpdate.getMessageId());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
ThreadDatabase threadDatabase = SignalDatabase.threads();
|
||||
Set<ThreadUpdate> threadUpdates = new HashSet<>();
|
||||
Set<MessageUpdate> messageUpdates = new HashSet<>();
|
||||
Collection<SyncMessageId> unhandled = new HashSet<>();
|
||||
|
||||
db.beginTransaction();
|
||||
try {
|
||||
for (SyncMessageId id : syncMessageIds) {
|
||||
Set<ThreadUpdate> updates = incrementReceiptCountInternal(id, timestamp, receiptType);
|
||||
Set<MessageUpdate> updates = incrementReceiptCountInternal(id, timestamp, receiptType);
|
||||
|
||||
if (updates.size() > 0) {
|
||||
threadUpdates.addAll(updates);
|
||||
messageUpdates.addAll(updates);
|
||||
} else {
|
||||
unhandled.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (ThreadUpdate update : threadUpdates) {
|
||||
for (MessageUpdate update : messageUpdates) {
|
||||
threadDatabase.updateSilently(update.getThreadId(), false);
|
||||
}
|
||||
|
||||
|
@ -464,15 +460,11 @@ public class MmsSmsDatabase extends Database {
|
|||
} finally {
|
||||
db.endTransaction();
|
||||
|
||||
for (ThreadUpdate threadUpdate : threadUpdates) {
|
||||
if (threadUpdate.isVerbose()) {
|
||||
notifyVerboseConversationListeners(threadUpdate.getThreadId());
|
||||
} else {
|
||||
notifyConversationListeners(threadUpdate.getThreadId());
|
||||
}
|
||||
for (MessageUpdate messageUpdate : messageUpdates) {
|
||||
ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(messageUpdate.getMessageId());
|
||||
}
|
||||
|
||||
if (threadUpdates.size() > 0) {
|
||||
if (messageUpdates.size() > 0) {
|
||||
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.
|
||||
*/
|
||||
private @NonNull Set<ThreadUpdate> incrementReceiptCountInternal(SyncMessageId syncMessageId, long timestamp, MessageDatabase.ReceiptType receiptType) {
|
||||
Set<ThreadUpdate> threadUpdates = new HashSet<>();
|
||||
private @NonNull Set<MessageUpdate> incrementReceiptCountInternal(SyncMessageId syncMessageId, long timestamp, MessageDatabase.ReceiptType receiptType) {
|
||||
Set<MessageUpdate> messageUpdates = new HashSet<>();
|
||||
|
||||
threadUpdates.addAll(SignalDatabase.sms().incrementReceiptCount(syncMessageId, timestamp, receiptType));
|
||||
threadUpdates.addAll(SignalDatabase.mms().incrementReceiptCount(syncMessageId, timestamp, receiptType));
|
||||
messageUpdates.addAll(SignalDatabase.sms().incrementReceiptCount(syncMessageId, timestamp, receiptType));
|
||||
messageUpdates.addAll(SignalDatabase.mms().incrementReceiptCount(syncMessageId, timestamp, receiptType));
|
||||
|
||||
return threadUpdates;
|
||||
return messageUpdates;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -481,18 +481,18 @@ public class SmsDatabase extends MessageDatabase {
|
|||
}
|
||||
|
||||
@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) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
SQLiteDatabase database = databaseHelper.getSignalWritableDatabase();
|
||||
Set<ThreadUpdate> threadUpdates = new HashSet<>();
|
||||
SQLiteDatabase database = databaseHelper.getSignalWritableDatabase();
|
||||
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},
|
||||
DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())},
|
||||
null, null, null, null)) {
|
||||
|
||||
DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())},
|
||||
null, null, null, null))
|
||||
{
|
||||
while (cursor.moveToNext()) {
|
||||
if (Types.isOutgoingMessageType(CursorUtil.requireLong(cursor, TYPE))) {
|
||||
RecipientId theirRecipientId = messageId.getRecipientId();
|
||||
|
@ -512,16 +512,16 @@ public class SmsDatabase extends MessageDatabase {
|
|||
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);
|
||||
}
|
||||
|
||||
return threadUpdates;
|
||||
return messageUpdates;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -195,13 +195,24 @@ class FixedSizePagingController<Key, Data> implements PagingController<Key> {
|
|||
List<Data> updatedList = new CompressedList<>(data);
|
||||
|
||||
updatedList.add(position, item);
|
||||
keyToPosition.put(dataSource.getKey(item), position);
|
||||
rebuildKeyToPositionMap(keyToPosition, updatedList, dataSource);
|
||||
|
||||
data = 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) {
|
||||
return "onDataNeededAroundIndex(" + aroundIndex + ") " + message;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue