Fix crash with disappearing messages while viewing message details.

This commit is contained in:
Cody Henthorne 2022-02-11 11:52:50 -05:00 committed by Greyson Parrelli
parent 2718dca6ea
commit 1692caeab7
3 changed files with 21 additions and 74 deletions

View file

@ -438,7 +438,7 @@ 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<MessageUpdate> messageUpdates = new HashSet<>();
Set<MessageUpdate> messageUpdates = new HashSet<>();
Collection<SyncMessageId> unhandled = new HashSet<>();
db.beginTransaction();
@ -455,16 +455,14 @@ public class MmsSmsDatabase extends Database {
for (MessageUpdate update : messageUpdates) {
threadDatabase.updateSilently(update.getThreadId(), false);
ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(update.getMessageId());
ApplicationDependencies.getDatabaseObserver().notifyVerboseConversationListeners(Collections.singleton(update.getThreadId()));
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
for (MessageUpdate messageUpdate : messageUpdates) {
ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(messageUpdate.getMessageId());
}
if (messageUpdates.size() > 0) {
notifyConversationListListeners();
}

View file

@ -12,9 +12,11 @@ import org.signal.core.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.conversation.ConversationMessage.ConversationMessageFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.recipients.Recipient;
@ -27,7 +29,7 @@ final class MessageDetailsRepository {
private final Context context = ApplicationDependencies.getApplication();
@NonNull LiveData<MessageRecord> getMessageRecord(String type, Long messageId) {
return new MessageRecordLiveData(context, type, messageId);
return new MessageRecordLiveData(new MessageId(messageId, type.equals(MmsSmsDatabase.MMS_TRANSPORT)));
}
@NonNull LiveData<MessageDetails> getMessageDetails(@Nullable MessageRecord messageRecord) {

View file

@ -1,104 +1,51 @@
package org.thoughtcrime.securesms.messagedetails;
import android.content.Context;
import android.database.Cursor;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import androidx.lifecycle.LiveData;
import org.signal.core.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.database.DatabaseObserver;
import org.thoughtcrime.securesms.database.MessageDatabase;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
final class MessageRecordLiveData extends LiveData<MessageRecord> {
private final Context context;
private final String type;
private final Long messageId;
private final DatabaseObserver.Observer observer;
private final MessageId messageId;
private @Nullable Cursor cursor;
MessageRecordLiveData(Context context, String type, Long messageId) {
this.context = context;
this.type = type;
MessageRecordLiveData(MessageId messageId) {
this.messageId = messageId;
this.observer = () -> SignalExecutors.BOUNDED.execute(this::resetCursor);
this.observer = this::retrieveMessageRecordActual;
}
@Override
protected void onActive() {
retrieveMessageRecord();
SignalExecutors.BOUNDED_IO.execute(this::retrieveMessageRecordActual);
}
@Override
protected void onInactive() {
SignalExecutors.BOUNDED.execute(this::destroyCursor);
}
private void retrieveMessageRecord() {
SignalExecutors.BOUNDED.execute(this::retrieveMessageRecordActual);
}
@WorkerThread
private synchronized void destroyCursor() {
ApplicationDependencies.getDatabaseObserver().unregisterObserver(observer);
if (cursor != null) {
cursor.close();
cursor = null;
}
}
@WorkerThread
private synchronized void resetCursor() {
destroyCursor();
retrieveMessageRecord();
}
@WorkerThread
private synchronized void retrieveMessageRecordActual() {
if (cursor != null) {
return;
}
switch (type) {
case MmsSmsDatabase.SMS_TRANSPORT:
handleSms();
break;
case MmsSmsDatabase.MMS_TRANSPORT:
handleMms();
break;
default:
throw new AssertionError("no valid message type specified");
}
retrieve(messageId.isMms() ? SignalDatabase.mms() : SignalDatabase.sms());
}
@WorkerThread
private synchronized void handleSms() {
final MessageDatabase db = SignalDatabase.sms();
final Cursor cursor = db.getMessageCursor(messageId);
final MessageRecord record = SmsDatabase.readerFor(cursor).getNext();
postValue(record);
ApplicationDependencies.getDatabaseObserver().registerVerboseConversationObserver(record.getThreadId(), observer);
this.cursor = cursor;
}
@WorkerThread
private synchronized void handleMms() {
final MessageDatabase db = SignalDatabase.mms();
final Cursor cursor = db.getMessageCursor(messageId);
final MessageRecord record = MmsDatabase.readerFor(cursor).getNext();
postValue(record);
ApplicationDependencies.getDatabaseObserver().registerVerboseConversationObserver(record.getThreadId(), observer);
this.cursor = cursor;
private synchronized void retrieve(MessageDatabase messageDatabase) {
try {
final MessageRecord record = messageDatabase.getMessageRecord(messageId.getId());
postValue(record);
ApplicationDependencies.getDatabaseObserver().registerVerboseConversationObserver(record.getThreadId(), observer);
} catch (NoSuchMessageException ignored) {
postValue(null);
}
}
}