Migrate most of MmsSmsTable.

This commit is contained in:
Greyson Parrelli 2022-12-30 18:17:39 -05:00
parent f149c0adb9
commit 6cd6073bc7
33 changed files with 884 additions and 1069 deletions

View file

@ -24,7 +24,7 @@ class MessageContentProcessor__handleTextMessageTest : MessageContentProcessorTe
// THEN
val record = SignalDatabase.messages.getMessageRecord(1)
val threadSize = SignalDatabase.mmsSms.getConversationCount(record.threadId)
val threadSize = SignalDatabase.messages.getMessageCountForThread(record.threadId)
assertEquals(1, threadSize)
assertTrue(record.isSecure)

View file

@ -80,9 +80,9 @@ class VoiceNoteMediaItemFactory {
@Nullable static MediaItem buildMediaItem(@NonNull Context context,
@NonNull MessageRecord messageRecord)
{
int startingPosition = SignalDatabase.mmsSms()
.getMessagePositionInConversation(messageRecord.getThreadId(),
messageRecord.getDateReceived());
int startingPosition = SignalDatabase.messages()
.getMessagePositionInConversation(messageRecord.getThreadId(),
messageRecord.getDateReceived());
Recipient threadRecipient = Objects.requireNonNull(SignalDatabase.threads()
.getRecipientForThreadId(messageRecord.getThreadId()));

View file

@ -267,8 +267,7 @@ final class VoiceNotePlaybackPreparer implements MediaSessionConnector.Playbac
@WorkerThread
private @NonNull List<MediaItem> loadMediaItemsForConsecutivePlayback(long messageId) {
try {
List<MessageRecord> recordsAfter = SignalDatabase.mmsSms()
.getMessagesAfterVoiceNoteInclusive(messageId, LIMIT);
List<MessageRecord> recordsAfter = SignalDatabase.messages().getMessagesAfterVoiceNoteInclusive(messageId, LIMIT);
return buildFilteredMessageRecordList(recordsAfter).stream()
.map(record -> VoiceNoteMediaItemFactory

View file

@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.conversation.ConversationData.MessageRequestData;
import org.thoughtcrime.securesms.conversation.ConversationMessage.ConversationMessageFactory;
import org.thoughtcrime.securesms.database.CallTable;
import org.thoughtcrime.securesms.database.MessageTable;
import org.thoughtcrime.securesms.database.MmsSmsTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.model.InMemoryMessageRecord;
@ -87,7 +88,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
}
}
return SignalDatabase.mmsSms().getConversationCount(threadId);
return SignalDatabase.messages().getMessageCountForThread(threadId);
}
@Override
@ -103,7 +104,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
CallHelper callHelper = new CallHelper();
Set<ServiceId> referencedIds = new HashSet<>();
try (MmsSmsTable.Reader reader = MmsSmsTable.readerFor(db.getConversation(threadId, start, length))) {
try (MessageTable.Reader reader = MessageTable.mmsReaderFor(db.getConversation(threadId, start, length))) {
MessageRecord record;
while ((record = reader.getNext()) != null && !cancellationSignal.isCanceled()) {
records.add(record);
@ -194,7 +195,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
List<Mention> mentions = SignalDatabase.mentions().getMentionsForMessage(messageId.getId());
stopwatch.split("mentions");
boolean isQuoted = SignalDatabase.mmsSms().isQuoted(record);
boolean isQuoted = SignalDatabase.messages().isQuoted(record);
stopwatch.split("is-quoted");
List<ReactionRecord> reactions = SignalDatabase.reactions().getReactions(messageId);
@ -265,7 +266,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
}
void fetchQuotedState() {
hasBeenQuotedIds = SignalDatabase.mmsSms().isQuoted(records);
hasBeenQuotedIds = SignalDatabase.messages().isQuoted(records);
}
boolean isQuoted(long id) {

View file

@ -1309,7 +1309,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
@SuppressWarnings("CodeBlock2Expr")
public void jumpToMessage(@NonNull RecipientId author, long timestamp, @Nullable Runnable onMessageNotFound) {
SimpleTask.run(getLifecycle(), () -> {
return SignalDatabase.mmsSms().getMessagePositionInConversation(threadId, timestamp, author);
return SignalDatabase.messages().getMessagePositionInConversation(threadId, timestamp, author);
}, p -> moveToPosition(p + (isTypingIndicatorShowing() ? 1 : 0), onMessageNotFound));
}
@ -1453,7 +1453,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
@Override
public void jumpToMessage(@NonNull MessageRecord messageRecord) {
SimpleTask.run(getLifecycle(), () -> {
return SignalDatabase.mmsSms().getMessagePositionInConversation(threadId,
return SignalDatabase.messages().getMessagePositionInConversation(threadId,
messageRecord.getDateReceived(),
messageRecord.isOutgoing() ? Recipient.self().getId() : messageRecord.getRecipient().getId());
}, p -> moveToPosition(p + (isTypingIndicatorShowing() ? 1 : 0), () -> {
@ -1738,9 +1738,9 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
}
SimpleTask.run(getLifecycle(), () -> {
return SignalDatabase.mmsSms().getQuotedMessagePosition(threadId,
messageRecord.getQuote().getId(),
messageRecord.getQuote().getAuthor());
return SignalDatabase.messages().getQuotedMessagePosition(threadId,
messageRecord.getQuote().getId(),
messageRecord.getQuote().getAuthor());
}, p -> moveToPosition(p + (isTypingIndicatorShowing() ? 1 : 0), () -> {
Toast.makeText(getContext(), R.string.ConversationFragment_quoted_message_no_longer_available, Toast.LENGTH_SHORT).show();
}));

View file

@ -186,7 +186,7 @@ public class ConversationMessage {
*/
@WorkerThread
public static @NonNull ConversationMessage createWithUnresolvedData(@NonNull Context context, @NonNull MessageRecord messageRecord, @NonNull CharSequence body) {
boolean hasBeenQuoted = SignalDatabase.mmsSms().isQuoted(messageRecord);
boolean hasBeenQuoted = SignalDatabase.messages().isQuoted(messageRecord);
if (messageRecord.isMms()) {
List<Mention> mentions = SignalDatabase.mentions().getMentionsForMessage(messageRecord.getId());

View file

@ -3889,7 +3889,7 @@ public class ConversationParentFragment extends Fragment
SimpleTask.run(() -> {
//noinspection CodeBlock2Expr
return SignalDatabase.mmsSms().checkMessageExists(reactionDelegate.getMessageRecord());
return SignalDatabase.messages().checkMessageExists(reactionDelegate.getMessageRecord());
}, messageExists -> {
if (!messageExists) {
reactionDelegate.hide();

View file

@ -59,7 +59,7 @@ class ConversationRepository {
@WorkerThread
public @NonNull ConversationData getConversationData(long threadId, @NonNull Recipient conversationRecipient, int jumpToPosition) {
ThreadTable.ConversationMetadata metadata = SignalDatabase.threads().getConversationMetadata(threadId);
int threadSize = SignalDatabase.mmsSms().getConversationCount(threadId);
int threadSize = SignalDatabase.messages().getMessageCountForThread(threadId);
long lastSeen = metadata.getLastSeen();
int lastSeenPosition = 0;
long lastScrolled = metadata.getLastScrolled();
@ -69,7 +69,7 @@ class ConversationRepository {
boolean showUniversalExpireTimerUpdate = false;
if (lastSeen > 0) {
lastSeenPosition = SignalDatabase.mmsSms().getMessagePositionOnOrAfterTimestamp(threadId, lastSeen);
lastSeenPosition = SignalDatabase.messages().getMessagePositionOnOrAfterTimestamp(threadId, lastSeen);
}
if (lastSeenPosition <= 0) {
@ -77,7 +77,7 @@ class ConversationRepository {
}
if (lastSeen == 0 && lastScrolled > 0) {
lastScrolledPosition = SignalDatabase.mmsSms().getMessagePositionOnOrAfterTimestamp(threadId, lastScrolled);
lastScrolledPosition = SignalDatabase.messages().getMessagePositionOnOrAfterTimestamp(threadId, lastScrolled);
}
if (!isMessageRequestAccepted) {
@ -105,7 +105,7 @@ class ConversationRepository {
conversationRecipient.getExpiresInSeconds() == 0 &&
!conversationRecipient.isGroup() &&
conversationRecipient.isRegistered() &&
(threadId == -1 || !SignalDatabase.mmsSms().hasMeaningfulMessage(threadId)))
(threadId == -1 || !SignalDatabase.messages().hasMeaningfulMessage(threadId)))
{
showUniversalExpireTimerUpdate = true;
}
@ -172,7 +172,7 @@ class ConversationRepository {
long threadId = SignalDatabase.threads().getThreadIdIfExistsFor(recipient.getId());
boolean hasUnexportedInsecureMessages = threadId != -1 && SignalDatabase.mmsSms().getUnexportedInsecureMessagesCount(threadId) > 0;
boolean hasUnexportedInsecureMessages = threadId != -1 && SignalDatabase.messages().getUnexportedInsecureMessagesCount(threadId) > 0;
Log.i(TAG, "Returning registered state...");
return new ConversationSecurityInfo(recipient.getId(),
@ -190,7 +190,7 @@ class ConversationRepository {
return Observable.<Integer> create(emitter -> {
DatabaseObserver.Observer listener = () -> emitter.onNext(SignalDatabase.mmsSms().getIncomingMeaningfulMessageCountSince(threadId, afterTime));
DatabaseObserver.Observer listener = () -> emitter.onNext(SignalDatabase.messages().getIncomingMeaningfulMessageCountSince(threadId, afterTime));
ApplicationDependencies.getDatabaseObserver().registerConversationObserver(threadId, listener);
emitter.setCancellable(() -> ApplicationDependencies.getDatabaseObserver().unregisterObserver(listener));

View file

@ -27,7 +27,7 @@ class MessageQuotesRepository {
*/
fun getMessagesInQuoteChain(application: Application, messageId: MessageId): Observable<List<ConversationMessage>> {
return Observable.create { emitter ->
val threadId: Long = SignalDatabase.mmsSms.getThreadId(messageId)
val threadId: Long = SignalDatabase.messages.getThreadIdForMessage(messageId.id)
if (threadId < 0) {
Log.w(TAG, "Could not find a threadId for $messageId!")
emitter.onNext(emptyList())
@ -46,7 +46,7 @@ class MessageQuotesRepository {
@WorkerThread
private fun getMessagesInQuoteChainSync(application: Application, messageId: MessageId): List<ConversationMessage> {
val rootMessageId: MessageId = SignalDatabase.mmsSms.getRootOfQuoteChain(messageId)
val rootMessageId: MessageId = SignalDatabase.messages.getRootOfQuoteChain(messageId)
var originalRecord: MessageRecord? = SignalDatabase.messages.getMessageRecordOrNull(rootMessageId.id)

View file

@ -616,7 +616,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
@Override
public void onMessageClicked(@NonNull MessageResult message) {
SimpleTask.run(getViewLifecycleOwner().getLifecycle(), () -> {
int startingPosition = SignalDatabase.mmsSms().getMessagePositionInConversation(message.getThreadId(), message.getReceivedTimestampMs());
int startingPosition = SignalDatabase.messages().getMessagePositionInConversation(message.getThreadId(), message.getReceivedTimestampMs());
return Math.max(0, startingPosition);
}, startingPosition -> {
hideKeyboard();

View file

@ -16,51 +16,26 @@
*/
package org.thoughtcrime.securesms.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.annimon.stream.Stream;
import com.google.protobuf.InvalidProtocolBufferException;
import net.zetetic.database.sqlcipher.SQLiteQueryBuilder;
import org.signal.core.util.CursorUtil;
import org.signal.core.util.SqlUtil;
import org.signal.core.util.logging.Log;
import org.signal.libsignal.protocol.util.Pair;
import org.thoughtcrime.securesms.database.MessageTable.MessageUpdate;
import org.thoughtcrime.securesms.database.MessageTable.SyncMessageId;
import org.thoughtcrime.securesms.database.model.DisplayRecord;
import org.thoughtcrime.securesms.database.model.MessageExportStatus;
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.database.model.databaseprotos.MessageExportState;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.notifications.v2.DefaultMessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage;
import java.io.Closeable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
public class MmsSmsTable extends DatabaseTable {
@ -112,61 +87,15 @@ public class MmsSmsTable extends DatabaseTable {
MessageTable.STORY_TYPE,
MessageTable.PARENT_STORY_ID};
private static final String SNIPPET_QUERY = "SELECT " + MessageTable.ID + ", " + MessageTable.TYPE + ", " + MessageTable.DATE_RECEIVED + " FROM " + MessageTable.TABLE_NAME + " " +
"WHERE " + MessageTable.THREAD_ID + " = ? AND " + MessageTable.TYPE + " & " + MessageTypes.GROUP_V2_LEAVE_BITS + " != " + MessageTypes.GROUP_V2_LEAVE_BITS + " AND " + MessageTable.STORY_TYPE + " = 0 AND " + MessageTable.PARENT_STORY_ID + " <= 0 " +
"ORDER BY " + MessageTable.DATE_RECEIVED + " DESC " +
"LIMIT 1";
public MmsSmsTable(Context context, SignalDatabase databaseHelper) {
super(context, databaseHelper);
}
/**
* @return The user that added you to the group, otherwise null.
*/
public @Nullable RecipientId getGroupAddedBy(long threadId) {
long lastQuitChecked = System.currentTimeMillis();
Pair<RecipientId, Long> pair;
do {
pair = getGroupAddedBy(threadId, lastQuitChecked);
if (pair.first() != null) {
return pair.first();
} else {
lastQuitChecked = pair.second();
}
} while (pair.second() != -1);
return null;
}
private @NonNull Pair<RecipientId, Long> getGroupAddedBy(long threadId, long lastQuitChecked) {
long latestQuit = SignalDatabase.messages().getLatestGroupQuitTimestamp(threadId, lastQuitChecked);
RecipientId id = SignalDatabase.messages().getOldestGroupUpdateSender(threadId, latestQuit);
return new Pair<>(id, latestQuit);
}
public int getMessagePositionOnOrAfterTimestamp(long threadId, long timestamp) {
String[] projection = new String[] { "COUNT(*)" };
String selection = MessageTable.THREAD_ID + " = " + threadId + " AND " +
MessageTable.DATE_RECEIVED + " >= " + timestamp + " AND " +
MessageTable.STORY_TYPE + " = 0 AND " + MessageTable.PARENT_STORY_ID + " <= 0";
try (Cursor cursor = queryTables(projection, selection, null, null, false)) {
if (cursor != null && cursor.moveToNext()) {
return cursor.getInt(0);
}
}
return 0;
}
public @Nullable MessageRecord getMessageFor(long timestamp, RecipientId authorId) {
Recipient author = Recipient.resolved(authorId);
try (Cursor cursor = queryTables(PROJECTION, MessageTable.DATE_SENT + " = " + timestamp, null, null, true)) {
MmsSmsTable.Reader reader = readerFor(cursor);
MessageTable.Reader reader = MessageTable.mmsReaderFor(cursor);
MessageRecord messageRecord;
@ -182,16 +111,6 @@ public class MmsSmsTable extends DatabaseTable {
return null;
}
public @NonNull List<MessageRecord> getMessagesAfterVoiceNoteInclusive(long messageId, long limit) throws NoSuchMessageException {
MessageRecord origin = SignalDatabase.messages().getMessageRecord(messageId);
List<MessageRecord> mms = SignalDatabase.messages().getMessagesInThreadAfterInclusive(origin.getThreadId(), origin.getDateReceived(), limit);
Collections.sort(mms, Comparator.comparingLong(DisplayRecord::getDateReceived));
return Stream.of(mms).limit(limit).toList();
}
public Cursor getConversation(long threadId, long offset, long limit) {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
String order = MessageTable.DATE_RECEIVED + " DESC";
@ -205,35 +124,6 @@ public class MmsSmsTable extends DatabaseTable {
public Cursor getConversation(long threadId) {
return getConversation(threadId, 0, 0);
}
public @NonNull MessageRecord getConversationSnippet(long threadId) throws NoSuchMessageException {
try (Cursor cursor = getConversationSnippetCursor(threadId)) {
if (cursor.moveToFirst()) {
long id = CursorUtil.requireLong(cursor, MessageTable.ID);
return SignalDatabase.messages().getMessageRecord(id);
} else {
throw new NoSuchMessageException("no message");
}
}
}
@VisibleForTesting
@NonNull Cursor getConversationSnippetCursor(long threadId) {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
return db.rawQuery(SNIPPET_QUERY, SqlUtil.buildArgs(threadId));
}
public long getConversationSnippetType(long threadId) throws NoSuchMessageException {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
try (Cursor cursor = db.rawQuery(SNIPPET_QUERY, SqlUtil.buildArgs(threadId))) {
if (cursor.moveToFirst()) {
return CursorUtil.requireLong(cursor, MessageTable.TYPE);
} else {
throw new NoSuchMessageException("no message");
}
}
}
public Cursor getMessagesForNotificationState(Collection<DefaultMessageNotifier.StickyThread> stickyThreads) {
StringBuilder stickyQuery = new StringBuilder();
for (DefaultMessageNotifier.StickyThread stickyThread : stickyThreads) {
@ -257,86 +147,6 @@ public class MmsSmsTable extends DatabaseTable {
return queryTables(PROJECTION, selection, order, null, true);
}
public Set<Long> isQuoted(@NonNull Collection<MessageRecord> records) {
if (records.isEmpty()) {
return Collections.emptySet();
}
Map<QuoteDescriptor, MessageRecord> byQuoteDescriptor = new HashMap<>(records.size());
List<String[]> args = new ArrayList<>(records.size());
for (MessageRecord record : records) {
long timestamp = record.getDateSent();
RecipientId author = record.isOutgoing() ? Recipient.self().getId() : record.getRecipient().getId();
byQuoteDescriptor.put(new QuoteDescriptor(timestamp, author), record);
args.add(SqlUtil.buildArgs(timestamp, author));
}
String[] projection = new String[] { MessageTable.QUOTE_ID, MessageTable.QUOTE_AUTHOR };
List<SqlUtil.Query> queries = SqlUtil.buildCustomCollectionQuery(MessageTable.QUOTE_ID + " = ? AND " + MessageTable.QUOTE_AUTHOR + " = ?", args);
Set<Long> quotedIds = new HashSet<>();
for (SqlUtil.Query query : queries) {
try (Cursor cursor = getReadableDatabase().query(MessageTable.TABLE_NAME, projection, query.getWhere(), query.getWhereArgs(), null, null, null)) {
while (cursor.moveToNext()) {
long timestamp = CursorUtil.requireLong(cursor, MessageTable.QUOTE_ID);
RecipientId author = RecipientId.from(CursorUtil.requireString(cursor, MessageTable.QUOTE_AUTHOR));
QuoteDescriptor quoteLocator = new QuoteDescriptor(timestamp, author);
quotedIds.add(byQuoteDescriptor.get(quoteLocator).getId());
}
}
}
return quotedIds;
}
/**
* Whether or not the message has been quoted by another message.
*/
public boolean isQuoted(@NonNull MessageRecord messageRecord) {
RecipientId author = messageRecord.isOutgoing() ? Recipient.self().getId() : messageRecord.getRecipient().getId();
long timestamp = messageRecord.getDateSent();
String where = MessageTable.QUOTE_ID + " = ? AND " + MessageTable.QUOTE_AUTHOR + " = ?";
String[] whereArgs = SqlUtil.buildArgs(timestamp, author);
try (Cursor cursor = getReadableDatabase().query(MessageTable.TABLE_NAME, new String[]{ "1" }, where, whereArgs, null, null, null, "1")) {
return cursor.moveToFirst();
}
}
public MessageId getRootOfQuoteChain(@NonNull MessageId id) {
MmsMessageRecord targetMessage;
try {
targetMessage = (MmsMessageRecord) SignalDatabase.messages().getMessageRecord(id.getId());
} catch (NoSuchMessageException e) {
throw new IllegalArgumentException("Invalid message ID!");
}
if (targetMessage.getQuote() == null) {
return id;
}
String query;
if (targetMessage.getQuote().getAuthor().equals(Recipient.self().getId())) {
query = MessageTable.DATE_SENT + " = " + targetMessage.getQuote().getId() + " AND (" + MessageTable.TYPE + " & " + MessageTypes.BASE_TYPE_MASK + ") = " + MessageTypes.BASE_SENT_TYPE;
} else {
query = MessageTable.DATE_SENT + " = " + targetMessage.getQuote().getId() + " AND " + MessageTable.RECIPIENT_ID + " = '" + targetMessage.getQuote().getAuthor().serialize() + "'";
}
try (Reader reader = new Reader(queryTables(PROJECTION, query, null, "1", false))) {
MessageRecord record;
if ((record = reader.getNext()) != null) {
return getRootOfQuoteChain(new MessageId(record.getId()));
}
}
return id;
}
public List<MessageRecord> getAllMessagesThatQuote(@NonNull MessageId id) {
MessageRecord targetMessage;
try {
@ -351,7 +161,7 @@ public class MmsSmsTable extends DatabaseTable {
List<MessageRecord> records = new ArrayList<>();
try (Reader reader = new Reader(queryTables(PROJECTION, query, order, null, true))) {
try (MessageTable.Reader reader = new MessageTable.MmsReader(queryTables(PROJECTION, query, order, null, true))) {
MessageRecord record;
while ((record = reader.getNext()) != null) {
records.add(record);
@ -380,508 +190,6 @@ public class MmsSmsTable extends DatabaseTable {
return " AND " + MessageTable.PARENT_STORY_ID + " = " + parentStoryId;
}
public int getUnreadCount(long threadId) {
String selection = MessageTable.READ + " = 0 AND " + MessageTable.STORY_TYPE + " = 0 AND " + MessageTable.THREAD_ID + " = " + threadId + " AND " + MessageTable.PARENT_STORY_ID + " <= 0";
try (Cursor cursor = queryTables(PROJECTION, selection, null, null, false)) {
return cursor != null ? cursor.getCount() : 0;
}
}
public boolean checkMessageExists(@NonNull MessageRecord messageRecord) {
try (Cursor cursor = SignalDatabase.messages().getMessageCursor(messageRecord.getId())) {
return cursor != null && cursor.getCount() > 0;
}
}
public int getSecureConversationCount(long threadId) {
if (threadId == -1) {
return 0;
}
return SignalDatabase.messages().getSecureMessageCount(threadId);
}
public int getOutgoingSecureConversationCount(long threadId) {
if (threadId == -1L) {
return 0;
}
return SignalDatabase.messages().getOutgoingSecureMessageCount(threadId);
}
public int getConversationCount(long threadId) {
return SignalDatabase.messages().getMessageCountForThread(threadId);
}
public int getConversationCount(long threadId, long beforeTime) {
return SignalDatabase.messages().getMessageCountForThread(threadId, beforeTime);
}
public int getInsecureSentCount(long threadId) {
return SignalDatabase.messages().getInsecureMessagesSentForThread(threadId);
}
public int getInsecureMessageCountForInsights() {
return SignalDatabase.messages().getInsecureMessageCountForInsights();
}
public int getUnexportedInsecureMessagesCount() {
return getUnexportedInsecureMessagesCount(-1);
}
public int getUnexportedInsecureMessagesCount(long threadId) {
return SignalDatabase.messages().getUnexportedInsecureMessagesCount(threadId);
}
public int getIncomingMeaningfulMessageCountSince(long threadId, long afterTime) {
return SignalDatabase.messages().getIncomingMeaningfulMessageCountSince(threadId, afterTime);
}
public int getMessageCountBeforeDate(long date) {
String selection = MessageTable.DATE_RECEIVED + " < " + date;
try (Cursor cursor = queryTables(new String[] { "COUNT(*)" }, selection, null, null, false)) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getInt(0);
}
}
return 0;
}
public int getSecureMessageCountForInsights() {
return SignalDatabase.messages().getSecureMessageCountForInsights();
}
public boolean hasMeaningfulMessage(long threadId) {
if (threadId == -1) {
return false;
}
return SignalDatabase.messages().hasMeaningfulMessage(threadId);
}
public long getThreadId(MessageId messageId) {
return SignalDatabase.messages().getThreadIdForMessage(messageId.getId());
}
/**
* This is currently only used in an old migration and shouldn't be used by anyone else, just because it flat-out isn't correct.
*/
@Deprecated
public long getThreadForMessageId(long messageId) {
long id = SignalDatabase.messages().getThreadIdForMessage(messageId);
if (id == -1) return SignalDatabase.messages().getThreadIdForMessage(messageId);
else return id;
}
public Collection<SyncMessageId> incrementDeliveryReceiptCounts(@NonNull List<SyncMessageId> syncMessageIds, long timestamp) {
return incrementReceiptCounts(syncMessageIds, timestamp, MessageTable.ReceiptType.DELIVERY);
}
public boolean incrementDeliveryReceiptCount(SyncMessageId syncMessageId, long timestamp) {
return incrementReceiptCount(syncMessageId, timestamp, MessageTable.ReceiptType.DELIVERY);
}
/**
* @return A list of ID's that were not updated.
*/
public @NonNull Collection<SyncMessageId> incrementReadReceiptCounts(@NonNull List<SyncMessageId> syncMessageIds, long timestamp) {
return incrementReceiptCounts(syncMessageIds, timestamp, MessageTable.ReceiptType.READ);
}
public boolean incrementReadReceiptCount(SyncMessageId syncMessageId, long timestamp) {
return incrementReceiptCount(syncMessageId, timestamp, MessageTable.ReceiptType.READ);
}
/**
* @return A list of ID's that were not updated.
*/
public @NonNull Collection<SyncMessageId> incrementViewedReceiptCounts(@NonNull List<SyncMessageId> syncMessageIds, long timestamp) {
return incrementReceiptCounts(syncMessageIds, timestamp, MessageTable.ReceiptType.VIEWED);
}
public @NonNull Collection<SyncMessageId> incrementViewedNonStoryReceiptCounts(@NonNull List<SyncMessageId> syncMessageIds, long timestamp) {
return incrementReceiptCounts(syncMessageIds, timestamp, MessageTable.ReceiptType.VIEWED, MessageTable.MessageQualifier.NORMAL);
}
public boolean incrementViewedReceiptCount(SyncMessageId syncMessageId, long timestamp) {
return incrementReceiptCount(syncMessageId, timestamp, MessageTable.ReceiptType.VIEWED);
}
public @NonNull Collection<SyncMessageId> incrementViewedStoryReceiptCounts(@NonNull List<SyncMessageId> syncMessageIds, long timestamp) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
Set<MessageUpdate> messageUpdates = new HashSet<>();
Collection<SyncMessageId> unhandled = new HashSet<>();
db.beginTransaction();
try {
for (SyncMessageId id : syncMessageIds) {
Set<MessageUpdate> updates = incrementReceiptCountInternal(id, timestamp, MessageTable.ReceiptType.VIEWED, MessageTable.MessageQualifier.STORY);
if (updates.size() > 0) {
messageUpdates.addAll(updates);
} else {
unhandled.add(id);
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
for (MessageUpdate update : messageUpdates) {
ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(update.getMessageId());
ApplicationDependencies.getDatabaseObserver().notifyVerboseConversationListeners(Collections.singleton(update.getThreadId()));
}
if (messageUpdates.size() > 0) {
notifyConversationListListeners();
}
}
return unhandled;
}
/**
* Wraps a single receipt update in a transaction and triggers the proper updates.
*
* @return Whether or not some thread was updated.
*/
private boolean incrementReceiptCount(SyncMessageId syncMessageId, long timestamp, @NonNull MessageTable.ReceiptType receiptType) {
return incrementReceiptCount(syncMessageId, timestamp, receiptType, MessageTable.MessageQualifier.ALL);
}
private boolean incrementReceiptCount(SyncMessageId syncMessageId, long timestamp, @NonNull MessageTable.ReceiptType receiptType, @NonNull MessageTable.MessageQualifier messageQualifier) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
ThreadTable threadTable = SignalDatabase.threads();
Set<MessageUpdate> messageUpdates = new HashSet<>();
db.beginTransaction();
try {
messageUpdates = incrementReceiptCountInternal(syncMessageId, timestamp, receiptType, messageQualifier);
for (MessageUpdate messageUpdate : messageUpdates) {
threadTable.update(messageUpdate.getThreadId(), false);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
for (MessageUpdate threadUpdate : messageUpdates) {
ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(threadUpdate.getMessageId());
}
}
return messageUpdates.size() > 0;
}
/**
* Wraps multiple receipt updates in a transaction and triggers the proper updates.
*
* @return All of the messages that didn't result in updates.
*/
private @NonNull Collection<SyncMessageId> incrementReceiptCounts(@NonNull List<SyncMessageId> syncMessageIds, long timestamp, @NonNull MessageTable.ReceiptType receiptType) {
return incrementReceiptCounts(syncMessageIds, timestamp, receiptType, MessageTable.MessageQualifier.ALL);
}
private @NonNull Collection<SyncMessageId> incrementReceiptCounts(@NonNull List<SyncMessageId> syncMessageIds, long timestamp, @NonNull MessageTable.ReceiptType receiptType, @NonNull MessageTable.MessageQualifier messageQualifier) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
ThreadTable threadTable = SignalDatabase.threads();
Set<MessageUpdate> messageUpdates = new HashSet<>();
Collection<SyncMessageId> unhandled = new HashSet<>();
db.beginTransaction();
try {
for (SyncMessageId id : syncMessageIds) {
Set<MessageUpdate> updates = incrementReceiptCountInternal(id, timestamp, receiptType, messageQualifier);
if (updates.size() > 0) {
messageUpdates.addAll(updates);
} else {
unhandled.add(id);
}
}
for (MessageUpdate update : messageUpdates) {
threadTable.updateSilently(update.getThreadId(), false);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
for (MessageUpdate update : messageUpdates) {
ApplicationDependencies.getDatabaseObserver().notifyMessageUpdateObservers(update.getMessageId());
ApplicationDependencies.getDatabaseObserver().notifyVerboseConversationListeners(Collections.singleton(update.getThreadId()));
}
if (messageUpdates.size() > 0) {
notifyConversationListListeners();
}
}
return unhandled;
}
/**
* Doesn't do any transactions or updates, so we can re-use the method safely.
*/
private @NonNull Set<MessageUpdate> incrementReceiptCountInternal(SyncMessageId syncMessageId, long timestamp, MessageTable.ReceiptType receiptType, @NonNull MessageTable.MessageQualifier messageQualifier) {
return SignalDatabase.messages().incrementReceiptCount(syncMessageId, timestamp, receiptType, messageQualifier);
}
public void updateViewedStories(@NonNull Set<SyncMessageId> syncMessageIds) {
SignalDatabase.messages().updateViewedStories(syncMessageIds);
}
private @NonNull MessageExportState getMessageExportState(@NonNull MessageId messageId) throws NoSuchMessageException {
String table = MessageTable.TABLE_NAME;
String[] projection = SqlUtil.buildArgs(MessageTable.EXPORT_STATE);
String[] args = SqlUtil.buildArgs(messageId.getId());
try (Cursor cursor = getReadableDatabase().query(table, projection, ID_WHERE, args, null, null, null, null)) {
if (cursor.moveToFirst()) {
byte[] bytes = CursorUtil.requireBlob(cursor, MessageTable.EXPORT_STATE);
if (bytes == null) {
return MessageExportState.getDefaultInstance();
} else {
try {
return MessageExportState.parseFrom(bytes);
} catch (InvalidProtocolBufferException e) {
return MessageExportState.getDefaultInstance();
}
}
} else {
throw new NoSuchMessageException("The requested message does not exist.");
}
}
}
public void updateMessageExportState(@NonNull MessageId messageId, @NonNull Function<MessageExportState, MessageExportState> transform) throws NoSuchMessageException {
SQLiteDatabase database = getWritableDatabase();
database.beginTransaction();
try {
MessageExportState oldState = getMessageExportState(messageId);
MessageExportState newState = transform.apply(oldState);
setMessageExportState(messageId, newState);
database.setTransactionSuccessful();
} finally {
database.endTransaction();
}
}
public void markMessageExported(@NonNull MessageId messageId) {
String table = MessageTable.TABLE_NAME;
ContentValues contentValues = new ContentValues(1);
contentValues.put(MessageTable.EXPORTED, MessageExportStatus.EXPORTED.getCode());
getWritableDatabase().update(table, contentValues, ID_WHERE, SqlUtil.buildArgs(messageId.getId()));
}
public void markMessageExportFailed(@NonNull MessageId messageId) {
String table = MessageTable.TABLE_NAME;
ContentValues contentValues = new ContentValues(1);
contentValues.put(MessageTable.EXPORTED, MessageExportStatus.ERROR.getCode());
getWritableDatabase().update(table, contentValues, ID_WHERE, SqlUtil.buildArgs(messageId.getId()));
}
private void setMessageExportState(@NonNull MessageId messageId, @NonNull MessageExportState messageExportState) {
String table = MessageTable.TABLE_NAME;
ContentValues contentValues = new ContentValues(1);
contentValues.put(MessageTable.EXPORT_STATE, messageExportState.toByteArray());
getWritableDatabase().update(table, contentValues, ID_WHERE, SqlUtil.buildArgs(messageId.getId()));
}
/**
* @return Unhandled ids
*/
public Collection<SyncMessageId> setTimestampReadFromSyncMessage(@NonNull List<ReadMessage> readMessages, long proposedExpireStarted, @NonNull Map<Long, Long> threadToLatestRead) {
SQLiteDatabase db = getWritableDatabase();
List<Pair<Long, Long>> expiringMessages = new LinkedList<>();
Set<Long> updatedThreads = new HashSet<>();
Collection<SyncMessageId> unhandled = new LinkedList<>();
db.beginTransaction();
try {
for (ReadMessage readMessage : readMessages) {
RecipientId authorId = Recipient.externalPush(readMessage.getSender()).getId();
TimestampReadResult result = SignalDatabase.messages().setTimestampReadFromSyncMessage(new SyncMessageId(authorId, readMessage.getTimestamp()),
proposedExpireStarted,
threadToLatestRead);
expiringMessages.addAll(result.expiring);
updatedThreads.addAll(result.threads);
if (result.threads.isEmpty()) {
unhandled.add(new SyncMessageId(authorId, readMessage.getTimestamp()));
}
}
for (long threadId : updatedThreads) {
SignalDatabase.threads().updateReadState(threadId);
SignalDatabase.threads().setLastSeen(threadId);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
for (Pair<Long, Long> expiringMessage : expiringMessages) {
ApplicationDependencies.getExpiringMessageManager()
.scheduleDeletion(expiringMessage.first(), true, proposedExpireStarted, expiringMessage.second());
}
for (long threadId : updatedThreads) {
notifyConversationListeners(threadId);
}
return unhandled;
}
public int getQuotedMessagePosition(long threadId, long quoteId, @NonNull RecipientId recipientId) {
String order = MessageTable.DATE_RECEIVED + " DESC";
String selection = MessageTable.THREAD_ID + " = " + threadId + " AND " + MessageTable.STORY_TYPE + " = 0" + " AND " + MessageTable.PARENT_STORY_ID + " <= 0";
try (Cursor cursor = queryTables(new String[]{ MessageTable.DATE_SENT, MessageTable.RECIPIENT_ID, MessageTable.REMOTE_DELETED}, selection, order, null, false)) {
boolean isOwnNumber = Recipient.resolved(recipientId).isSelf();
while (cursor != null && cursor.moveToNext()) {
boolean quoteIdMatches = cursor.getLong(0) == quoteId;
boolean recipientIdMatches = recipientId.equals(RecipientId.from(CursorUtil.requireLong(cursor, MessageTable.RECIPIENT_ID)));
if (quoteIdMatches && (recipientIdMatches || isOwnNumber)) {
if (CursorUtil.requireBoolean(cursor, MessageTable.REMOTE_DELETED)) {
return -1;
} else {
return cursor.getPosition();
}
}
}
}
return -1;
}
public int getMessagePositionInConversation(long threadId, long receivedTimestamp, @NonNull RecipientId recipientId) {
String order = MessageTable.DATE_RECEIVED + " DESC";
String selection = MessageTable.THREAD_ID + " = " + threadId + " AND " + MessageTable.STORY_TYPE + " = 0" + " AND " + MessageTable.PARENT_STORY_ID + " <= 0";
try (Cursor cursor = queryTables(new String[]{ MessageTable.DATE_RECEIVED, MessageTable.RECIPIENT_ID, MessageTable.REMOTE_DELETED}, selection, order, null, false)) {
boolean isOwnNumber = Recipient.resolved(recipientId).isSelf();
while (cursor != null && cursor.moveToNext()) {
boolean timestampMatches = cursor.getLong(0) == receivedTimestamp;
boolean recipientIdMatches = recipientId.equals(RecipientId.from(cursor.getLong(1)));
if (timestampMatches && (recipientIdMatches || isOwnNumber)) {
if (CursorUtil.requireBoolean(cursor, MessageTable.REMOTE_DELETED)) {
return -1;
} else {
return cursor.getPosition();
}
}
}
}
return -1;
}
boolean hasReceivedAnyCallsSince(long threadId, long timestamp) {
return SignalDatabase.messages().hasReceivedAnyCallsSince(threadId, timestamp);
}
public int getMessagePositionInConversation(long threadId, long receivedTimestamp) {
return getMessagePositionInConversation(threadId, 0, receivedTimestamp);
}
/**
* Retrieves the position of the message with the provided timestamp in the query results you'd
* get from calling {@link #getConversation(long)}.
*
* Note: This could give back incorrect results in the situation where multiple messages have the
* same received timestamp. However, because this was designed to determine where to scroll to,
* you'll still wind up in about the right spot.
*
* @param groupStoryId Ignored if passed value is <= 0
*/
public int getMessagePositionInConversation(long threadId, long groupStoryId, long receivedTimestamp) {
final String order;
final String selection;
if (groupStoryId > 0) {
order = MessageTable.DATE_RECEIVED + " ASC";
selection = MessageTable.THREAD_ID + " = " + threadId + " AND " +
MessageTable.DATE_RECEIVED + " < " + receivedTimestamp + " AND " +
MessageTable.STORY_TYPE + " = 0 AND " + MessageTable.PARENT_STORY_ID + " = " + groupStoryId;
} else {
order = MessageTable.DATE_RECEIVED + " DESC";
selection = MessageTable.THREAD_ID + " = " + threadId + " AND " +
MessageTable.DATE_RECEIVED + " > " + receivedTimestamp + " AND " +
MessageTable.STORY_TYPE + " = 0 AND " + MessageTable.PARENT_STORY_ID + " <= 0";
}
try (Cursor cursor = queryTables(new String[]{ "COUNT(*)" }, selection, order, null, false)) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getInt(0);
}
}
return -1;
}
public long getTimestampForFirstMessageAfterDate(long date) {
String order = MessageTable.DATE_RECEIVED + " ASC";
String selection = MessageTable.DATE_RECEIVED + " > " + date;
try (Cursor cursor = queryTables(new String[] { MessageTable.DATE_RECEIVED }, selection, order, "1", false)) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getLong(0);
}
}
return 0;
}
public void setNotifiedTimestamp(long timestamp, @NonNull List<Long> messageIds) {
SignalDatabase.messages().setNotifiedTimestamp(timestamp, messageIds);
}
public int deleteMessagesInThreadBeforeDate(long threadId, long trimBeforeDate) {
Log.d(TAG, "deleteMessagesInThreadBeforeData(" + threadId + ", " + trimBeforeDate + ")");
int deletes = SignalDatabase.messages().deleteMessagesInThreadBeforeDate(threadId, trimBeforeDate);
deletes += SignalDatabase.messages().deleteMessagesInThreadBeforeDate(threadId, trimBeforeDate);
return deletes;
}
public void deleteAbandonedMessages() {
Log.d(TAG, "deleteAbandonedMessages()");
SignalDatabase.messages().deleteAbandonedMessages();
SignalDatabase.messages().deleteAbandonedMessages();
}
public @NonNull List<MessageTable.ReportSpamData> getReportSpamMessageServerData(long threadId, long timestamp, int limit) {
List<MessageTable.ReportSpamData> data = new ArrayList<>();
data.addAll(SignalDatabase.messages().getReportSpamMessageServerGuids(threadId, timestamp));
data.addAll(SignalDatabase.messages().getReportSpamMessageServerGuids(threadId, timestamp));
return data.stream()
.sorted((l, r) -> -Long.compare(l.getDateReceived(), r.getDateReceived()))
.limit(limit)
.collect(Collectors.toList());
}
private static @NonNull String buildQuery(String[] projection, String selection, String order, String limit, boolean includeAttachments) {
String attachmentJsonJoin;
if (includeAttachments) {
@ -942,75 +250,4 @@ public class MmsSmsTable extends DatabaseTable {
return databaseHelper.getSignalReadableDatabase().rawQuery(query, null);
}
public static Reader readerFor(@NonNull Cursor cursor) {
return new Reader(cursor);
}
public static class Reader implements Closeable {
private final Cursor cursor;
private MessageTable.MmsReader mmsReader;
public Reader(Cursor cursor) {
this.cursor = cursor;
}
private MessageTable.MmsReader getMmsReader() {
if (mmsReader == null) {
mmsReader = MessageTable.mmsReaderFor(cursor);
}
return mmsReader;
}
public MessageRecord getNext() {
if (cursor == null || !cursor.moveToNext())
return null;
return getCurrent();
}
public MessageRecord getCurrent() {
return getMmsReader().getCurrent();
}
@Override
public void close() {
cursor.close();
}
}
static final class TimestampReadResult {
final List<Pair<Long, Long>> expiring;
final List<Long> threads;
TimestampReadResult(@NonNull List<Pair<Long, Long>> expiring, @NonNull List<Long> threads) {
this.expiring = expiring;
this.threads = threads;
}
}
private static class QuoteDescriptor {
private final long timestamp;
private final RecipientId author;
private QuoteDescriptor(long timestamp, RecipientId author) {
this.author = author;
this.timestamp = timestamp;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final QuoteDescriptor that = (QuoteDescriptor) o;
return timestamp == that.timestamp && author.equals(that.author);
}
@Override
public int hashCode() {
return Objects.hash(author, timestamp);
}
}
}

View file

@ -296,7 +296,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
}
val deletes = writableDatabase.withinTransaction {
mmsSms.deleteAbandonedMessages()
messages.deleteAbandonedMessages()
attachments.trimAllAbandonedAttachments()
groupReceipts.deleteAbandonedRows()
mentions.deleteAbandonedMentions()
@ -318,7 +318,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
val deletes = writableDatabase.withinTransaction {
trimThreadInternal(threadId, length, trimBeforeDate)
mmsSms.deleteAbandonedMessages()
messages.deleteAbandonedMessages()
attachments.trimAllAbandonedAttachments()
groupReceipts.deleteAbandonedRows()
mentions.deleteAbandonedMentions()
@ -354,7 +354,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
if (finalTrimBeforeDate != NO_TRIM_BEFORE_DATE_SET) {
Log.i(TAG, "Trimming thread: $threadId before: $finalTrimBeforeDate")
val deletes = mmsSms.deleteMessagesInThreadBeforeDate(threadId, finalTrimBeforeDate)
val deletes = messages.deleteMessagesInThreadBeforeDate(threadId, finalTrimBeforeDate)
if (deletes > 0) {
Log.i(TAG, "Trimming deleted $deletes messages thread: $threadId")
setLastScrolled(threadId, 0)
@ -389,7 +389,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
}
fun hasReceivedAnyCallsSince(threadId: Long, timestamp: Long): Boolean {
return mmsSms.hasReceivedAnyCallsSince(threadId, timestamp)
return messages.hasReceivedAnyCallsSince(threadId, timestamp)
}
fun setEntireThreadRead(threadId: Long): List<MarkedMessageInfo> {
@ -441,7 +441,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
messages.setReactionsSeen(threadId, sinceTimestamp)
val unreadCount = mmsSms.getUnreadCount(threadId)
val unreadCount = messages.getUnreadCount(threadId)
val unreadMentionsCount = messages.getUnreadMentionCount(threadId)
val contentValues = contentValuesOf(
@ -1180,7 +1180,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
fun updateReadState(threadId: Long) {
val previous = getThreadRecord(threadId)
val unreadCount = mmsSms.getUnreadCount(threadId)
val unreadCount = messages.getUnreadCount(threadId)
val unreadMentionsCount = messages.getUnreadMentionCount(threadId)
writableDatabase
@ -1268,7 +1268,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
if (forcedUnread) {
values.put(READ, ReadStatus.FORCED_UNREAD.serialize())
} else if (threadId != null) {
val unreadCount = mmsSms.getUnreadCount(threadId)
val unreadCount = messages.getUnreadCount(threadId)
val unreadMentionsCount = messages.getUnreadMentionCount(threadId)
values.put(READ, if (unreadCount == 0) ReadStatus.READ.serialize() else ReadStatus.UNREAD.serialize())
@ -1315,7 +1315,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
}
private fun update(threadId: Long, unarchive: Boolean, allowDeletion: Boolean, notifyListeners: Boolean): Boolean {
val meaningfulMessages = mmsSms.hasMeaningfulMessage(threadId)
val meaningfulMessages = messages.hasMeaningfulMessage(threadId)
val isPinned = getPinnedThreadIds().contains(threadId)
val shouldDelete = allowDeletion && !isPinned && !messages.containsStories(threadId)
@ -1331,7 +1331,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
}
val record: MessageRecord = try {
mmsSms.getConversationSnippet(threadId)
messages.getConversationSnippet(threadId)
} catch (e: NoSuchMessageException) {
Log.w(TAG, "Failed to get a conversation snippet for thread $threadId")
@ -1400,7 +1400,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
}
val type: Long = try {
mmsSms.getConversationSnippetType(threadId)
messages.getConversationSnippetType(threadId)
} catch (e: NoSuchMessageException) {
Log.w(TAG, "Unable to find snippet message for thread $threadId")
return
@ -1552,7 +1552,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
Log.w(TAG, "Falling back to unknown message request state for GV2 message")
return Extra.forMessageRequest(individualRecipientId)
} else {
val recipientId = mmsSms.getGroupAddedBy(record.threadId)
val recipientId = messages.getGroupAddedBy(record.threadId)
if (recipientId != null) {
return Extra.forGroupMessageRequest(recipientId, individualRecipientId)
}

View file

@ -103,66 +103,66 @@ class SignalSmsExportService : SmsExportService() {
}
override fun onMessageExportStarted(exportableMessage: ExportableMessage) {
SignalDatabase.mmsSms.updateMessageExportState(exportableMessage.getMessageId()) {
SignalDatabase.messages.updateMessageExportState(exportableMessage.getMessageId()) {
it.toBuilder().setProgress(MessageExportState.Progress.STARTED).build()
}
}
override fun onMessageExportSucceeded(exportableMessage: ExportableMessage) {
SignalDatabase.mmsSms.updateMessageExportState(exportableMessage.getMessageId()) {
SignalDatabase.messages.updateMessageExportState(exportableMessage.getMessageId()) {
it.toBuilder().setProgress(MessageExportState.Progress.COMPLETED).build()
}
SignalDatabase.mmsSms.markMessageExported(exportableMessage.getMessageId())
SignalDatabase.messages.markMessageExported(exportableMessage.getMessageId())
}
override fun onMessageExportFailed(exportableMessage: ExportableMessage) {
SignalDatabase.mmsSms.updateMessageExportState(exportableMessage.getMessageId()) {
SignalDatabase.messages.updateMessageExportState(exportableMessage.getMessageId()) {
it.toBuilder().setProgress(MessageExportState.Progress.INIT).build()
}
SignalDatabase.mmsSms.markMessageExportFailed(exportableMessage.getMessageId())
SignalDatabase.messages.markMessageExportFailed(exportableMessage.getMessageId())
}
override fun onMessageIdCreated(exportableMessage: ExportableMessage, messageId: Long) {
SignalDatabase.mmsSms.updateMessageExportState(exportableMessage.getMessageId()) {
SignalDatabase.messages.updateMessageExportState(exportableMessage.getMessageId()) {
it.toBuilder().setMessageId(messageId).build()
}
}
override fun onAttachmentPartExportStarted(exportableMessage: ExportableMessage, part: ExportableMessage.Mms.Part) {
SignalDatabase.mmsSms.updateMessageExportState(exportableMessage.getMessageId()) {
SignalDatabase.messages.updateMessageExportState(exportableMessage.getMessageId()) {
it.toBuilder().addStartedAttachments(part.contentId).build()
}
}
override fun onAttachmentPartExportSucceeded(exportableMessage: ExportableMessage, part: ExportableMessage.Mms.Part) {
SignalDatabase.mmsSms.updateMessageExportState(exportableMessage.getMessageId()) {
SignalDatabase.messages.updateMessageExportState(exportableMessage.getMessageId()) {
it.toBuilder().addCompletedAttachments(part.contentId).build()
}
}
override fun onAttachmentPartExportFailed(exportableMessage: ExportableMessage, part: ExportableMessage.Mms.Part) {
SignalDatabase.mmsSms.updateMessageExportState(exportableMessage.getMessageId()) {
SignalDatabase.messages.updateMessageExportState(exportableMessage.getMessageId()) {
val startedAttachments = it.startedAttachmentsList - part.contentId
it.toBuilder().clearStartedAttachments().addAllStartedAttachments(startedAttachments).build()
}
}
override fun onRecipientExportStarted(exportableMessage: ExportableMessage, recipient: String) {
SignalDatabase.mmsSms.updateMessageExportState(exportableMessage.getMessageId()) {
SignalDatabase.messages.updateMessageExportState(exportableMessage.getMessageId()) {
it.toBuilder().addStartedRecipients(recipient).build()
}
}
override fun onRecipientExportSucceeded(exportableMessage: ExportableMessage, recipient: String) {
SignalDatabase.mmsSms.updateMessageExportState(exportableMessage.getMessageId()) {
SignalDatabase.messages.updateMessageExportState(exportableMessage.getMessageId()) {
it.toBuilder().addCompletedRecipients(recipient).build()
}
}
override fun onRecipientExportFailed(exportableMessage: ExportableMessage, recipient: String) {
SignalDatabase.mmsSms.updateMessageExportState(exportableMessage.getMessageId()) {
SignalDatabase.messages.updateMessageExportState(exportableMessage.getMessageId()) {
val startedAttachments = it.startedRecipientsList - recipient
it.toBuilder().clearStartedRecipients().addAllStartedRecipients(startedAttachments).build()
}

View file

@ -10,6 +10,7 @@ import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
import org.thoughtcrime.securesms.database.MessageTable;
import org.thoughtcrime.securesms.database.MmsSmsTable;
import org.thoughtcrime.securesms.database.RecipientTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
@ -34,9 +35,9 @@ public class InsightsRepository implements InsightsDashboardViewModel.Repository
@Override
public void getInsightsData(@NonNull Consumer<InsightsData> insightsDataConsumer) {
SimpleTask.run(() -> {
MmsSmsTable mmsSmsDatabase = SignalDatabase.mmsSms();
int insecure = mmsSmsDatabase.getInsecureMessageCountForInsights();
int secure = mmsSmsDatabase.getSecureMessageCountForInsights();
MessageTable messageTable = SignalDatabase.messages();
int insecure = messageTable.getInsecureMessageCountForInsights();
int secure = messageTable.getSecureMessageCountForInsights();
if (insecure + secure == 0) {
return new InsightsData(false, 0);

View file

@ -52,7 +52,7 @@ public final class InviteReminderModel {
Long threadId = threadTable.getThreadIdFor(recipient.getId());
if (threadId != null) {
int conversationCount = SignalDatabase.mmsSms().getInsecureSentCount(threadId);
int conversationCount = SignalDatabase.messages().getInsecureMessageSentCount(threadId);
if (conversationCount >= SECOND_INVITE_REMINDER_MESSAGE_THRESHOLD && !resolved.hasSeenSecondInviteReminder()) {
return new SecondInviteReminderInfo(context, resolved, repository, repository.getPercentOfInsecureMessages(conversationCount));

View file

@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.invites;
import android.content.Context;
import org.thoughtcrime.securesms.database.MessageTable;
import org.thoughtcrime.securesms.database.MmsSmsTable;
import org.thoughtcrime.securesms.database.RecipientTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
@ -29,9 +30,9 @@ public final class InviteReminderRepository implements InviteReminderModel.Repos
@Override
public int getPercentOfInsecureMessages(int insecureCount) {
MmsSmsTable mmsSmsDatabase = SignalDatabase.mmsSms();
int insecure = mmsSmsDatabase.getInsecureMessageCountForInsights();
int secure = mmsSmsDatabase.getSecureMessageCountForInsights();
MessageTable messageTable = SignalDatabase.messages();
int insecure = messageTable.getInsecureMessageCountForInsights();
int secure = messageTable.getSecureMessageCountForInsights();
if (insecure + secure == 0) return 0;
return Math.round(100f * (insecureCount / (float) (insecure + secure)));

View file

@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.jobmanager.migrations;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.database.MessageTable;
import org.thoughtcrime.securesms.database.MmsSmsTable;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.JobMigration;
@ -11,22 +12,22 @@ import java.util.TreeSet;
public class SendReadReceiptsJobMigration extends JobMigration {
private final MmsSmsTable mmsSmsDatabase;
private final MessageTable messageTable;
public SendReadReceiptsJobMigration(@NonNull MmsSmsTable mmsSmsDatabase) {
public SendReadReceiptsJobMigration(@NonNull MessageTable messageTable) {
super(5);
this.mmsSmsDatabase = mmsSmsDatabase;
this.messageTable = messageTable;
}
@Override
protected @NonNull JobData migrate(@NonNull JobData jobData) {
if ("SendReadReceiptJob".equals(jobData.getFactoryKey())) {
return migrateSendReadReceiptJob(mmsSmsDatabase, jobData);
return migrateSendReadReceiptJob(messageTable, jobData);
}
return jobData;
}
private static @NonNull JobData migrateSendReadReceiptJob(@NonNull MmsSmsTable mmsSmsDatabase, @NonNull JobData jobData) {
private static @NonNull JobData migrateSendReadReceiptJob(@NonNull MessageTable messageTable, @NonNull JobData jobData) {
Data data = jobData.getData();
if (!data.hasLong("thread")) {
@ -34,7 +35,7 @@ public class SendReadReceiptsJobMigration extends JobMigration {
SortedSet<Long> threadIds = new TreeSet<>();
for (long id : messageIds) {
long threadForMessageId = mmsSmsDatabase.getThreadForMessageId(id);
long threadForMessageId = messageTable.getThreadIdForMessage(id);
if (id != -1) {
threadIds.add(threadForMessageId);
}

View file

@ -156,9 +156,9 @@ public class IndividualSendJob extends PushSendJob {
if (recipient.isSelf()) {
SyncMessageId id = new SyncMessageId(recipient.getId(), message.getSentTimeMillis());
SignalDatabase.mmsSms().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
SignalDatabase.mmsSms().incrementReadReceiptCount(id, System.currentTimeMillis());
SignalDatabase.mmsSms().incrementViewedReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementReadReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementViewedReceiptCount(id, System.currentTimeMillis());
}
if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) {

View file

@ -287,7 +287,7 @@ public final class JobManagerFactories {
return Arrays.asList(new RecipientIdJobMigration(application),
new RecipientIdFollowUpJobMigration(),
new RecipientIdFollowUpJobMigration2(),
new SendReadReceiptsJobMigration(SignalDatabase.mmsSms()),
new SendReadReceiptsJobMigration(SignalDatabase.messages()),
new PushProcessMessageQueueJobMigration(application),
new RetrieveProfileJobMigration(),
new PushDecryptMessageJobEnvelopeMigration(application),

View file

@ -69,7 +69,7 @@ public class ReportSpamJob extends BaseJob {
}
int count = 0;
List<ReportSpamData> reportSpamData = SignalDatabase.mmsSms().getReportSpamMessageServerData(threadId, timestamp, MAX_MESSAGE_COUNT);
List<ReportSpamData> reportSpamData = SignalDatabase.messages().getReportSpamMessageServerData(threadId, timestamp, MAX_MESSAGE_COUNT);
SignalServiceAccountManager signalServiceAccountManager = ApplicationDependencies.getSignalServiceAccountManager();
for (ReportSpamData data : reportSpamData) {
Optional<ServiceId> serviceId = Recipient.resolved(data.getRecipientId()).getServiceId();

View file

@ -95,7 +95,7 @@ class MediaPreviewRepository {
stopwatch.split("get message record")
val threadId: Long = messageRecord.threadId
val messagePosition: Int = SignalDatabase.mmsSms.getMessagePositionInConversation(threadId, messageRecord.dateReceived)
val messagePosition: Int = SignalDatabase.messages.getMessagePositionInConversation(threadId, messageRecord.dateReceived)
stopwatch.split("get message position")
val recipientId: RecipientId = SignalDatabase.threads.getRecipientForThreadId(threadId)?.id ?: throw IllegalStateException("Could not find recipient for thread ID $threadId")

View file

@ -66,12 +66,10 @@ public class IncomingMessageProcessor {
public class Processor implements Closeable {
private final Context context;
private final MmsSmsTable mmsSmsDatabase;
private final JobManager jobManager;
private Processor(@NonNull Context context) {
this.context = context;
this.mmsSmsDatabase = SignalDatabase.mmsSms();
this.jobManager = ApplicationDependencies.getJobManager();
}
@ -160,7 +158,7 @@ public class IncomingMessageProcessor {
Recipient sender = Recipient.externalPush(envelope.getSourceAddress());
Log.i(TAG, "Received server receipt. Sender: " + sender.getId() + ", Device: " + envelope.getSourceDevice() + ", Timestamp: " + envelope.getTimestamp());
mmsSmsDatabase.incrementDeliveryReceiptCount(new SyncMessageId(sender.getId(), envelope.getTimestamp()), System.currentTimeMillis());
SignalDatabase.messages().incrementDeliveryReceiptCount(new SyncMessageId(sender.getId(), envelope.getTimestamp()), System.currentTimeMillis());
SignalDatabase.messageLog().deleteEntryForRecipient(envelope.getTimestamp(), sender.getId(), envelope.getSourceDevice());
}

View file

@ -1410,7 +1410,7 @@ public final class MessageContentProcessor {
Map<Long, Long> threadToLatestRead = new HashMap<>();
Collection<SyncMessageId> unhandled = SignalDatabase.mmsSms().setTimestampReadFromSyncMessage(readMessages, envelopeTimestamp, threadToLatestRead);
Collection<SyncMessageId> unhandled = SignalDatabase.messages().setTimestampReadFromSyncMessage(readMessages, envelopeTimestamp, threadToLatestRead);
List<MessageTable.MarkedMessageInfo> markedMessages = SignalDatabase.threads().setReadSince(threadToLatestRead, false);
@ -2111,8 +2111,8 @@ public final class MessageContentProcessor {
if (recipient.isSelf()) {
SyncMessageId id = new SyncMessageId(recipient.getId(), message.getTimestamp());
SignalDatabase.mmsSms().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
SignalDatabase.mmsSms().incrementReadReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementReadReceiptCount(id, System.currentTimeMillis());
}
database.setTransactionSuccessful();
@ -2224,8 +2224,8 @@ public final class MessageContentProcessor {
if (recipient.isSelf()) {
SyncMessageId id = new SyncMessageId(recipient.getId(), message.getTimestamp());
SignalDatabase.mmsSms().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
SignalDatabase.mmsSms().incrementReadReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementReadReceiptCount(id, System.currentTimeMillis());
}
database.setTransactionSuccessful();
@ -2333,8 +2333,8 @@ public final class MessageContentProcessor {
if (recipients.isSelf()) {
SyncMessageId id = new SyncMessageId(recipients.getId(), message.getTimestamp());
SignalDatabase.mmsSms().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
SignalDatabase.mmsSms().incrementReadReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementReadReceiptCount(id, System.currentTimeMillis());
}
database.setTransactionSuccessful();
@ -2502,8 +2502,8 @@ public final class MessageContentProcessor {
if (recipient.isSelf()) {
SyncMessageId id = new SyncMessageId(recipient.getId(), message.getTimestamp());
SignalDatabase.mmsSms().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
SignalDatabase.mmsSms().incrementReadReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
SignalDatabase.messages().incrementReadReceiptCount(id, System.currentTimeMillis());
}
return threadId;
@ -2659,17 +2659,17 @@ public final class MessageContentProcessor {
final Collection<SyncMessageId> unhandled;
if (readReceipts && storyViewedReceipts) {
unhandled = SignalDatabase.mmsSms().incrementViewedReceiptCounts(ids, content.getTimestamp());
unhandled = SignalDatabase.messages().incrementViewedReceiptCounts(ids, content.getTimestamp());
} else if (readReceipts) {
unhandled = SignalDatabase.mmsSms().incrementViewedNonStoryReceiptCounts(ids, content.getTimestamp());
unhandled = SignalDatabase.messages().incrementViewedNonStoryReceiptCounts(ids, content.getTimestamp());
} else {
unhandled = SignalDatabase.mmsSms().incrementViewedStoryReceiptCounts(ids, content.getTimestamp());
unhandled = SignalDatabase.messages().incrementViewedStoryReceiptCounts(ids, content.getTimestamp());
}
Set<SyncMessageId> handled = new HashSet<>(ids);
handled.removeAll(unhandled);
SignalDatabase.mmsSms().updateViewedStories(handled);
SignalDatabase.messages().updateViewedStories(handled);
if (unhandled.size() > 0) {
RecipientId selfId = Recipient.self().getId();
@ -2698,7 +2698,7 @@ public final class MessageContentProcessor {
.map(t -> new SyncMessageId(senderRecipient.getId(), t))
.toList();
Collection<SyncMessageId> unhandled = SignalDatabase.mmsSms().incrementDeliveryReceiptCounts(ids, System.currentTimeMillis());
Collection<SyncMessageId> unhandled = SignalDatabase.messages().incrementDeliveryReceiptCounts(ids, System.currentTimeMillis());
for (SyncMessageId id : unhandled) {
warn(String.valueOf(content.getTimestamp()), "[handleDeliveryReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + id.getRecipientId());
@ -2729,7 +2729,7 @@ public final class MessageContentProcessor {
.map(t -> new SyncMessageId(senderRecipient.getId(), t))
.toList();
Collection<SyncMessageId> unhandled = SignalDatabase.mmsSms().incrementReadReceiptCounts(ids, content.getTimestamp());
Collection<SyncMessageId> unhandled = SignalDatabase.messages().incrementReadReceiptCounts(ids, content.getTimestamp());
if (unhandled.size() > 0) {
RecipientId selfId = Recipient.self().getId();

View file

@ -212,7 +212,7 @@ class DefaultMessageNotifier(context: Application) : MessageNotifier {
updateBadge(context, state.messageCount)
val messageIds: List<Long> = state.notificationItems.map { it.id }
SignalDatabase.mmsSms.setNotifiedTimestamp(System.currentTimeMillis(), messageIds)
SignalDatabase.messages.setNotifiedTimestamp(System.currentTimeMillis(), messageIds)
Log.i(TAG, "threads: ${state.threadCount} messages: ${state.messageCount}")

View file

@ -215,7 +215,7 @@ class MessageNotification(threadRecipient: Recipient, record: MessageRecord) : N
override fun getStartingPosition(context: Context): Int {
return if (thread.groupStoryId != null) {
SignalDatabase.mmsSms.getMessagePositionInConversation(thread.threadId, thread.groupStoryId, record.dateReceived)
SignalDatabase.messages.getMessagePositionInConversation(thread.threadId, thread.groupStoryId, record.dateReceived)
} else {
-1
}
@ -328,7 +328,7 @@ class ReactionNotification(threadRecipient: Recipient, record: MessageRecord, va
}
override fun getStartingPosition(context: Context): Int {
return SignalDatabase.mmsSms.getMessagePositionInConversation(thread.threadId, thread.groupStoryId ?: 0L, record.dateReceived)
return SignalDatabase.messages.getMessagePositionInConversation(thread.threadId, thread.groupStoryId ?: 0L, record.dateReceived)
}
override fun getLargeIconUri(): Uri? = null

View file

@ -4,7 +4,6 @@ import androidx.annotation.WorkerThread
import org.signal.core.util.CursorUtil
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.database.MessageTable
import org.thoughtcrime.securesms.database.MmsSmsTable
import org.thoughtcrime.securesms.database.NoSuchMessageException
import org.thoughtcrime.securesms.database.RecipientTable
import org.thoughtcrime.securesms.database.SignalDatabase
@ -31,7 +30,7 @@ object NotificationStateProvider {
return NotificationState.EMPTY
}
MmsSmsTable.readerFor(unreadMessages).use { reader ->
MessageTable.mmsReaderFor(unreadMessages).use { reader ->
var record: MessageRecord? = reader.next
while (record != null) {
val threadRecipient: Recipient? = SignalDatabase.threads.getRecipientForThreadId(record.threadId)

View file

@ -257,7 +257,7 @@ public class RecipientUtil {
@WorkerThread
public static boolean isPreMessageRequestThread(@Nullable Long threadId) {
long beforeTime = SignalStore.misc().getMessageRequestEnableTime();
return threadId != null && SignalDatabase.mmsSms().getConversationCount(threadId, beforeTime) > 0;
return threadId != null && SignalDatabase.messages().getMessageCountForThread(threadId, beforeTime) > 0;
}
@WorkerThread
@ -272,7 +272,7 @@ public class RecipientUtil {
return;
}
boolean firstMessage = SignalDatabase.mmsSms().getOutgoingSecureConversationCount(threadId) == 0;
boolean firstMessage = SignalDatabase.messages().getOutgoingSecureMessageCount(threadId) == 0;
if (firstMessage) {
SignalDatabase.recipients().setProfileSharing(recipient.getId(), true);
@ -317,7 +317,7 @@ public class RecipientUtil {
return false;
}
if (threadId == -1 || !SignalDatabase.mmsSms().hasMeaningfulMessage(threadId)) {
if (threadId == -1 || !SignalDatabase.messages().hasMeaningfulMessage(threadId)) {
SignalDatabase.recipients().setExpireMessages(recipient.getId(), defaultTimer);
OutgoingMessage outgoingMessage = OutgoingMessage.expirationUpdateMessage(recipient, System.currentTimeMillis(), defaultTimer * 1000L);
MessageSender.send(context, outgoingMessage, SignalDatabase.threads().getOrCreateThreadIdFor(recipient), false, null, null);
@ -349,7 +349,7 @@ public class RecipientUtil {
@WorkerThread
public static boolean hasSentMessageInThread(@Nullable Long threadId) {
return threadId != null && SignalDatabase.mmsSms().getOutgoingSecureConversationCount(threadId) != 0;
return threadId != null && SignalDatabase.messages().getOutgoingSecureMessageCount(threadId) != 0;
}
public static boolean isSmsOnly(long threadId, @NonNull Recipient threadRecipient) {
@ -363,7 +363,7 @@ public class RecipientUtil {
return true;
}
return SignalDatabase.mmsSms().getSecureConversationCount(threadId) == 0 &&
return SignalDatabase.messages().getSecureMessageCount(threadId) == 0 &&
!SignalDatabase.threads().hasReceivedAnyCallsSince(threadId, 0);
}

View file

@ -9,7 +9,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.MmsSmsTable;
import org.thoughtcrime.securesms.database.MessageTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.ThreadTable;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
@ -20,14 +20,14 @@ public class TrimThreadsByDateManager extends TimedEventManager<TrimThreadsByDat
private static final String TAG = Log.tag(TrimThreadsByDateManager.class);
private final ThreadTable threadTable;
private final MmsSmsTable mmsSmsDatabase;
private final ThreadTable threadTable;
private final MessageTable messageTable;
public TrimThreadsByDateManager(@NonNull Application application) {
super(application, "TrimThreadsByDateManager");
threadTable = SignalDatabase.threads();
mmsSmsDatabase = SignalDatabase.mmsSms();
threadTable = SignalDatabase.threads();
messageTable = SignalDatabase.messages();
scheduleIfNecessary();
}
@ -41,12 +41,12 @@ public class TrimThreadsByDateManager extends TimedEventManager<TrimThreadsByDat
long trimBeforeDate = System.currentTimeMillis() - keepMessagesDuration.getDuration();
if (mmsSmsDatabase.getMessageCountBeforeDate(trimBeforeDate) > 0) {
if (messageTable.getMessageCountBeforeDate(trimBeforeDate) > 0) {
Log.i(TAG, "Messages exist before date, trim immediately");
return new TrimEvent(0);
}
long timestamp = mmsSmsDatabase.getTimestampForFirstMessageAfterDate(trimBeforeDate);
long timestamp = messageTable.getTimestampForFirstMessageAfterDate(trimBeforeDate);
if (timestamp == 0) {
return null;

View file

@ -598,10 +598,9 @@ public class MessageSender {
private static void sendLocalMediaSelf(Context context, long messageId) {
try {
ExpiringMessageManager expirationManager = ApplicationDependencies.getExpiringMessageManager();
MessageTable mmsDatabase = SignalDatabase.messages();
MmsSmsTable mmsSmsDatabase = SignalDatabase.mmsSms();
OutgoingMessage message = mmsDatabase.getOutgoingMessage(messageId);
SyncMessageId syncId = new SyncMessageId(Recipient.self().getId(), message.getSentTimeMillis());
MessageTable mmsDatabase = SignalDatabase.messages();
OutgoingMessage message = mmsDatabase.getOutgoingMessage(messageId);
SyncMessageId syncId = new SyncMessageId(Recipient.self().getId(), message.getSentTimeMillis());
List<Attachment> attachments = new LinkedList<>();
@ -633,9 +632,9 @@ public class MessageSender {
mmsDatabase.markAsSent(messageId, true);
mmsDatabase.markUnidentified(messageId, true);
mmsSmsDatabase.incrementDeliveryReceiptCount(syncId, System.currentTimeMillis());
mmsSmsDatabase.incrementReadReceiptCount(syncId, System.currentTimeMillis());
mmsSmsDatabase.incrementViewedReceiptCount(syncId, System.currentTimeMillis());
mmsDatabase.incrementDeliveryReceiptCount(syncId, System.currentTimeMillis());
mmsDatabase.incrementReadReceiptCount(syncId, System.currentTimeMillis());
mmsDatabase.incrementViewedReceiptCount(syncId, System.currentTimeMillis());
if (message.getExpiresIn() > 0 && !message.isExpirationUpdate()) {
mmsDatabase.markExpireStarted(messageId);

View file

@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.testing.TestDatabaseUtil
class MmsSmsDatabaseTest {
private lateinit var mmsSmsTable: MmsSmsTable
private lateinit var messageTable: MessageTable
private lateinit var db: SQLiteDatabase
@Before
@ -28,6 +29,7 @@ class MmsSmsDatabaseTest {
db = sqlCipher.writableDatabase
mmsSmsTable = MmsSmsTable(ApplicationProvider.getApplicationContext(), sqlCipher)
messageTable = MessageTable(ApplicationProvider.getApplicationContext(), sqlCipher)
}
@After
@ -38,7 +40,7 @@ class MmsSmsDatabaseTest {
@Test
fun `getConversationSnippet when single normal SMS, return SMS message id and transport as false`() {
TestSms.insert(db)
mmsSmsTable.getConversationSnippetCursor(1).use { cursor ->
messageTable.getConversationSnippetCursor(1).use { cursor ->
cursor.moveToFirst()
assertEquals(1, CursorUtil.requireLong(cursor, MessageTable.ID))
}
@ -47,7 +49,7 @@ class MmsSmsDatabaseTest {
@Test
fun `getConversationSnippet when single normal MMS, return MMS message id and transport as true`() {
TestMms.insert(db)
mmsSmsTable.getConversationSnippetCursor(1).use { cursor ->
messageTable.getConversationSnippetCursor(1).use { cursor ->
cursor.moveToFirst()
assertEquals(1, CursorUtil.requireLong(cursor, MessageTable.ID))
}
@ -58,13 +60,13 @@ class MmsSmsDatabaseTest {
val timestamp = System.currentTimeMillis()
TestMms.insert(db, receivedTimestampMillis = timestamp + 2)
mmsSmsTable.getConversationSnippetCursor(1).use { cursor ->
messageTable.getConversationSnippetCursor(1).use { cursor ->
cursor.moveToFirst()
assertEquals(1, CursorUtil.requireLong(cursor, MessageTable.ID))
}
TestSms.insert(db, receivedTimestampMillis = timestamp + 3, type = MessageTypes.BASE_SENDING_TYPE or MessageTypes.SECURE_MESSAGE_BIT or MessageTypes.PUSH_MESSAGE_BIT or MessageTypes.GROUP_V2_LEAVE_BITS)
mmsSmsTable.getConversationSnippetCursor(1).use { cursor ->
messageTable.getConversationSnippetCursor(1).use { cursor ->
cursor.moveToFirst()
assertEquals(1, CursorUtil.requireLong(cursor, MessageTable.ID))
}

View file

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.jobmanager.migrations;
import org.junit.Test;
import org.thoughtcrime.securesms.database.MessageTable;
import org.thoughtcrime.securesms.database.MmsSmsTable;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.JobMigration;
@ -17,7 +18,7 @@ import static org.mockito.Mockito.when;
public class SendReadReceiptsJobMigrationTest {
private final MmsSmsTable mockDatabase = mock(MmsSmsTable.class);
private final MessageTable mockDatabase = mock(MessageTable.class);
private final SendReadReceiptsJobMigration testSubject = new SendReadReceiptsJobMigration(mockDatabase);
@Test
@ -30,7 +31,7 @@ public class SendReadReceiptsJobMigrationTest {
.putString("recipient", RecipientId.from(2).serialize())
.putLongArray("message_ids", new long[]{1, 2, 3, 4, 5})
.putLong("timestamp", 292837649).build());
when(mockDatabase.getThreadForMessageId(anyLong())).thenReturn(1234L);
when(mockDatabase.getThreadIdForMessage(anyLong())).thenReturn(1234L);
// WHEN
JobMigration.JobData result = testSubject.migrate(jobData);
@ -52,7 +53,7 @@ public class SendReadReceiptsJobMigrationTest {
.putString("recipient", RecipientId.from(2).serialize())
.putLongArray("message_ids", new long[]{})
.putLong("timestamp", 292837649).build());
when(mockDatabase.getThreadForMessageId(anyLong())).thenReturn(-1L);
when(mockDatabase.getThreadIdForMessage(anyLong())).thenReturn(-1L);
// WHEN
JobMigration.JobData result = testSubject.migrate(jobData);

View file

@ -10,11 +10,10 @@ import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.thoughtcrime.securesms.database.MmsSmsTable;
import org.thoughtcrime.securesms.database.MessageTable;
import org.thoughtcrime.securesms.database.RecipientTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.ThreadTable;
import org.thoughtcrime.securesms.util.FeatureFlags;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@ -29,22 +28,19 @@ public class RecipientUtilTest {
@Rule
public MockitoRule rule = MockitoJUnit.rule();
private Context context = mock(Context.class);
private Context context = mock(Context.class);
private Recipient recipient = mock(Recipient.class);
private ThreadTable mockThreadTable = mock(ThreadTable.class);
private MmsSmsTable mockMmsSmsDatabase = mock(MmsSmsTable.class);
private MessageTable mockMessageTable = mock(MessageTable.class);
private RecipientTable mockRecipientTable = mock(RecipientTable.class);
@Mock
private MockedStatic<SignalDatabase> signalDatabaseMockedStatic;
@Mock
private MockedStatic<FeatureFlags> featureFlagsMockedStatic;
@Before
public void setUp() {
signalDatabaseMockedStatic.when(SignalDatabase::threads).thenReturn(mockThreadTable);
signalDatabaseMockedStatic.when(SignalDatabase::mmsSms).thenReturn(mockMmsSmsDatabase);
signalDatabaseMockedStatic.when(SignalDatabase::messages).thenReturn(mockMessageTable);
signalDatabaseMockedStatic.when(SignalDatabase::recipients).thenReturn(mockRecipientTable);
when(recipient.getId()).thenReturn(RecipientId.from(5));
@ -73,7 +69,7 @@ public class RecipientUtilTest {
public void givenIHaveSentASecureMessageInThisThread_whenIsThreadMessageRequestAccepted_thenIExpectTrue() {
// GIVEN
when(mockThreadTable.getRecipientForThreadId(anyLong())).thenReturn(recipient);
when(mockMmsSmsDatabase.getOutgoingSecureConversationCount(1L)).thenReturn(5);
when(mockMessageTable.getOutgoingSecureMessageCount(1L)).thenReturn(5);
// WHEN
boolean result = RecipientUtil.isMessageRequestAccepted(context, 1L);
@ -87,7 +83,7 @@ public class RecipientUtilTest {
// GIVEN
when(recipient.isProfileSharing()).thenReturn(true);
when(mockThreadTable.getRecipientForThreadId(anyLong())).thenReturn(recipient);
when(mockMmsSmsDatabase.getOutgoingSecureConversationCount(1L)).thenReturn(0);
when(mockMessageTable.getOutgoingSecureMessageCount(1L)).thenReturn(0);
// WHEN
boolean result = RecipientUtil.isMessageRequestAccepted(context, 1L);
@ -101,7 +97,7 @@ public class RecipientUtilTest {
// GIVEN
when(recipient.isSystemContact()).thenReturn(true);
when(mockThreadTable.getRecipientForThreadId(anyLong())).thenReturn(recipient);
when(mockMmsSmsDatabase.getOutgoingSecureConversationCount(1L)).thenReturn(0);
when(mockMessageTable.getOutgoingSecureMessageCount(1L)).thenReturn(0);
// WHEN
boolean result = RecipientUtil.isMessageRequestAccepted(context, 1L);
@ -115,8 +111,8 @@ public class RecipientUtilTest {
public void givenIHaveReceivedASecureMessageIHaveNotSentASecureMessageAndRecipientIsNotSystemContactAndNotProfileSharing_whenIsThreadMessageRequestAccepted_thenIExpectFalse() {
// GIVEN
when(mockThreadTable.getRecipientForThreadId(anyLong())).thenReturn(recipient);
when(mockMmsSmsDatabase.getOutgoingSecureConversationCount(1L)).thenReturn(0);
when(mockMmsSmsDatabase.getSecureConversationCount(1L)).thenReturn(5);
when(mockMessageTable.getOutgoingSecureMessageCount(1L)).thenReturn(0);
when(mockMessageTable.getSecureMessageCount(1L)).thenReturn(5);
// WHEN
boolean result = RecipientUtil.isMessageRequestAccepted(context, 1L);
@ -129,8 +125,8 @@ public class RecipientUtilTest {
public void givenIHaveNotReceivedASecureMessageIHaveNotSentASecureMessageAndRecipientIsNotSystemContactAndNotProfileSharing_whenIsThreadMessageRequestAccepted_thenIExpectTrue() {
// GIVEN
when(mockThreadTable.getRecipientForThreadId(anyLong())).thenReturn(recipient);
when(mockMmsSmsDatabase.getOutgoingSecureConversationCount(1L)).thenReturn(0);
when(mockMmsSmsDatabase.getSecureConversationCount(1L)).thenReturn(0);
when(mockMessageTable.getOutgoingSecureMessageCount(1L)).thenReturn(0);
when(mockMessageTable.getSecureMessageCount(1L)).thenReturn(0);
// WHEN
boolean result = RecipientUtil.isMessageRequestAccepted(context, 1L);
@ -151,7 +147,7 @@ public class RecipientUtilTest {
@Test
public void givenNonZeroOutgoingSecureMessageCount_whenIsRecipientMessageRequestAccepted_thenIExpectTrue() {
// GIVEN
when(mockMmsSmsDatabase.getOutgoingSecureConversationCount(anyLong())).thenReturn(1);
when(mockMessageTable.getOutgoingSecureMessageCount(anyLong())).thenReturn(1);
// WHEN
boolean result = RecipientUtil.isMessageRequestAccepted(context, recipient);
@ -189,7 +185,7 @@ public class RecipientUtilTest {
public void givenNoSecureMessagesSentSomeSecureMessagesReceivedNotSharingAndNotSystemContact_whenIsRecipientMessageRequestAccepted_thenIExpectFalse() {
// GIVEN
when(recipient.isRegistered()).thenReturn(true);
when(mockMmsSmsDatabase.getSecureConversationCount(anyLong())).thenReturn(5);
when(mockMessageTable.getSecureMessageCount(anyLong())).thenReturn(5);
// WHEN
boolean result = RecipientUtil.isMessageRequestAccepted(context, recipient);
@ -201,7 +197,7 @@ public class RecipientUtilTest {
@Test
public void givenNoSecureMessagesSentNoSecureMessagesReceivedNotSharingAndNotSystemContact_whenIsRecipientMessageRequestAccepted_thenIExpectTrue() {
// GIVEN
when(mockMmsSmsDatabase.getSecureConversationCount(anyLong())).thenReturn(0);
when(mockMessageTable.getSecureMessageCount(anyLong())).thenReturn(0);
// WHEN
boolean result = RecipientUtil.isMessageRequestAccepted(context, recipient);
@ -214,7 +210,7 @@ public class RecipientUtilTest {
@Test
public void givenNoSecureMessagesSent_whenIShareProfileIfFirstSecureMessage_thenIShareProfile() {
// GIVEN
when(mockMmsSmsDatabase.getOutgoingSecureConversationCount(anyLong())).thenReturn(0);
when(mockMessageTable.getOutgoingSecureMessageCount(anyLong())).thenReturn(0);
// WHEN
RecipientUtil.shareProfileIfFirstSecureMessage(recipient);
@ -227,7 +223,7 @@ public class RecipientUtilTest {
@Test
public void givenSecureMessagesSent_whenIShareProfileIfFirstSecureMessage_thenIShareProfile() {
// GIVEN
when(mockMmsSmsDatabase.getOutgoingSecureConversationCount(anyLong())).thenReturn(5);
when(mockMessageTable.getOutgoingSecureMessageCount(anyLong())).thenReturn(5);
// WHEN
RecipientUtil.shareProfileIfFirstSecureMessage(recipient);