diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java index 1d73994b7..6fc4b1782 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java @@ -993,17 +993,26 @@ public class ConversationListFragment extends MainFragment implements ActionMode } private void handleMarkAsRead(@NonNull Collection ids) { - Context context = requireContext(); + Context context = requireContext(); + Stopwatch stopwatch = new Stopwatch("mark-read"); SimpleTask.run(getViewLifecycleOwner().getLifecycle(), () -> { + stopwatch.split("task-start"); + List messageIds = SignalDatabase.threads().setRead(ids, false); + stopwatch.split("db"); ApplicationDependencies.getMessageNotifier().updateNotification(context); + stopwatch.split("notification"); + MarkReadReceiver.process(context, messageIds); + stopwatch.split("process"); return null; }, none -> { endActionModeIfActive(); + stopwatch.stop(TAG); + }); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.java b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.java index cc0ee0497..b8a796144 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.java @@ -232,12 +232,14 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie EXPORT_STATE + " BLOB DEFAULT NULL, " + EXPORTED + " INTEGER DEFAULT 0);"; + private static final String INDEX_THREAD_DATE = "mms_thread_date_index"; + public static final String[] CREATE_INDEXS = { "CREATE INDEX IF NOT EXISTS mms_read_and_notified_and_thread_id_index ON " + TABLE_NAME + "(" + READ + "," + NOTIFIED + "," + THREAD_ID + ");", "CREATE INDEX IF NOT EXISTS mms_type_index ON " + TABLE_NAME + " (" + TYPE + ");", "CREATE INDEX IF NOT EXISTS mms_date_sent_index ON " + TABLE_NAME + " (" + DATE_SENT + ", " + RECIPIENT_ID + ", " + THREAD_ID + ");", "CREATE INDEX IF NOT EXISTS mms_date_server_index ON " + TABLE_NAME + " (" + DATE_SERVER + ");", - "CREATE INDEX IF NOT EXISTS mms_thread_date_index ON " + TABLE_NAME + " (" + THREAD_ID + ", " + DATE_RECEIVED + ");", + "CREATE INDEX IF NOT EXISTS " + INDEX_THREAD_DATE + " ON " + TABLE_NAME + " (" + THREAD_ID + ", " + DATE_RECEIVED + ");", "CREATE INDEX IF NOT EXISTS mms_reactions_unread_index ON " + TABLE_NAME + " (" + REACTIONS_UNREAD + ");", "CREATE INDEX IF NOT EXISTS mms_story_type_index ON " + TABLE_NAME + " (" + STORY_TYPE + ");", "CREATE INDEX IF NOT EXISTS mms_parent_story_id_index ON " + TABLE_NAME + " (" + PARENT_STORY_ID + ");", @@ -2020,7 +2022,7 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie database.beginTransaction(); try { - cursor = database.query(TABLE_NAME, new String[] { ID, RECIPIENT_ID, DATE_SENT, TYPE, EXPIRES_IN, EXPIRE_STARTED, THREAD_ID, STORY_TYPE }, where, arguments, null, null, null); + cursor = database.query(TABLE_NAME + " INDEXED BY " + INDEX_THREAD_DATE, new String[] { ID, RECIPIENT_ID, DATE_SENT, TYPE, EXPIRES_IN, EXPIRE_STARTED, THREAD_ID, STORY_TYPE }, where, arguments, null, null, null); while(cursor != null && cursor.moveToNext()) { if (MessageTypes.isSecureType(CursorUtil.requireLong(cursor, TYPE))) { @@ -2045,7 +2047,7 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie contentValues.put(REACTIONS_UNREAD, 0); contentValues.put(REACTIONS_LAST_SEEN, System.currentTimeMillis()); - database.update(TABLE_NAME, contentValues, where, arguments); + database.update(TABLE_NAME + " INDEXED BY " + INDEX_THREAD_DATE, contentValues, where, arguments); database.setTransactionSuccessful(); } finally { if (cursor != null) cursor.close(); @@ -3913,7 +3915,7 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie public int getUnreadCount(long threadId) { String selection = READ + " = 0 AND " + STORY_TYPE + " = 0 AND " + THREAD_ID + " = " + threadId + " AND " + PARENT_STORY_ID + " <= 0"; - try (Cursor cursor = getReadableDatabase().query(TABLE_NAME, COUNT, selection, null, null, null, null)) { + try (Cursor cursor = getReadableDatabase().query(TABLE_NAME + " INDEXED BY " + INDEX_THREAD_DATE, COUNT, selection, null, null, null, null)) { if (cursor.moveToFirst()) { return cursor.getInt(0); } else { diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java index 273d40c43..87298f51e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java @@ -10,6 +10,7 @@ import androidx.annotation.NonNull; import com.annimon.stream.Collectors; import com.annimon.stream.Stream; +import org.signal.core.util.Stopwatch; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.database.MessageTable.ExpirationInfo; @@ -72,21 +73,15 @@ public class MarkReadReceiver extends BroadcastReceiver { public static void process(@NonNull Context context, @NonNull List markedReadMessages) { if (markedReadMessages.isEmpty()) return; - List syncMessageIds = Stream.of(markedReadMessages) - .map(MarkedMessageInfo::getSyncMessageId) - .toList(); - List mmsExpirationInfo = Stream.of(markedReadMessages) - .map(MarkedMessageInfo::getExpirationInfo) - .filter(ExpirationInfo::isMms) - .filter(info -> info.getExpiresIn() > 0 && info.getExpireStarted() <= 0) - .toList(); - List smsExpirationInfo = Stream.of(markedReadMessages) - .map(MarkedMessageInfo::getExpirationInfo) - .filterNot(ExpirationInfo::isMms) - .filter(info -> info.getExpiresIn() > 0 && info.getExpireStarted() <= 0) - .toList(); + List syncMessageIds = Stream.of(markedReadMessages) + .map(MarkedMessageInfo::getSyncMessageId) + .toList(); + List expirationInfo = Stream.of(markedReadMessages) + .map(MarkedMessageInfo::getExpirationInfo) + .filter(info -> info.getExpiresIn() > 0 && info.getExpireStarted() <= 0) + .toList(); - scheduleDeletion(context, smsExpirationInfo, mmsExpirationInfo); + scheduleDeletion(expirationInfo); MultiDeviceReadUpdateJob.enqueue(syncMessageIds); @@ -108,23 +103,13 @@ public class MarkReadReceiver extends BroadcastReceiver { }); } - private static void scheduleDeletion(@NonNull Context context, - @NonNull List smsExpirationInfo, - @NonNull List mmsExpirationInfo) - { - if (smsExpirationInfo.size() > 0) { - SignalDatabase.messages().markExpireStarted(Stream.of(smsExpirationInfo).map(ExpirationInfo::getId).toList(), System.currentTimeMillis()); - } + private static void scheduleDeletion(@NonNull List expirationInfo) { + if (expirationInfo.size() > 0) { + SignalDatabase.messages().markExpireStarted(Stream.of(expirationInfo).map(ExpirationInfo::getId).toList(), System.currentTimeMillis()); - if (mmsExpirationInfo.size() > 0) { - SignalDatabase.messages().markExpireStarted(Stream.of(mmsExpirationInfo).map(ExpirationInfo::getId).toList(), System.currentTimeMillis()); - } - - if (smsExpirationInfo.size() + mmsExpirationInfo.size() > 0) { ExpiringMessageManager expirationManager = ApplicationDependencies.getExpiringMessageManager(); - Stream.concat(Stream.of(smsExpirationInfo), Stream.of(mmsExpirationInfo)) - .forEach(info -> expirationManager.scheduleDeletion(info.getId(), info.isMms(), info.getExpiresIn())); + expirationInfo.stream().forEach(info -> expirationManager.scheduleDeletion(info.getId(), info.isMms(), info.getExpiresIn())); } } }