mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-25 05:27:42 +00:00
Fix group update item bugs caused by backup support changes.
This commit is contained in:
committed by
Alex Hart
parent
347005bec6
commit
dfdb8f699a
@@ -103,6 +103,8 @@ import org.thoughtcrime.securesms.database.model.StoryType
|
||||
import org.thoughtcrime.securesms.database.model.StoryType.Companion.fromCode
|
||||
import org.thoughtcrime.securesms.database.model.StoryViewState
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GV2UpdateDescription
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExportState
|
||||
@@ -3817,20 +3819,25 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val secondLatestMessage = reader.getNext()
|
||||
|
||||
val id: Long
|
||||
val encodedBody: String
|
||||
val updatedContext: DecryptedGroupV2Context
|
||||
val messageExtras: MessageExtras?
|
||||
val changeRevision: Int = message.groupContext?.let { GroupV2UpdateMessageUtil.getChangeRevision(it) } ?: -1
|
||||
|
||||
if (secondLatestMessage != null && secondLatestMessage.isGroupV2JoinRequest(changeEditor.get())) {
|
||||
id = secondLatestMessage.id
|
||||
encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(secondLatestMessage, changeRevision, changeEditor.get().toByteString())
|
||||
messageExtras = secondLatestMessage.messageExtras
|
||||
updatedContext = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(secondLatestMessage, changeRevision, changeEditor.get().toByteString())
|
||||
deleteMessage(latestMessage.id)
|
||||
} else {
|
||||
id = latestMessage.id
|
||||
encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(latestMessage, changeRevision, changeEditor.get().toByteString())
|
||||
messageExtras = latestMessage.messageExtras
|
||||
updatedContext = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(latestMessage, changeRevision, changeEditor.get().toByteString())
|
||||
}
|
||||
|
||||
val updatedMessageExtras = (messageExtras?.newBuilder() ?: MessageExtras.Builder()).gv2UpdateDescription(GV2UpdateDescription(gv2ChangeDescription = updatedContext)).build()
|
||||
|
||||
db.update(TABLE_NAME)
|
||||
.values(BODY to encodedBody)
|
||||
.values(MESSAGE_EXTRAS to updatedMessageExtras.encode())
|
||||
.where("$ID = ?", id)
|
||||
.run()
|
||||
|
||||
|
||||
@@ -24,12 +24,10 @@ import android.text.style.RelativeSizeSpan;
|
||||
import android.text.style.StyleSpan;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.compose.ui.text.AnnotatedString;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
@@ -40,6 +38,8 @@ import org.signal.core.util.logging.Log;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate;
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupCreationUpdate;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.parsing.EmojiParser;
|
||||
import org.thoughtcrime.securesms.components.transfercontrols.TransferControlView;
|
||||
@@ -55,9 +55,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.SessionSwitchove
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource;
|
||||
import org.thoughtcrime.securesms.emoji.JumboEmoji;
|
||||
import org.thoughtcrime.securesms.fonts.SignalSymbols;
|
||||
import org.thoughtcrime.securesms.fonts.SignalSymbols.Glyph;
|
||||
import org.thoughtcrime.securesms.fonts.SignalSymbols.Weight;
|
||||
import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
@@ -305,12 +303,22 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
public boolean isSelfCreatedGroup() {
|
||||
DecryptedGroupV2Context decryptedGroupV2Context = getDecryptedGroupV2Context();
|
||||
|
||||
if (decryptedGroupV2Context == null) {
|
||||
return false;
|
||||
}
|
||||
DecryptedGroupChange change = decryptedGroupV2Context.change;
|
||||
if (decryptedGroupV2Context != null) {
|
||||
DecryptedGroupChange change = decryptedGroupV2Context.change;
|
||||
|
||||
return selfCreatedGroup(change);
|
||||
return selfCreatedGroup(change);
|
||||
}
|
||||
|
||||
GroupChangeChatUpdate groupChangeChatUpdate = getGroupChangeChatUpdate();
|
||||
if (groupChangeChatUpdate != null) {
|
||||
GroupCreationUpdate update = groupChangeChatUpdate.updates.stream().filter(u -> u.groupCreationUpdate != null).map(u -> u.groupCreationUpdate).findFirst().orElse(null);
|
||||
|
||||
return update != null &&
|
||||
update.updaterAci != null &&
|
||||
update.updaterAci.equals(SignalStore.account().requireAci().toByteString());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public @Nullable MessageExtras getMessageExtras() {
|
||||
@@ -343,6 +351,18 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return decryptedGroupV2Context;
|
||||
}
|
||||
|
||||
private @Nullable GroupChangeChatUpdate getGroupChangeChatUpdate() {
|
||||
if (!isGroupUpdate() || !isGroupV2()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (messageExtras != null && messageExtras.gv2UpdateDescription != null) {
|
||||
return messageExtras.gv2UpdateDescription.groupChangeUpdate;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean selfCreatedGroup(@Nullable DecryptedGroupChange change) {
|
||||
return change != null &&
|
||||
change.revision == 0 &&
|
||||
@@ -552,6 +572,12 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
if (decryptedGroupV2Context != null) {
|
||||
return decryptedGroupV2Context.change != null && decryptedGroupV2Context.change.newDescription != null;
|
||||
}
|
||||
|
||||
GroupChangeChatUpdate updates = getGroupChangeChatUpdate();
|
||||
if (updates != null) {
|
||||
return updates.updates.stream().anyMatch(update -> update.groupDescriptionUpdate != null);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -560,6 +586,15 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
if (decryptedGroupV2Context != null && decryptedGroupV2Context.change != null) {
|
||||
return decryptedGroupV2Context.change.newDescription != null ? decryptedGroupV2Context.change.newDescription.value_ : "";
|
||||
}
|
||||
|
||||
GroupChangeChatUpdate updates = getGroupChangeChatUpdate();
|
||||
if (updates != null) {
|
||||
return updates.updates.stream()
|
||||
.filter(u -> u.groupDescriptionUpdate != null)
|
||||
.map(u -> u.groupDescriptionUpdate.newDescription)
|
||||
.findFirst()
|
||||
.orElse("");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -594,7 +629,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static @NonNull String createNewContextWithAppendedDeleteJoinRequest(@NonNull MessageRecord messageRecord, int revision, @NonNull ByteString id) {
|
||||
public static @NonNull DecryptedGroupV2Context createNewContextWithAppendedDeleteJoinRequest(@NonNull MessageRecord messageRecord, int revision, @NonNull ByteString id) {
|
||||
DecryptedGroupV2Context decryptedGroupV2Context = messageRecord.getDecryptedGroupV2Context();
|
||||
|
||||
if (decryptedGroupV2Context != null && decryptedGroupV2Context.change != null) {
|
||||
@@ -603,13 +638,12 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
List<ByteString> deleteRequestingMembers = new ArrayList<>(change.deleteRequestingMembers);
|
||||
deleteRequestingMembers.add(id);
|
||||
|
||||
return Base64.encodeWithPadding(decryptedGroupV2Context.newBuilder()
|
||||
.change(change.newBuilder()
|
||||
.revision(revision)
|
||||
.deleteRequestingMembers(deleteRequestingMembers)
|
||||
.build())
|
||||
.build()
|
||||
.encode());
|
||||
return decryptedGroupV2Context.newBuilder()
|
||||
.change(change.newBuilder()
|
||||
.revision(revision)
|
||||
.deleteRequestingMembers(deleteRequestingMembers)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
throw new AssertionError("Attempting to modify a message with no change");
|
||||
|
||||
@@ -36,11 +36,11 @@ private fun DecryptedGroup.formatAsHtml(): String {
|
||||
return """
|
||||
Revision: $revision
|
||||
Title: $title
|
||||
Avatar: ${(avatar?.length ?: 0) != 0}
|
||||
Timer: ${disappearingMessagesTimer!!.duration}
|
||||
Avatar: ${(avatar.length) != 0}
|
||||
Timer: ${disappearingMessagesTimer?.duration}
|
||||
Description: "$description"
|
||||
Announcement: $isAnnouncementGroup
|
||||
Access: attributes(${accessControl!!.attributes}) members(${accessControl!!.members}) link(${accessControl!!.addFromInviteLink})
|
||||
Access: attributes(${accessControl?.attributes}) members(${accessControl?.members}) link(${accessControl?.addFromInviteLink})
|
||||
Members: $members
|
||||
Pending: $pending
|
||||
Requesting: $requesting
|
||||
|
||||
@@ -50,7 +50,9 @@ object GV2UpdateTransformer : ColumnTransformer {
|
||||
private fun messageExtrasGroupUpdate(messageExtras: MessageExtras): String {
|
||||
val gv2ChangeDescription: UpdateDescription = MessageRecord.getGv2ChangeDescription(AppDependencies.application, messageExtras, null)
|
||||
|
||||
return "${gv2ChangeDescription.spannable}<br><br>${messageExtras.gv2UpdateDescription!!.gv2ChangeDescription!!.change}"
|
||||
val gv2ChangeProto: Any? = messageExtras.gv2UpdateDescription?.gv2ChangeDescription?.change ?: messageExtras.gv2UpdateDescription?.groupChangeUpdate
|
||||
|
||||
return "${gv2ChangeDescription.spannable}<br><br>$gv2ChangeProto"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import okio.ByteString
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.signal.core.util.Base64
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context
|
||||
import org.thoughtcrime.securesms.groups.v2.ChangeBuilder
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
@@ -65,9 +64,7 @@ class MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest {
|
||||
every { decryptedGroupV2Context } returns context
|
||||
}
|
||||
|
||||
val newEncodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(messageRecord, 10, aliceByteString)
|
||||
|
||||
val newContext = DecryptedGroupV2Context.ADAPTER.decode(Base64.decode(newEncodedBody))
|
||||
val newContext = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(messageRecord, 10, aliceByteString)
|
||||
|
||||
assertEquals("revision updated to 10", newContext.change?.revision, 10)
|
||||
assertEquals("change should retain join request", newContext.change?.newRequestingMembers?.single()?.aciBytes, aliceByteString)
|
||||
|
||||
@@ -350,6 +350,7 @@ internal class SpinnerServer(
|
||||
try {
|
||||
row += transformers[i].transform(null, columnName, this)
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Failed to transform", e)
|
||||
row += "*Failed to Transform*\n\n${DefaultColumnTransformer.transform(null, columnName, this)}"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user