mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 08:39:22 +01:00
Add urgency flag to message sends.
This commit is contained in:
committed by
Greyson Parrelli
parent
c7cd261641
commit
dc04c8ed98
@@ -6,6 +6,8 @@ import net.zetetic.database.sqlcipher.SQLiteConstraintException
|
||||
import org.signal.core.util.CursorUtil
|
||||
import org.signal.core.util.SqlUtil
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.requireBoolean
|
||||
import org.signal.core.util.toInt
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.MessageLogEntry
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
@@ -67,13 +69,15 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
|
||||
const val DATE_SENT = "date_sent"
|
||||
const val CONTENT = "content"
|
||||
const val CONTENT_HINT = "content_hint"
|
||||
const val URGENT = "urgent"
|
||||
|
||||
const val CREATE_TABLE = """
|
||||
CREATE TABLE $TABLE_NAME (
|
||||
$ID INTEGER PRIMARY KEY,
|
||||
$DATE_SENT INTEGER NOT NULL,
|
||||
$CONTENT BLOB NOT NULL,
|
||||
$CONTENT_HINT INTEGER NOT NULL
|
||||
$CONTENT_HINT INTEGER NOT NULL,
|
||||
$URGENT INTEGER NOT NULL DEFAULT 1
|
||||
)
|
||||
"""
|
||||
|
||||
@@ -152,31 +156,31 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
|
||||
}
|
||||
|
||||
/** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */
|
||||
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId): Long {
|
||||
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId, urgent: Boolean): Long {
|
||||
if (!FeatureFlags.retryReceipts()) return -1
|
||||
|
||||
if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) {
|
||||
val recipientDevice = listOf(RecipientDevice(recipientId, sendMessageResult.success.devices))
|
||||
return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, listOf(messageId))
|
||||
return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, listOf(messageId), urgent)
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
/** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */
|
||||
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageIds: List<MessageId>): Long {
|
||||
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageIds: List<MessageId>, urgent: Boolean): Long {
|
||||
if (!FeatureFlags.retryReceipts()) return -1
|
||||
|
||||
if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) {
|
||||
val recipientDevice = listOf(RecipientDevice(recipientId, sendMessageResult.success.devices))
|
||||
return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, messageIds)
|
||||
return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, messageIds, urgent)
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
/** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */
|
||||
fun insertIfPossible(sentTimestamp: Long, possibleRecipients: List<Recipient>, results: List<SendMessageResult>, contentHint: ContentHint, messageId: MessageId): Long {
|
||||
fun insertIfPossible(sentTimestamp: Long, possibleRecipients: List<Recipient>, results: List<SendMessageResult>, contentHint: ContentHint, messageId: MessageId, urgent: Boolean): Long {
|
||||
if (!FeatureFlags.retryReceipts()) return -1
|
||||
|
||||
val accessList = RecipientAccessList(possibleRecipients)
|
||||
@@ -194,10 +198,10 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
|
||||
|
||||
val content: SignalServiceProtos.Content = results.first { it.isSuccess && it.success.content.isPresent }.success.content.get()
|
||||
|
||||
return insert(recipientDevices, sentTimestamp, content, contentHint, listOf(messageId))
|
||||
return insert(recipientDevices, sentTimestamp, content, contentHint, listOf(messageId), urgent)
|
||||
}
|
||||
|
||||
fun addRecipientToExistingEntryIfPossible(payloadId: Long, recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId): Long {
|
||||
fun addRecipientToExistingEntryIfPossible(payloadId: Long, recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId, urgent: Boolean): Long {
|
||||
if (!FeatureFlags.retryReceipts()) return payloadId
|
||||
|
||||
if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) {
|
||||
@@ -218,9 +222,9 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
|
||||
db.setTransactionSuccessful()
|
||||
} catch (e: SQLiteConstraintException) {
|
||||
Log.w(TAG, "Failed to append to existing entry. Creating a new one.")
|
||||
val payloadId = insertIfPossible(recipientId, sentTimestamp, sendMessageResult, contentHint, messageId)
|
||||
val newPayloadId = insertIfPossible(recipientId, sentTimestamp, sendMessageResult, contentHint, messageId, urgent)
|
||||
db.setTransactionSuccessful()
|
||||
return payloadId
|
||||
return newPayloadId
|
||||
} finally {
|
||||
db.endTransaction()
|
||||
}
|
||||
@@ -229,7 +233,7 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
|
||||
return payloadId
|
||||
}
|
||||
|
||||
private fun insert(recipients: List<RecipientDevice>, dateSent: Long, content: SignalServiceProtos.Content, contentHint: ContentHint, messageIds: List<MessageId>): Long {
|
||||
private fun insert(recipients: List<RecipientDevice>, dateSent: Long, content: SignalServiceProtos.Content, contentHint: ContentHint, messageIds: List<MessageId>, urgent: Boolean): Long {
|
||||
val db = databaseHelper.signalWritableDatabase
|
||||
|
||||
db.beginTransaction()
|
||||
@@ -238,6 +242,7 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
|
||||
put(PayloadTable.DATE_SENT, dateSent)
|
||||
put(PayloadTable.CONTENT, content.toByteArray())
|
||||
put(PayloadTable.CONTENT_HINT, contentHint.type)
|
||||
put(PayloadTable.URGENT, urgent.toInt())
|
||||
}
|
||||
|
||||
val payloadId: Long = db.insert(PayloadTable.TABLE_NAME, null, payloadValues)
|
||||
@@ -304,6 +309,7 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
|
||||
dateSent = CursorUtil.requireLong(entryCursor, PayloadTable.DATE_SENT),
|
||||
content = SignalServiceProtos.Content.parseFrom(CursorUtil.requireBlob(entryCursor, PayloadTable.CONTENT)),
|
||||
contentHint = ContentHint.fromType(CursorUtil.requireInt(entryCursor, PayloadTable.CONTENT_HINT)),
|
||||
urgent = entryCursor.requireBoolean(PayloadTable.URGENT),
|
||||
relatedMessages = messageIds
|
||||
)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,8 @@ public class PushDatabase extends Database {
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_RECEIVED_TIMESTAMP)),
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_DELIVERED_TIMESTAMP)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID)),
|
||||
"");
|
||||
"",
|
||||
true);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
@@ -180,7 +181,8 @@ public class PushDatabase extends Database {
|
||||
serverReceivedTimestamp,
|
||||
serverDeliveredTimestamp,
|
||||
serverGuid,
|
||||
"");
|
||||
"",
|
||||
true);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper.entrySet
|
||||
import org.thoughtcrime.securesms.database.KeyValueDatabase
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.UrgentMslFlagMigration
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ReactionList
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
@@ -203,8 +204,9 @@ object SignalDatabaseMigrations {
|
||||
private const val QUOTE_INDEX = 147
|
||||
private const val MY_STORY_PRIVACY_MODE = 148
|
||||
private const val EXPIRING_PROFILE_CREDENTIALS = 149
|
||||
private const val URGENT_FLAG = 150
|
||||
|
||||
const val DATABASE_VERSION = 149
|
||||
const val DATABASE_VERSION = 150
|
||||
|
||||
@JvmStatic
|
||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
@@ -2663,6 +2665,10 @@ object SignalDatabaseMigrations {
|
||||
if (oldVersion < EXPIRING_PROFILE_CREDENTIALS) {
|
||||
db.execSQL("UPDATE recipient SET profile_key_credential = NULL")
|
||||
}
|
||||
|
||||
if (oldVersion < URGENT_FLAG) {
|
||||
UrgentMslFlagMigration.migrate(context, db, oldVersion, newVersion)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.thoughtcrime.securesms.database.helpers.migration
|
||||
|
||||
import android.app.Application
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase
|
||||
|
||||
/**
|
||||
* Simple interface for allowing database migrations to live outside of [org.thoughtcrime.securesms.database.helpers.SignalDatabaseMigrations].
|
||||
*/
|
||||
interface SignalDatabaseMigration {
|
||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.thoughtcrime.securesms.database.helpers.migration
|
||||
|
||||
import android.app.Application
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase
|
||||
|
||||
/**
|
||||
* Adding an urgent flag to message envelopes to help with notifications. Need to track flag in
|
||||
* MSL table so can be resent with the correct urgency.
|
||||
*/
|
||||
object UrgentMslFlagMigration : SignalDatabaseMigration {
|
||||
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
db.execSQL("ALTER TABLE msl_payload ADD COLUMN urgent INTEGER NOT NULL DEFAULT 1")
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ data class MessageLogEntry(
|
||||
val dateSent: Long,
|
||||
val content: SignalServiceProtos.Content,
|
||||
val contentHint: ContentHint,
|
||||
@get:JvmName("isUrgent")
|
||||
val urgent: Boolean,
|
||||
val relatedMessages: List<MessageId>
|
||||
) {
|
||||
val hasRelatedMessage: Boolean
|
||||
|
||||
@@ -1273,16 +1273,7 @@ final class GroupManagerV2 {
|
||||
GroupId.V2 groupId = GroupId.v2(masterKey);
|
||||
Recipient groupRecipient = Recipient.externalGroupExact(groupId);
|
||||
DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, groupMutation, signedGroupChange);
|
||||
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(groupRecipient,
|
||||
decryptedGroupV2Context,
|
||||
null,
|
||||
System.currentTimeMillis(),
|
||||
0,
|
||||
false,
|
||||
null,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(groupRecipient, decryptedGroupV2Context, System.currentTimeMillis());
|
||||
|
||||
|
||||
DecryptedGroupChange plainGroupChange = groupMutation.getGroupChange();
|
||||
|
||||
@@ -464,18 +464,8 @@ public class GroupsV2StateProcessor {
|
||||
.addDeleteMembers(UuidUtil.toByteString(selfUuid))
|
||||
.build();
|
||||
|
||||
DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, new GroupMutation(decryptedGroup, simulatedGroupChange, simulatedGroupState), null);
|
||||
|
||||
OutgoingGroupUpdateMessage leaveMessage = new OutgoingGroupUpdateMessage(groupRecipient,
|
||||
decryptedGroupV2Context,
|
||||
null,
|
||||
System.currentTimeMillis(),
|
||||
0,
|
||||
false,
|
||||
null,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, new GroupMutation(decryptedGroup, simulatedGroupChange, simulatedGroupState), null);
|
||||
OutgoingGroupUpdateMessage leaveMessage = new OutgoingGroupUpdateMessage(groupRecipient, decryptedGroupV2Context, System.currentTimeMillis());
|
||||
|
||||
try {
|
||||
MessageDatabase mmsDatabase = SignalDatabase.mms();
|
||||
@@ -703,7 +693,7 @@ public class GroupsV2StateProcessor {
|
||||
ThreadDatabase threadDatabase = SignalDatabase.threads();
|
||||
RecipientId recipientId = recipientDatabase.getOrInsertFromGroupId(groupId);
|
||||
Recipient recipient = Recipient.resolved(recipientId);
|
||||
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, decryptedGroupV2Context, null, timestamp, 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
|
||||
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, decryptedGroupV2Context, timestamp);
|
||||
long threadId = threadDatabase.getOrCreateThreadIdFor(recipient);
|
||||
long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null);
|
||||
|
||||
|
||||
@@ -57,9 +57,9 @@ public class GroupCallUpdateSendJob extends BaseJob {
|
||||
}
|
||||
|
||||
List<RecipientId> recipientIds = Stream.of(RecipientUtil.getEligibleForSending(Recipient.resolvedList(conversationRecipient.getParticipantIds())))
|
||||
.filterNot(Recipient::isSelf)
|
||||
.map(Recipient::getId)
|
||||
.toList();
|
||||
.filterNot(Recipient::isSelf)
|
||||
.map(Recipient::getId)
|
||||
.toList();
|
||||
|
||||
return new GroupCallUpdateSendJob(recipientId,
|
||||
eraId,
|
||||
@@ -161,7 +161,8 @@ public class GroupCallUpdateSendJob extends BaseJob {
|
||||
nonSelfDestinations,
|
||||
false,
|
||||
ContentHint.DEFAULT,
|
||||
dataMessage);
|
||||
dataMessage,
|
||||
false);
|
||||
|
||||
if (includesSelf) {
|
||||
results.add(ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(dataMessage));
|
||||
|
||||
@@ -110,7 +110,7 @@ public final class PaymentNotificationSendJob extends BaseJob {
|
||||
.withPayment(new SignalServiceDataMessage.Payment(new SignalServiceDataMessage.PaymentNotification(payment.getReceipt(), payment.getNote())))
|
||||
.build();
|
||||
|
||||
SendMessageResult sendMessageResult = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.DEFAULT, dataMessage, IndividualSendEvents.EMPTY);
|
||||
SendMessageResult sendMessageResult = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.DEFAULT, dataMessage, IndividualSendEvents.EMPTY, false);
|
||||
|
||||
if (sendMessageResult.getIdentityFailure() != null) {
|
||||
Log.w(TAG, "Identity failure for " + recipient.getId());
|
||||
|
||||
@@ -153,7 +153,7 @@ public class ProfileKeySendJob extends BaseJob {
|
||||
.withTimestamp(System.currentTimeMillis())
|
||||
.withProfileKey(Recipient.self().resolve().getProfileKey());
|
||||
|
||||
List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, null, destinations, false, ContentHint.IMPLICIT, dataMessage.build());
|
||||
List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, null, destinations, false, ContentHint.IMPLICIT, dataMessage.build(), false);
|
||||
|
||||
return GroupSendJobHelper.getCompletedSends(destinations, results).completed;
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ public final class PushGroupSendJob extends PushSendJob {
|
||||
.withExpiration(groupRecipient.getExpiresInSeconds())
|
||||
.asGroupMessage(group)
|
||||
.build();
|
||||
return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage);
|
||||
return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage, message.isUrgent());
|
||||
} else {
|
||||
throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!");
|
||||
}
|
||||
@@ -351,7 +351,8 @@ public final class PushGroupSendJob extends PushSendJob {
|
||||
isRecipientUpdate,
|
||||
ContentHint.RESENDABLE,
|
||||
new MessageId(messageId, true),
|
||||
groupMessageBuilder.build());
|
||||
groupMessageBuilder.build(),
|
||||
message.isUrgent());
|
||||
}
|
||||
} catch (ServerRejectedException e) {
|
||||
throw new UndeliverableMessageException(e);
|
||||
|
||||
@@ -175,7 +175,7 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob {
|
||||
.asGroupMessage(group)
|
||||
.build();
|
||||
|
||||
List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, groupId, destinations, false, ContentHint.IMPLICIT, groupDataMessage);
|
||||
List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, groupId, destinations, false, ContentHint.IMPLICIT, groupDataMessage, false);
|
||||
|
||||
return GroupSendJobHelper.getCompletedSends(destinations, results).completed;
|
||||
}
|
||||
|
||||
@@ -254,11 +254,11 @@ public class PushMediaSendJob extends PushSendJob {
|
||||
if (Util.equals(SignalStore.account().getAci(), address.getServiceId())) {
|
||||
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
|
||||
SendMessageResult result = messageSender.sendSyncMessage(mediaMessage);
|
||||
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
|
||||
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true), false);
|
||||
return syncAccess.isPresent();
|
||||
} else {
|
||||
SendMessageResult result = messageSender.sendDataMessage(address, UnidentifiedAccessUtil.getAccessFor(context, messageRecipient), ContentHint.RESENDABLE, mediaMessage, IndividualSendEvents.EMPTY);
|
||||
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
|
||||
SendMessageResult result = messageSender.sendDataMessage(address, UnidentifiedAccessUtil.getAccessFor(context, messageRecipient), ContentHint.RESENDABLE, mediaMessage, IndividualSendEvents.EMPTY, message.isUrgent());
|
||||
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true), message.isUrgent());
|
||||
return result.getSuccess().isUnidentified();
|
||||
}
|
||||
} catch (UnregisteredUserException e) {
|
||||
|
||||
@@ -194,13 +194,13 @@ public class PushTextSendJob extends PushSendJob {
|
||||
SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
|
||||
SendMessageResult result = messageSender.sendSyncMessage(textSecureMessage);
|
||||
|
||||
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
|
||||
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false), false);
|
||||
return syncAccess.isPresent();
|
||||
} else {
|
||||
SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
|
||||
SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage, new MetricEventListener(messageId));
|
||||
SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage, new MetricEventListener(messageId), true);
|
||||
|
||||
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
|
||||
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false), true);
|
||||
return result.getSuccess().isUnidentified();
|
||||
}
|
||||
} catch (UnregisteredUserException e) {
|
||||
|
||||
@@ -242,7 +242,8 @@ public class ReactionSendJob extends BaseJob {
|
||||
false,
|
||||
ContentHint.RESENDABLE,
|
||||
messageId,
|
||||
dataMessage);
|
||||
dataMessage,
|
||||
true);
|
||||
|
||||
if (includesSelf) {
|
||||
results.add(ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(dataMessage));
|
||||
|
||||
@@ -214,7 +214,8 @@ public class RemoteDeleteSendJob extends BaseJob {
|
||||
false,
|
||||
ContentHint.RESENDABLE,
|
||||
new MessageId(messageId, isMms),
|
||||
dataMessage);
|
||||
dataMessage,
|
||||
true);
|
||||
|
||||
return GroupSendJobHelper.getCompletedSends(destinations, results);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ public class ResendMessageJob extends BaseJob {
|
||||
private final long sentTimestamp;
|
||||
private final Content content;
|
||||
private final ContentHint contentHint;
|
||||
private final boolean urgent;
|
||||
private final GroupId.V2 groupId;
|
||||
private final DistributionId distributionId;
|
||||
|
||||
@@ -58,6 +59,7 @@ public class ResendMessageJob extends BaseJob {
|
||||
private static final String KEY_SENT_TIMESTAMP = "sent_timestamp";
|
||||
private static final String KEY_CONTENT = "content";
|
||||
private static final String KEY_CONTENT_HINT = "content_hint";
|
||||
private static final String KEY_URGENT = "urgent";
|
||||
private static final String KEY_GROUP_ID = "group_id";
|
||||
private static final String KEY_DISTRIBUTION_ID = "distribution_id";
|
||||
|
||||
@@ -65,6 +67,7 @@ public class ResendMessageJob extends BaseJob {
|
||||
long sentTimestamp,
|
||||
@NonNull Content content,
|
||||
@NonNull ContentHint contentHint,
|
||||
boolean urgent,
|
||||
@Nullable GroupId.V2 groupId,
|
||||
@Nullable DistributionId distributionId)
|
||||
{
|
||||
@@ -72,6 +75,7 @@ public class ResendMessageJob extends BaseJob {
|
||||
sentTimestamp,
|
||||
content,
|
||||
contentHint,
|
||||
urgent,
|
||||
groupId,
|
||||
distributionId,
|
||||
new Parameters.Builder().setQueue(recipientId.toQueueKey())
|
||||
@@ -85,6 +89,7 @@ public class ResendMessageJob extends BaseJob {
|
||||
long sentTimestamp,
|
||||
@NonNull Content content,
|
||||
@NonNull ContentHint contentHint,
|
||||
boolean urgent,
|
||||
@Nullable GroupId.V2 groupId,
|
||||
@Nullable DistributionId distributionId,
|
||||
@NonNull Parameters parameters)
|
||||
@@ -95,6 +100,7 @@ public class ResendMessageJob extends BaseJob {
|
||||
this.sentTimestamp = sentTimestamp;
|
||||
this.content = content;
|
||||
this.contentHint = contentHint;
|
||||
this.urgent = urgent;
|
||||
this.groupId = groupId;
|
||||
this.distributionId = distributionId;
|
||||
}
|
||||
@@ -106,6 +112,7 @@ public class ResendMessageJob extends BaseJob {
|
||||
.putLong(KEY_SENT_TIMESTAMP, sentTimestamp)
|
||||
.putBlobAsString(KEY_CONTENT, content.toByteArray())
|
||||
.putInt(KEY_CONTENT_HINT, contentHint.getType())
|
||||
.putBoolean(KEY_URGENT, urgent)
|
||||
.putBlobAsString(KEY_GROUP_ID, groupId != null ? groupId.getDecodedId() : null)
|
||||
.putString(KEY_DISTRIBUTION_ID, distributionId != null ? distributionId.toString() : null)
|
||||
.build();
|
||||
@@ -152,7 +159,7 @@ public class ResendMessageJob extends BaseJob {
|
||||
contentToSend = contentToSend.toBuilder().setSenderKeyDistributionMessage(distributionBytes).build();
|
||||
}
|
||||
|
||||
SendMessageResult result = messageSender.resendContent(address, access, sentTimestamp, contentToSend, contentHint, Optional.ofNullable(groupId).map(GroupId::getDecodedId));
|
||||
SendMessageResult result = messageSender.resendContent(address, access, sentTimestamp, contentToSend, contentHint, Optional.ofNullable(groupId).map(GroupId::getDecodedId), urgent);
|
||||
|
||||
if (result.isSuccess() && distributionId != null) {
|
||||
List<SignalProtocolAddress> addresses = result.getSuccess()
|
||||
@@ -195,6 +202,7 @@ public class ResendMessageJob extends BaseJob {
|
||||
data.getLong(KEY_SENT_TIMESTAMP),
|
||||
content,
|
||||
ContentHint.fromType(data.getInt(KEY_CONTENT_HINT)),
|
||||
data.getBooleanOrDefault(KEY_URGENT, true),
|
||||
groupId,
|
||||
distributionId,
|
||||
parameters);
|
||||
|
||||
@@ -122,7 +122,7 @@ public class SendDeliveryReceiptJob extends BaseJob {
|
||||
receiptMessage);
|
||||
|
||||
if (messageId != null) {
|
||||
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageId);
|
||||
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageId, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ public class SendReadReceiptJob extends BaseJob {
|
||||
receiptMessage);
|
||||
|
||||
if (Util.hasItems(messageIds)) {
|
||||
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds);
|
||||
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ public class SendViewedReceiptJob extends BaseJob {
|
||||
receiptMessage);
|
||||
|
||||
if (Util.hasItems(messageIds)) {
|
||||
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds);
|
||||
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ public final class SenderKeyDistributionSendJob extends BaseJob {
|
||||
SenderKeyDistributionMessage message = messageSender.getOrCreateNewGroupSession(distributionId);
|
||||
List<Optional<UnidentifiedAccessPair>> access = UnidentifiedAccessUtil.getAccessFor(context, Collections.singletonList(recipient));
|
||||
|
||||
SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(distributionId, address, access, message, Optional.of(groupId.getDecodedId())).get(0);
|
||||
SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(distributionId, address, access, message, Optional.of(groupId.getDecodedId()), false).get(0);
|
||||
|
||||
if (result.isSuccess()) {
|
||||
List<SignalProtocolAddress> addresses = result.getSuccess()
|
||||
|
||||
@@ -88,10 +88,11 @@ public final class GroupSendUtil {
|
||||
boolean isRecipientUpdate,
|
||||
ContentHint contentHint,
|
||||
@NonNull MessageId messageId,
|
||||
@NonNull SignalServiceDataMessage message)
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
boolean urgent)
|
||||
throws IOException, UntrustedIdentityException
|
||||
{
|
||||
return sendMessage(context, groupId, getDistributionId(groupId), messageId, allTargets, isRecipientUpdate, DataSendOperation.resendable(message, contentHint, messageId), null);
|
||||
return sendMessage(context, groupId, getDistributionId(groupId), messageId, allTargets, isRecipientUpdate, DataSendOperation.resendable(message, contentHint, messageId, urgent), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,10 +110,11 @@ public final class GroupSendUtil {
|
||||
@NonNull List<Recipient> allTargets,
|
||||
boolean isRecipientUpdate,
|
||||
ContentHint contentHint,
|
||||
@NonNull SignalServiceDataMessage message)
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
boolean urgent)
|
||||
throws IOException, UntrustedIdentityException
|
||||
{
|
||||
return sendMessage(context, groupId, getDistributionId(groupId), null, allTargets, isRecipientUpdate, DataSendOperation.unresendable(message, contentHint), null);
|
||||
return sendMessage(context, groupId, getDistributionId(groupId), null, allTargets, isRecipientUpdate, DataSendOperation.unresendable(message, contentHint, urgent), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,7 +297,7 @@ public final class GroupSendUtil {
|
||||
Log.d(TAG, "Successfully sent using sender key to " + successCount + "/" + targets.size() + " sender key targets.");
|
||||
|
||||
if (sendOperation.shouldIncludeInMessageLog()) {
|
||||
SignalDatabase.messageLog().insertIfPossible(sendOperation.getSentTimestamp(), senderKeyTargets, results, sendOperation.getContentHint(), sendOperation.getRelatedMessageId());
|
||||
SignalDatabase.messageLog().insertIfPossible(sendOperation.getSentTimestamp(), senderKeyTargets, results, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isUrgent());
|
||||
}
|
||||
|
||||
if (relatedMessageId != null) {
|
||||
@@ -353,9 +355,9 @@ public final class GroupSendUtil {
|
||||
|
||||
synchronized (entryId) {
|
||||
if (entryId.get() == -1) {
|
||||
entryId.set(messageLogDatabase.insertIfPossible(recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId()));
|
||||
entryId.set(messageLogDatabase.insertIfPossible(recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isUrgent()));
|
||||
} else {
|
||||
entryId.set(messageLogDatabase.addRecipientToExistingEntryIfPossible(entryId.get(), recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId()));
|
||||
entryId.set(messageLogDatabase.addRecipientToExistingEntryIfPossible(entryId.get(), recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isUrgent()));
|
||||
}
|
||||
}
|
||||
}, cancelationSignal);
|
||||
@@ -424,6 +426,7 @@ public final class GroupSendUtil {
|
||||
long getSentTimestamp();
|
||||
boolean shouldIncludeInMessageLog();
|
||||
@NonNull MessageId getRelatedMessageId();
|
||||
boolean isUrgent();
|
||||
}
|
||||
|
||||
private static class DataSendOperation implements SendOperation {
|
||||
@@ -431,20 +434,22 @@ public final class GroupSendUtil {
|
||||
private final ContentHint contentHint;
|
||||
private final MessageId relatedMessageId;
|
||||
private final boolean resendable;
|
||||
private final boolean urgent;
|
||||
|
||||
public static DataSendOperation resendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, @NonNull MessageId relatedMessageId) {
|
||||
return new DataSendOperation(message, contentHint, true, relatedMessageId);
|
||||
public static DataSendOperation resendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, @NonNull MessageId relatedMessageId, boolean urgent) {
|
||||
return new DataSendOperation(message, contentHint, true, relatedMessageId, urgent);
|
||||
}
|
||||
|
||||
public static DataSendOperation unresendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint) {
|
||||
return new DataSendOperation(message, contentHint, false, null);
|
||||
public static DataSendOperation unresendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean urgent) {
|
||||
return new DataSendOperation(message, contentHint, false, null, urgent);
|
||||
}
|
||||
|
||||
private DataSendOperation(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean resendable, @Nullable MessageId relatedMessageId) {
|
||||
this.message = message;
|
||||
this.contentHint = contentHint;
|
||||
this.resendable = resendable;
|
||||
this.relatedMessageId = relatedMessageId;
|
||||
private DataSendOperation(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean resendable, @Nullable MessageId relatedMessageId, boolean urgent) {
|
||||
this.message = message;
|
||||
this.contentHint = contentHint;
|
||||
this.resendable = resendable;
|
||||
this.relatedMessageId = relatedMessageId;
|
||||
this.urgent = urgent;
|
||||
|
||||
if (resendable && relatedMessageId == null) {
|
||||
throw new IllegalArgumentException("If a message is resendable, it must have a related message ID!");
|
||||
@@ -460,7 +465,7 @@ public final class GroupSendUtil {
|
||||
throws NoSessionException, UntrustedIdentityException, InvalidKeyException, IOException, InvalidRegistrationIdException
|
||||
{
|
||||
SenderKeyGroupEvents listener = relatedMessageId != null ? new SenderKeyMetricEventListener(relatedMessageId.getId()) : SenderKeyGroupEvents.EMPTY;
|
||||
return messageSender.sendGroupDataMessage(distributionId, targets, access, isRecipientUpdate, contentHint, message, listener);
|
||||
return messageSender.sendGroupDataMessage(distributionId, targets, access, isRecipientUpdate, contentHint, message, listener, urgent);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -473,7 +478,7 @@ public final class GroupSendUtil {
|
||||
throws IOException, UntrustedIdentityException
|
||||
{
|
||||
LegacyGroupEvents listener = relatedMessageId != null ? new LegacyMetricEventListener(relatedMessageId.getId()) : LegacyGroupEvents.EMPTY;
|
||||
return messageSender.sendDataMessage(targets, access, isRecipientUpdate, contentHint, message, listener, partialListener, cancelationSignal);
|
||||
return messageSender.sendDataMessage(targets, access, isRecipientUpdate, contentHint, message, listener, partialListener, cancelationSignal, urgent);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -499,6 +504,11 @@ public final class GroupSendUtil {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUrgent() {
|
||||
return urgent;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TypingSendOperation implements SendOperation {
|
||||
@@ -553,6 +563,11 @@ public final class GroupSendUtil {
|
||||
public @NonNull MessageId getRelatedMessageId() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUrgent() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CallSendOperation implements SendOperation {
|
||||
@@ -605,6 +620,11 @@ public final class GroupSendUtil {
|
||||
public @NonNull MessageId getRelatedMessageId() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUrgent() {
|
||||
return message.isUrgent();
|
||||
}
|
||||
}
|
||||
|
||||
public static class StorySendOperation implements SendOperation {
|
||||
@@ -670,6 +690,11 @@ public final class GroupSendUtil {
|
||||
public @NonNull MessageId getRelatedMessageId() {
|
||||
return relatedMessageId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUrgent() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SenderKeyMetricEventListener implements SenderKeyGroupEvents {
|
||||
|
||||
@@ -2694,6 +2694,7 @@ public final class MessageContentProcessor {
|
||||
messageLogEntry.getDateSent(),
|
||||
messageLogEntry.getContent(),
|
||||
messageLogEntry.getContentHint(),
|
||||
messageLogEntry.isUrgent(),
|
||||
groupId,
|
||||
distributionId));
|
||||
} else {
|
||||
@@ -2735,6 +2736,7 @@ public final class MessageContentProcessor {
|
||||
messageLogEntry.getDateSent(),
|
||||
messageLogEntry.getContent(),
|
||||
messageLogEntry.getContentHint(),
|
||||
messageLogEntry.isUrgent(),
|
||||
null,
|
||||
null));
|
||||
} else if (archivedSession) {
|
||||
|
||||
@@ -32,4 +32,8 @@ public class OutgoingExpirationUpdateMessage extends OutgoingSecureMediaMessage
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUrgent() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,16 +67,9 @@ public final class OutgoingGroupUpdateMessage extends OutgoingSecureMediaMessage
|
||||
|
||||
public OutgoingGroupUpdateMessage(@NonNull Recipient recipient,
|
||||
@NonNull DecryptedGroupV2Context group,
|
||||
@Nullable final Attachment avatar,
|
||||
long sentTimeMillis,
|
||||
long expireIn,
|
||||
boolean viewOnce,
|
||||
@Nullable QuoteModel quote,
|
||||
@NonNull List<Contact> contacts,
|
||||
@NonNull List<LinkPreview> previews,
|
||||
@NonNull List<Mention> mentions)
|
||||
long sentTimeMillis)
|
||||
{
|
||||
this(recipient, new MessageGroupContext(group), getAttachments(avatar), sentTimeMillis, expireIn, viewOnce, quote, contacts, previews, mentions);
|
||||
this(recipient, new MessageGroupContext(group), Collections.emptyList(), sentTimeMillis, 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,6 +93,11 @@ public final class OutgoingGroupUpdateMessage extends OutgoingSecureMediaMessage
|
||||
return messageGroupContext.requireGroupV2Properties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUrgent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<Attachment> getAttachments(@Nullable Attachment avatar) {
|
||||
return avatar == null ? Collections.emptyList() : Collections.singletonList(avatar);
|
||||
}
|
||||
|
||||
@@ -249,6 +249,10 @@ public class OutgoingMediaMessage {
|
||||
return giftBadge;
|
||||
}
|
||||
|
||||
public boolean isUrgent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String buildMessage(SlideDeck slideDeck, String message) {
|
||||
if (!TextUtils.isEmpty(message) && !TextUtils.isEmpty(slideDeck.getBody())) {
|
||||
return slideDeck.getBody() + "\n\n" + message;
|
||||
|
||||
Reference in New Issue
Block a user