From be80619a3b39eaed7610819d7fddb6466a6044c0 Mon Sep 17 00:00:00 2001 From: Michelle Tang Date: Mon, 1 Jun 2026 14:06:14 -0400 Subject: [PATCH] Disappear 1:1 calls. --- .../preferences/CallPreference.kt | 21 ++++++ .../conversation/ConversationUpdateItem.java | 7 +- .../securesms/conversation/ExpirationTimer.kt | 4 + .../securesms/database/CallTable.kt | 47 +++++++++++- .../securesms/database/MessageTable.kt | 41 +++++++++- .../securesms/database/ThreadTable.kt | 2 +- .../database/model/MessageRecord.java | 4 + .../database/model/MmsMessageRecord.java | 8 +- .../database/model/UpdateDescription.java | 16 +++- .../securesms/util/RemoteConfig.kt | 8 ++ ...ersation_settings_call_preference_item.xml | 9 +++ .../database/CollapsingMessagesTests.kt | 75 ++++++++++--------- 12 files changed, 193 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/CallPreference.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/CallPreference.kt index 4c96fe3df7..6eda6d68a5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/CallPreference.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/CallPreference.kt @@ -7,11 +7,13 @@ import org.thoughtcrime.securesms.database.CallTable import org.thoughtcrime.securesms.database.MessageTypes import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.databinding.ConversationSettingsCallPreferenceItemBinding +import org.thoughtcrime.securesms.dependencies.AppDependencies import org.thoughtcrime.securesms.util.DateUtils import org.thoughtcrime.securesms.util.adapter.mapping.BindingFactory import org.thoughtcrime.securesms.util.adapter.mapping.BindingViewHolder import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel +import org.thoughtcrime.securesms.util.visible /** * Renders a single call preference row when displaying call info. @@ -41,6 +43,25 @@ object CallPreference { binding.callIcon.setImageResource(getCallIcon(model.call)) binding.callType.text = getCallType(model.call) binding.callTime.text = getCallTime(model.record) + presentTimer(model.record) + } + + private fun presentTimer(messageRecord: MessageRecord) { + if (messageRecord.expiresIn > 0) { + binding.callTimer.visible = true + binding.callTimer.setPercentComplete(0f) + + if (messageRecord.expireStarted > 0) { + binding.callTimer.setExpirationTime(messageRecord.expireStarted, messageRecord.expiresIn) + binding.callTimer.startAnimation() + + if (messageRecord.expireStarted + messageRecord.expiresIn <= System.currentTimeMillis()) { + AppDependencies.expiringMessageManager.checkSchedule() + } + } + } else { + binding.callTimer.visible = false + } } @DrawableRes diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java index 9d0ef55378..4b05c6795b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java @@ -19,7 +19,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.StringRes; import androidx.appcompat.content.res.AppCompatResources; import androidx.core.content.ContextCompat; import androidx.lifecycle.LifecycleOwner; @@ -104,6 +103,7 @@ public final class ConversationUpdateItem extends FrameLayout private EventListener eventListener; private Button collapsedButton; private float lastYDownRelativeToThis; + private int tint; private final UpdateObserver updateObserver = new UpdateObserver(); @@ -221,6 +221,8 @@ public final class ConversationUpdateItem extends FrameLayout observeDisplayBody(lifecycleOwner, spannableMessage); observeDisplayBodyWithTimer(lifecycleOwner); + this.tint = updateDescription.getTint(getContext()); + boolean donationRequest = conversationMessage.getMessageRecord().isReleaseChannelDonationRequest(); present(conversationMessage, nextMessageRecord, conversationRecipient, isMessageRequestAccepted); @@ -487,8 +489,9 @@ public final class ConversationUpdateItem extends FrameLayout SpannableStringBuilder builder = new SpannableStringBuilder(displayBody); + int color = tint != 0 ? tint : ContextCompat.getColor(getContext(), R.color.signal_icon_tint_secondary); if (latestFrame != 0) { - Drawable drawable = DrawableUtil.tint(getContext().getDrawable(latestFrame), ContextCompat.getColor(getContext(), R.color.signal_icon_tint_secondary)); + Drawable drawable = DrawableUtil.tint(getContext().getDrawable(latestFrame), color); SpanUtil.appendCenteredImageSpan(builder, drawable, 12, 12); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ExpirationTimer.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/ExpirationTimer.kt index 77be52a38d..e540158a27 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ExpirationTimer.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ExpirationTimer.kt @@ -41,6 +41,10 @@ class ExpirationTimer( } fun calculateProgress(): Float { + if (startedAt == 0L) { + return 0f + } + val progressed = System.currentTimeMillis() - startedAt val percentComplete = progressed.toFloat() / expiresIn.toFloat() diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt index 6c834e9dcf..45f220fb0b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt @@ -30,6 +30,7 @@ import org.signal.core.util.update import org.signal.core.util.withinTransaction import org.signal.ringrtc.CallId import org.signal.ringrtc.CallManager.RingUpdate +import org.thoughtcrime.securesms.database.CallTable.Companion.TIMESTAMP import org.thoughtcrime.securesms.database.model.MessageId import org.thoughtcrime.securesms.dependencies.AppDependencies import org.thoughtcrime.securesms.jobs.CallLinkUpdateSendJob @@ -109,24 +110,66 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl ) } fun markAllCallEventsRead(timestamp: Long = Long.MAX_VALUE) { + val now = System.currentTimeMillis() + + val allUnreadMissedCalls = readableDatabase + .select(MESSAGE_ID) + .from(TABLE_NAME) + .where("$TIMESTAMP <= ? AND $READ != ? AND $EVENT = ?", timestamp, ReadState.serialize(ReadState.READ), Event.serialize(Event.MISSED)) + .run() + .readToList { cursor -> + cursor.requireLong(MESSAGE_ID) + } + val updateCount = writableDatabase .update(TABLE_NAME) .values(READ to ReadState.serialize(ReadState.READ)) .where("$TIMESTAMP <= ? AND $READ != ?", timestamp, ReadState.serialize(ReadState.READ)) .run() + val expiringCalls = SignalDatabase.messages.getUnstartedExpirations(allUnreadMissedCalls) + + if (expiringCalls.isNotEmpty()) { + Log.i(TAG, "Found ${expiringCalls.size} calls that needs expiring.") + SignalDatabase.messages.markExpireStarted(expiringCalls.map { it.key to now }) + for ((messageId, expiresIn) in expiringCalls) { + AppDependencies.expiringMessageManager.scheduleDeletion(messageId, true, now, expiresIn) + } + } + if (updateCount > 0) { notifyConversationListListeners() } } fun markAllCallEventsWithPeerBeforeTimestampRead(peer: RecipientId, timestamp: Long): Call? { + val now = System.currentTimeMillis() val latestCallAsOfTimestamp = writableDatabase.withinTransaction { db -> + + val unreadMissedCalls = db + .select(MESSAGE_ID) + .from(TABLE_NAME) + .where("$PEER = ? AND $TIMESTAMP <= ? AND $READ != ? AND $EVENT = ?", peer.toLong(), timestamp, ReadState.serialize(ReadState.READ), Event.serialize(Event.MISSED)) + .run() + .readToList { cursor -> + cursor.requireLong(MESSAGE_ID) + } + val updated = db.update(TABLE_NAME) .values(READ to ReadState.serialize(ReadState.READ)) .where("$PEER = ? AND $TIMESTAMP <= ?", peer.toLong(), timestamp) .run() + val expiring = SignalDatabase.messages.getUnstartedExpirations(unreadMissedCalls) + + if (expiring.isNotEmpty()) { + Log.i(TAG, "Found ${expiring.size} calls that needs expiring.") + SignalDatabase.messages.markExpireStarted(expiring.map { it.key to now }) + for ((messageId, expiresIn) in expiring) { + AppDependencies.expiringMessageManager.scheduleDeletion(messageId, true, now, expiresIn) + } + } + if (updated == 0) { null } else { @@ -157,7 +200,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl val messageType: Long = Call.getMessageType(type, direction, event) writableDatabase.withinTransaction { - val result = SignalDatabase.messages.insertCallLog(peer, messageType, timestamp, direction == Direction.OUTGOING) + val result = SignalDatabase.messages.insertOneToOneCallLog(peer, messageType, timestamp, direction == Direction.OUTGOING) val values = contentValuesOf( CALL_ID to callId, MESSAGE_ID to result.messageId, @@ -202,7 +245,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl if (call.messageId == null) { Log.w(TAG, "Call does not have an associated message id! No message to update.") } else { - SignalDatabase.messages.updateCallLog(call.messageId, call.messageType) + SignalDatabase.messages.updateOneToOneCallLog(call.messageId, call.messageType) } AppDependencies.messageNotifier.updateNotification(context) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt index dbe72c0922..267e853671 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt @@ -655,6 +655,32 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat return queryMessages(where, null) } + /** + * Given a list of ids, will return a list of the ids that have an expiration and what that expiration is. + */ + fun getUnstartedExpirations(messageIds: List): Map { + val expirations: MutableMap = hashMapOf() + + SqlUtil.buildCollectionQuery( + column = ID, + values = messageIds, + prefix = "$EXPIRES_IN != 0 AND $EXPIRE_STARTED = 0 AND" + ).forEach { query -> + readableDatabase + .select(ID, EXPIRES_IN) + .from(TABLE_NAME) + .where(query.where, query.whereArgs) + .run() + .use { cursor -> + while (cursor.moveToNext()) { + expirations[cursor.requireLong(ID)] = cursor.requireLong(EXPIRES_IN) + } + } + } + + return expirations + } + /** * Returns true iff * - the message will expire within [ChatItemArchiveExporter.EXPIRATION_CUTOFF] once viewed @@ -876,11 +902,12 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat return results } - fun insertCallLog(recipientId: RecipientId, type: Long, timestamp: Long, outgoing: Boolean): InsertResult { + fun insertOneToOneCallLog(recipientId: RecipientId, type: Long, timestamp: Long, outgoing: Boolean): InsertResult { val recipient = Recipient.resolved(recipientId) val threadIdResult = threads.getOrCreateThreadIdResultFor(recipient.id, recipient.isGroup) val threadId = threadIdResult.threadId val dateReceived = System.currentTimeMillis() + val expiresIn = if (RemoteConfig.disappearMore) threads.getExpiresIn(threadId) else 0 val values = contentValuesOf( FROM_RECIPIENT_ID to if (outgoing) Recipient.self().id.serialize() else recipientId.serialize(), @@ -891,7 +918,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat READ to 1, NOTIFIED to 1, TYPE to type, - THREAD_ID to threadId + THREAD_ID to threadId, + EXPIRES_IN to expiresIn ) val messageId = writableDatabase.insert(TABLE_NAME, null, values) @@ -910,7 +938,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat ) } - fun updateCallLog(messageId: Long, type: Long) { + fun updateOneToOneCallLog(messageId: Long, type: Long) { val message = getMessageRecordOrNull(messageId = messageId) writableDatabase .update(TABLE_NAME) @@ -930,6 +958,13 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat maybeCollapseMessage(db = writableDatabase, messageId = messageId, threadId = threadId, dateReceived = message.dateReceived, messageExtras = message.messageExtras, messageType = type) } + // Start disappearing timer when a call is answered or declined (e.g. not missed) + if (message?.expiresIn != null && message.expiresIn != 0L && !MessageTypes.isMissedVideoCall(type) && !MessageTypes.isMissedAudioCall(type)) { + val now = System.currentTimeMillis() + markExpireStarted(messageId, now) + AppDependencies.expiringMessageManager.scheduleDeletion(messageId, message.isMms, now, message.expiresIn) + } + notifyConversationListeners(threadId) AppDependencies.databaseObserver.notifyMessageUpdateObservers(MessageId(messageId)) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt index 679679cb30..04b49acdbf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadTable.kt @@ -2086,7 +2086,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa } } - private fun getExpiresIn(threadId: Long): Long { + fun getExpiresIn(threadId: Long): Long { return readableDatabase .select(EXPIRES_IN) .from(TABLE_NAME) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index 5ad3bc7265..183b28ab77 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -511,6 +511,10 @@ public abstract class MessageRecord extends DisplayRecord { return UpdateDescription.staticDescriptionWithExpiration(string, glyph); } + protected static @NonNull UpdateDescription staticUpdateDescriptionWithExpiration(@NonNull String string, Glyph glyph, @ColorInt int lightTint, @ColorInt int darkTint) { + return UpdateDescription.staticDescriptionWithExpiration(string, glyph, lightTint, darkTint); + } + protected static @NonNull UpdateDescription staticUpdateDescription(@NonNull String string, Glyph glyph, @ColorInt int lightTint, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java index 34bcf28363..cc2d2f878a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java @@ -265,13 +265,13 @@ public class MmsMessageRecord extends MessageRecord { if (call.getEvent() == CallTable.Event.NOT_ACCEPTED) { int message = isVideoCall ? R.string.MessageRecord_unanswered_video_call : R.string.MessageRecord_unanswered_voice_call; - return staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(message), callDateString), + return staticUpdateDescriptionWithExpiration(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(message), callDateString), icon, ContextCompat.getColor(context, R.color.core_red_shade), ContextCompat.getColor(context, R.color.core_red)); } else { int updateString = isVideoCall ? R.string.MessageRecord_outgoing_video_call : R.string.MessageRecord_outgoing_voice_call; - return staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(updateString), callDateString), icon); + return staticUpdateDescriptionWithExpiration(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(updateString), callDateString), icon); } } else { boolean isVideoCall = call.getType() == CallTable.Type.VIDEO_CALL; @@ -279,7 +279,7 @@ public class MmsMessageRecord extends MessageRecord { if (accepted || !call.isDisplayedAsMissedCallInUi()) { int updateString = isVideoCall ? R.string.MessageRecord_incoming_video_call : R.string.MessageRecord_incoming_voice_call; Glyph icon = isVideoCall ? Glyph.VIDEO_CAMERA : Glyph.PHONE; - return staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(updateString), callDateString), icon); + return staticUpdateDescriptionWithExpiration(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(updateString), callDateString), icon); } else { Glyph icon = isVideoCall ? Glyph.VIDEO_CAMERA : Glyph.PHONE; int message; @@ -291,7 +291,7 @@ public class MmsMessageRecord extends MessageRecord { message = isVideoCall ? R.string.MessageRecord_missed_video_call : R.string.MessageRecord_missed_voice_call; } - return staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, + return staticUpdateDescriptionWithExpiration(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(message), callDateString), icon, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java index 6019ace2fe..978e6dcf77 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms.database.model; +import android.content.Context; import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; @@ -10,6 +11,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import org.signal.core.ui.util.ThemeUtil; import org.thoughtcrime.securesms.fonts.SignalSymbols.Glyph; import org.signal.core.models.ServiceId; @@ -98,7 +100,14 @@ public final class UpdateDescription { * Create an update description that's string value is fixed with a start glyph and has the ability to expire when a disappearing timer is set. */ public static UpdateDescription staticDescriptionWithExpiration(@NonNull String staticString, Glyph glyph) { - return new UpdateDescription(Collections.emptyList(), null, new SpannableString(staticString), glyph, true,0, 0); + return staticDescriptionWithExpiration(staticString, glyph, 0, 0); + } + + /** + * Create an update description that's string value is fixed with a start glyph and has the ability to expire when a disappearing timer is set. + */ + public static UpdateDescription staticDescriptionWithExpiration(@NonNull String staticString, Glyph glyph, @ColorInt int lightTint, @ColorInt int darkTint) { + return new UpdateDescription(Collections.emptyList(), null, new SpannableString(staticString), glyph, true, lightTint, darkTint); } /** @@ -161,6 +170,11 @@ public final class UpdateDescription { return darkTint; } + public @ColorInt int getTint(Context context) { + boolean isDarkTheme = ThemeUtil.isDarkTheme(context); + return isDarkTheme ? getDarkTint() : getLightTint(); + } + public boolean hasExpiration() { return canExpire; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/RemoteConfig.kt b/app/src/main/java/org/thoughtcrime/securesms/util/RemoteConfig.kt index 6def4ab3f8..affe1c220b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/RemoteConfig.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/RemoteConfig.kt @@ -1467,5 +1467,13 @@ object RemoteConfig { hotSwappable = true ) + @JvmStatic + @get:JvmName("disappearMore") + val disappearMore: Boolean by remoteBoolean( + key = "android.disappearMore", + defaultValue = false, + hotSwappable = true + ) + // endregion } diff --git a/app/src/main/res/layout/conversation_settings_call_preference_item.xml b/app/src/main/res/layout/conversation_settings_call_preference_item.xml index 0f603d47a2..af6aab9834 100644 --- a/app/src/main/res/layout/conversation_settings_call_preference_item.xml +++ b/app/src/main/res/layout/conversation_settings_call_preference_item.xml @@ -44,5 +44,14 @@ app:layout_constraintTop_toBottomOf="@id/call_type" tools:text="10:00 AM" /> + \ No newline at end of file diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/CollapsingMessagesTests.kt b/app/src/test/java/org/thoughtcrime/securesms/database/CollapsingMessagesTests.kt index 20912240a6..bc13f94d82 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/CollapsingMessagesTests.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/database/CollapsingMessagesTests.kt @@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.mms.OutgoingMessage import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.testutil.RecipientTestRule +import org.thoughtcrime.securesms.util.RemoteConfig import kotlin.time.Duration.Companion.days @RunWith(RobolectricTestRunner::class) @@ -46,11 +47,13 @@ class CollapsingMessagesTests { alice = recipients.createRecipient("Alice Android") aliceThread = SignalDatabase.threads.getOrCreateThreadIdFor(Recipient.resolved(alice)) bob = recipients.createRecipient("Bob Android") + + every { RemoteConfig.disappearMore } returns false } @Test fun givenCollapsibleMessage_whenIInsert_thenItBecomesHead() { - val messageId = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId + val messageId = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId val msg = message.getMessageRecord(messageId) assertEquals(CollapsedState.HEAD_COLLAPSED, msg.collapsedState) @@ -59,9 +62,9 @@ class CollapsingMessagesTests { @Test fun givenSameCollapsibleTypes_whenIInsert_thenAllCollapseUnderHead() { - val messageId1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId - val messageId2 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId - val messageId3 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false).messageId + val messageId1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId + val messageId2 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId + val messageId3 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false).messageId val msg1 = message.getMessageRecord(messageId1) val msg2 = message.getMessageRecord(messageId2) @@ -79,7 +82,7 @@ class CollapsingMessagesTests { @Test fun givenDifferentCollapsedTypes_whenIInsert_thenNoCollapsing() { - val messageId1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId + val messageId1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId val messageId2 = recipients.insertOutgoingMessage(OutgoingMessage.identityVerifiedMessage(Recipient.resolved(alice), 2000L), aliceThread) val msg1 = message.getMessageRecord(messageId1) @@ -103,7 +106,7 @@ class CollapsingMessagesTests { @Test fun givenMessagesOnDifferentDays_whenIInsert_thenNoCollapsing() { - val messageId1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId + val messageId1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId message.writableDatabase.update( MessageTable.TABLE_NAME, @@ -112,7 +115,7 @@ class CollapsingMessagesTests { arrayOf(messageId1.toString()) ) - val messageId2 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId + val messageId2 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId val msg2 = message.getMessageRecord(messageId2) assertEquals(CollapsedState.HEAD_COLLAPSED, msg2.collapsedState) @@ -121,9 +124,9 @@ class CollapsingMessagesTests { @Test fun givenRegularMessageBetweenCollapsed_whenIInsertCollapsed_thenNoCollapsing() { - val messageId1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId + val messageId1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId val messageId2 = recipients.insertOutgoingMessage(alice, sentTimeMillis = 2000L) - val messageId3 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false).messageId + val messageId3 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false).messageId val msg1 = message.getMessageRecord(messageId1) val msg2 = message.getMessageRecord(messageId2) @@ -141,8 +144,8 @@ class CollapsingMessagesTests { @Test fun givenDifferentThreads_whenIInsertCollapsed_thenNoCollapsing() { - val messageId1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId - val messageId2 = message.insertCallLog(bob, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId + val messageId1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId + val messageId2 = message.insertOneToOneCallLog(bob, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId val msg1 = message.getMessageRecord(messageId1) val msg2 = message.getMessageRecord(messageId2) @@ -156,9 +159,9 @@ class CollapsingMessagesTests { @Test fun givenCollapsedMessages_whenIDeleteFirstMessage_thenNextMessageBecomesHead() { - val messageId1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId - val messageId2 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId - val messageId3 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false).messageId + val messageId1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId + val messageId2 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId + val messageId3 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false).messageId message.deleteMessage(messageId1, aliceThread) @@ -174,9 +177,9 @@ class CollapsingMessagesTests { @Test fun givenCollapsedMessages_whenIDeleteNonFirstMessage_thenFirstMessageStaysHead() { - val messageId1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId - val messageId2 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId - val messageId3 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false).messageId + val messageId1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId + val messageId2 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId + val messageId3 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false).messageId message.deleteMessage(messageId2, aliceThread) @@ -192,8 +195,8 @@ class CollapsingMessagesTests { @Test fun givenTwoCollapsingTypes_whenIDeleteHeadOfFirstGroup_thenSecondGroupIsUnchanged() { - val call1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false) - val call2 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false) + val call1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false) + val call2 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false) val recipient = Recipient.resolved(alice) val identity1Id = recipients.insertOutgoingMessage(OutgoingMessage.identityVerifiedMessage(recipient, 3000L), call1.threadId) @@ -215,12 +218,12 @@ class CollapsingMessagesTests { @Test fun givenPendingCollapsingEvents_whenIMarkSeenAtASpecificTime_thenEverythingBeforeThatTimeIsCollapsed() { - val call1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false) - val call2 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false) + val call1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false) + val call2 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false) message.collapsePendingCollapsibleEvents(aliceThread, System.currentTimeMillis()) - val call3 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false) + val call3 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false) val msgCall1 = message.getMessageRecord(call1.messageId) val msgCall2 = message.getMessageRecord(call2.messageId) @@ -233,12 +236,12 @@ class CollapsingMessagesTests { @Test fun givenPendingCollapsingEvents_whenIMarkAllAsSeen_thenEverythingIsCollapsed() { - val call1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false) - val call2 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false) + val call1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false) + val call2 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false) message.collapseAllPendingCollapsibleEvents() - val call3 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false) + val call3 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false) val msgCall1 = message.getMessageRecord(call1.messageId) val msgCall2 = message.getMessageRecord(call2.messageId) @@ -251,10 +254,10 @@ class CollapsingMessagesTests { @Test fun givenCollapsedEvents_whenITrimTheThreadByCount_thenIExpectANewHead() { - val call1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false) - val call2 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false) - val call3 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false) - val call4 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 4000L, false) + val call1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false) + val call2 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false) + val call3 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false) + val call4 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 4000L, false) val msgCall1 = message.getMessageRecord(call1.messageId) val msgCall2 = message.getMessageRecord(call2.messageId) @@ -274,11 +277,11 @@ class CollapsingMessagesTests { @Test fun givenCollapsedEvents_whenITrimTheThreadByDate_thenIExpectANewHead() { - val call1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false) - val call2 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false) + val call1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false) + val call2 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false) val trimBeforeDate = System.currentTimeMillis() - val call3 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false) - val call4 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 4000L, false) + val call3 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false) + val call4 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 4000L, false) message.collapsePendingCollapsibleEvents(aliceThread, System.currentTimeMillis()) @@ -303,9 +306,9 @@ class CollapsingMessagesTests { mockkObject(CollapsibleEvents) every { CollapsibleEvents.MAX_SIZE } returns 2 - val messageId1 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId - val messageId2 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId - val messageId3 = message.insertCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false).messageId + val messageId1 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 1000L, false).messageId + val messageId2 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 2000L, false).messageId + val messageId3 = message.insertOneToOneCallLog(alice, MessageTypes.INCOMING_AUDIO_CALL_TYPE, 3000L, false).messageId val msg1 = message.getMessageRecord(messageId1) val msg2 = message.getMessageRecord(messageId2)