Add support for versioned expiration timers.

Co-authored-by: Greyson Parrelli <greyson@signal.org>
This commit is contained in:
Cody Henthorne
2024-08-27 07:41:35 -04:00
committed by Nicholas Tinsley
parent 4152294b57
commit 1f196f74ff
43 changed files with 392 additions and 139 deletions

View File

@@ -84,6 +84,7 @@ class Recipient(
private val messageRingtoneUri: Uri? = null,
private val callRingtoneUri: Uri? = null,
val expiresInSeconds: Int = 0,
val expireTimerVersion: Int = 1,
private val registeredValue: RegisteredState = RegisteredState.UNKNOWN,
val profileKey: ByteArray? = null,
val expiringProfileKeyCredential: ExpiringProfileKeyCredential? = null,
@@ -314,9 +315,12 @@ class Recipient(
/** The notification channel, if both set and supported by the system. Otherwise null. */
val notificationChannel: String? = if (!NotificationChannels.supported()) null else notificationChannelValue
/** The user's payment capability. */
/** The user's capability to handle synchronizing deletes across linked devices. */
val deleteSyncCapability: Capability = capabilities.deleteSync
/** The user's capability to handle tracking an expire timer version. */
val versionedExpirationTimerCapability: Capability = capabilities.versionedExpirationTimer
/** The state around whether we can send sealed sender to this user. */
val sealedSenderAccessMode: SealedSenderAccessMode = if (pni.isPresent && pni == serviceId) {
SealedSenderAccessMode.DISABLED

View File

@@ -167,6 +167,7 @@ object RecipientCreator {
callVibrate = record.callVibrateState,
isBlocked = record.isBlocked,
expiresInSeconds = record.expireMessages,
expireTimerVersion = record.expireTimerVersion,
participantIdsValue = participantIds ?: LinkedList(),
isActiveGroup = groupRecord.map { it.isActive }.orElse(false),
profileName = record.signalProfileName,

View File

@@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mms.OutgoingMessage;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
import org.thoughtcrime.securesms.util.ExpirationTimerUtil;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
@@ -324,21 +325,23 @@ public class RecipientUtil {
/**
* Checks if a universal timer is set and if the thread should have it set on it. Attempts to abort quickly and perform
* minimal database access.
*
* @return The new expire timer version if the timer was set, otherwise null.
*/
@WorkerThread
public static boolean setAndSendUniversalExpireTimerIfNecessary(@NonNull Context context, @NonNull Recipient recipient, long threadId) {
public static @Nullable Integer setAndSendUniversalExpireTimerIfNecessary(@NonNull Context context, @NonNull Recipient recipient, long threadId) {
int defaultTimer = SignalStore.settings().getUniversalExpireTimer();
if (defaultTimer == 0 || recipient.isGroup() || recipient.isDistributionList() || recipient.getExpiresInSeconds() != 0 || !recipient.isRegistered()) {
return false;
return null;
}
if (threadId == -1 || SignalDatabase.messages().canSetUniversalTimer(threadId)) {
SignalDatabase.recipients().setExpireMessages(recipient.getId(), defaultTimer);
OutgoingMessage outgoingMessage = OutgoingMessage.expirationUpdateMessage(recipient, System.currentTimeMillis(), defaultTimer * 1000L);
int expireTimerVersion = ExpirationTimerUtil.setExpirationTimer(recipient.getId(), defaultTimer);
OutgoingMessage outgoingMessage = OutgoingMessage.expirationUpdateMessage(recipient, System.currentTimeMillis(), defaultTimer * 1000L, expireTimerVersion);
MessageSender.send(context, outgoingMessage, SignalDatabase.threads().getOrCreateThreadIdFor(recipient), MessageSender.SendType.SIGNAL, null, null);
return true;
return expireTimerVersion;
}
return false;
return null;
}
@WorkerThread