mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Add support for rendering session switchover events.
This commit is contained in:
@@ -2406,6 +2406,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
|
||||
@VisibleForTesting
|
||||
fun writePnpChangeSetToDisk(changeSet: PnpChangeSet, inputPni: PNI?): RecipientId {
|
||||
var hadThreadMerge = false
|
||||
for (operation in changeSet.operations) {
|
||||
@Exhaustive
|
||||
when (operation) {
|
||||
@@ -2465,16 +2466,21 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
.run()
|
||||
}
|
||||
is PnpOperation.Merge -> {
|
||||
merge(operation.primaryId, operation.secondaryId, inputPni)
|
||||
val mergeResult: MergeResult = merge(operation.primaryId, operation.secondaryId, inputPni)
|
||||
hadThreadMerge = hadThreadMerge || mergeResult.neededThreadMerge
|
||||
}
|
||||
is PnpOperation.SessionSwitchoverInsert -> {
|
||||
val threadId: Long? = threads.getThreadIdFor(operation.recipientId)
|
||||
if (threadId != null) {
|
||||
val event = SessionSwitchoverEvent
|
||||
.newBuilder()
|
||||
.setE164(operation.e164 ?: "")
|
||||
.build()
|
||||
SignalDatabase.messages.insertSessionSwitchoverEvent(operation.recipientId, threadId, event)
|
||||
if (hadThreadMerge) {
|
||||
Log.d(TAG, "Skipping SSE insert because we already had a thread merge event.")
|
||||
} else {
|
||||
val threadId: Long? = threads.getThreadIdFor(operation.recipientId)
|
||||
if (threadId != null) {
|
||||
val event = SessionSwitchoverEvent
|
||||
.newBuilder()
|
||||
.setE164(operation.e164 ?: "")
|
||||
.build()
|
||||
SignalDatabase.messages.insertSessionSwitchoverEvent(operation.recipientId, threadId, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
is PnpOperation.ChangeNumberInsert -> {
|
||||
@@ -2622,6 +2628,14 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
)
|
||||
}
|
||||
|
||||
if (!pniVerified && fullData.pniSidRecord != null && finalData.aciSidRecord != null && sessions.hasAnySessionFor(fullData.pniSidRecord.serviceId.toString())) {
|
||||
breadCrumbs += "FinalUpdateSSE"
|
||||
operations += PnpOperation.SessionSwitchoverInsert(
|
||||
recipientId = primaryId,
|
||||
e164 = finalData.e164
|
||||
)
|
||||
}
|
||||
|
||||
return PnpChangeSet(
|
||||
id = PnpIdResolver.PnpNoopId(primaryId),
|
||||
operations = operations,
|
||||
@@ -3644,7 +3658,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
* Merges one ACI recipient with an E164 recipient. It is assumed that the E164 recipient does
|
||||
* *not* have an ACI.
|
||||
*/
|
||||
private fun merge(primaryId: RecipientId, secondaryId: RecipientId, newPni: PNI? = null): RecipientId {
|
||||
private fun merge(primaryId: RecipientId, secondaryId: RecipientId, newPni: PNI? = null): MergeResult {
|
||||
ensureInTransaction()
|
||||
val db = writableDatabase
|
||||
val primaryRecord = getRecord(primaryId)
|
||||
@@ -3656,7 +3670,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
}
|
||||
|
||||
// Threads
|
||||
val threadMerge = threads.merge(primaryId, secondaryId)
|
||||
val threadMerge: ThreadTable.MergeResult = threads.merge(primaryId, secondaryId)
|
||||
threads.setLastScrolled(threadMerge.threadId, 0)
|
||||
threads.update(threadMerge.threadId, false, false)
|
||||
|
||||
@@ -3721,7 +3735,11 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
}
|
||||
|
||||
db.update(TABLE_NAME, uuidValues, ID_WHERE, SqlUtil.buildArgs(primaryId))
|
||||
return primaryId
|
||||
|
||||
return MergeResult(
|
||||
finalId = primaryId,
|
||||
neededThreadMerge = threadMerge.neededMerge
|
||||
)
|
||||
}
|
||||
|
||||
private fun ensureInTransaction() {
|
||||
@@ -3845,6 +3863,8 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
* get them back through CDS).
|
||||
*/
|
||||
fun debugClearServiceIds(recipientId: RecipientId? = null) {
|
||||
check(FeatureFlags.internalUser())
|
||||
|
||||
writableDatabase
|
||||
.update(TABLE_NAME)
|
||||
.values(
|
||||
@@ -3868,6 +3888,8 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
* Should only be used for debugging! A very destructive action that clears all known profile keys and credentials.
|
||||
*/
|
||||
fun debugClearProfileData(recipientId: RecipientId? = null) {
|
||||
check(FeatureFlags.internalUser())
|
||||
|
||||
writableDatabase
|
||||
.update(TABLE_NAME)
|
||||
.values(
|
||||
@@ -3896,6 +3918,8 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
* Should only be used for debugging! Clears the E164 and PNI from a recipient.
|
||||
*/
|
||||
fun debugClearE164AndPni(recipientId: RecipientId) {
|
||||
check(FeatureFlags.internalUser())
|
||||
|
||||
writableDatabase
|
||||
.update(TABLE_NAME)
|
||||
.values(
|
||||
@@ -3905,7 +3929,28 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
.where(ID_WHERE, recipientId)
|
||||
.run()
|
||||
|
||||
Recipient.live(recipientId).refresh()
|
||||
ApplicationDependencies.getRecipientCache().clear()
|
||||
RecipientId.clearCache()
|
||||
}
|
||||
|
||||
/**
|
||||
* Should only be used for debugging! Clears the ACI from a contact.
|
||||
* Only works if the recipient has a PNI.
|
||||
*/
|
||||
fun debugRemoveAci(recipientId: RecipientId) {
|
||||
check(FeatureFlags.internalUser())
|
||||
|
||||
writableDatabase.execSQL(
|
||||
"""
|
||||
UPDATE $TABLE_NAME
|
||||
SET $SERVICE_ID = $PNI_COLUMN
|
||||
WHERE $ID = ? AND $PNI_COLUMN NOT NULL
|
||||
""".toSingleLine(),
|
||||
SqlUtil.buildArgs(recipientId)
|
||||
)
|
||||
|
||||
ApplicationDependencies.getRecipientCache().clear()
|
||||
RecipientId.clearCache()
|
||||
}
|
||||
|
||||
fun getRecord(context: Context, cursor: Cursor): RecipientRecord {
|
||||
@@ -4131,6 +4176,11 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
)
|
||||
}
|
||||
|
||||
private data class MergeResult(
|
||||
val finalId: RecipientId,
|
||||
val neededThreadMerge: Boolean
|
||||
)
|
||||
|
||||
inner class BulkOperationsHandle internal constructor(private val database: SQLiteDatabase) {
|
||||
private val pendingRecipients: MutableSet<RecipientId> = mutableSetOf()
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileChangeDetails;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.SessionSwitchoverEvent;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource;
|
||||
import org.thoughtcrime.securesms.emoji.JumboEmoji;
|
||||
@@ -235,6 +236,18 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
} else if (isSessionSwitchoverEventType()) {
|
||||
try {
|
||||
SessionSwitchoverEvent event = SessionSwitchoverEvent.parseFrom(Base64.decodeOrThrow(getBody()));
|
||||
|
||||
if (event.getE164().isEmpty()) {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_16);
|
||||
} else {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_belongs_to_s, PhoneNumberFormatter.prettyPrint(r.requireE164()), r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
}
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
} else if (isSmsExportType()) {
|
||||
int messageResource = SignalStore.misc().getSmsExportPhase().isSmsSupported() ? R.string.MessageRecord__you_will_no_longer_be_able_to_send_sms_messages_from_signal_soon
|
||||
: R.string.MessageRecord__you_can_no_longer_send_sms_messages_in_signal;
|
||||
@@ -551,6 +564,10 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return MessageTypes.isThreadMergeType(type);
|
||||
}
|
||||
|
||||
public boolean isSessionSwitchoverEventType() {
|
||||
return MessageTypes.isSessionSwitchoverType(type);
|
||||
}
|
||||
|
||||
public boolean isSmsExportType() {
|
||||
return MessageTypes.isSmsExport(type);
|
||||
}
|
||||
@@ -575,7 +592,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
|
||||
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() ||
|
||||
isProfileChange() || isGroupV1MigrationEvent() || isChatSessionRefresh() || isBadDecryptType() ||
|
||||
isChangeNumber() || isBoostRequest() || isThreadMergeEventType() || isSmsExportType() ||
|
||||
isChangeNumber() || isBoostRequest() || isThreadMergeEventType() || isSmsExportType() || isSessionSwitchoverEventType() ||
|
||||
isPaymentsRequestToActivate() || isPaymentsActivated();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user