Add support for import/export of shared contact messages.
This commit is contained in:
parent
84515482a6
commit
058c523329
5 changed files with 243 additions and 20 deletions
|
@ -25,6 +25,8 @@ import org.thoughtcrime.securesms.attachments.DatabaseAttachment
|
||||||
import org.thoughtcrime.securesms.backup.v2.BackupRepository.getMediaName
|
import org.thoughtcrime.securesms.backup.v2.BackupRepository.getMediaName
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatItem
|
import org.thoughtcrime.securesms.backup.v2.proto.ChatItem
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatUpdateMessage
|
import org.thoughtcrime.securesms.backup.v2.proto.ChatUpdateMessage
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.proto.ContactAttachment
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.proto.ContactMessage
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.ExpirationTimerChatUpdate
|
import org.thoughtcrime.securesms.backup.v2.proto.ExpirationTimerChatUpdate
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
|
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupCall
|
import org.thoughtcrime.securesms.backup.v2.proto.GroupCall
|
||||||
|
@ -44,6 +46,7 @@ import org.thoughtcrime.securesms.backup.v2.proto.Sticker
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.StickerMessage
|
import org.thoughtcrime.securesms.backup.v2.proto.StickerMessage
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.Text
|
import org.thoughtcrime.securesms.backup.v2.proto.Text
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.ThreadMergeChatUpdate
|
import org.thoughtcrime.securesms.backup.v2.proto.ThreadMergeChatUpdate
|
||||||
|
import org.thoughtcrime.securesms.contactshare.Contact
|
||||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||||
import org.thoughtcrime.securesms.database.CallTable
|
import org.thoughtcrime.securesms.database.CallTable
|
||||||
import org.thoughtcrime.securesms.database.GroupReceiptTable
|
import org.thoughtcrime.securesms.database.GroupReceiptTable
|
||||||
|
@ -198,6 +201,9 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
|
||||||
MessageTypes.isGiftBadge(record.type) -> {
|
MessageTypes.isGiftBadge(record.type) -> {
|
||||||
builder.giftBadge = record.toGiftBadgeUpdate()
|
builder.giftBadge = record.toGiftBadgeUpdate()
|
||||||
}
|
}
|
||||||
|
!record.sharedContacts.isNullOrEmpty() -> {
|
||||||
|
builder.contactMessage = record.toContactMessage(reactionsById[id], attachmentsById[id])
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
if (record.body == null && !attachmentsById.containsKey(record.id)) {
|
if (record.body == null && !attachmentsById.containsKey(record.id)) {
|
||||||
Log.w(TAG, "Record with ID ${record.id} missing a body and doesn't have attachments. Skipping.")
|
Log.w(TAG, "Record with ID ${record.id} missing a body and doesn't have attachments. Skipping.")
|
||||||
|
@ -490,6 +496,45 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun BackupMessageRecord.parseSharedContacts(attachments: List<DatabaseAttachment>?): List<Contact> {
|
||||||
|
if (this.sharedContacts.isNullOrEmpty()) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val attachmentIdMap: Map<AttachmentId, DatabaseAttachment> = attachments?.associateBy { it.attachmentId } ?: emptyMap()
|
||||||
|
|
||||||
|
try {
|
||||||
|
val contacts: MutableList<Contact> = LinkedList()
|
||||||
|
val jsonContacts = JSONArray(sharedContacts)
|
||||||
|
|
||||||
|
for (i in 0 until jsonContacts.length()) {
|
||||||
|
val contact: Contact = Contact.deserialize(jsonContacts.getJSONObject(i).toString())
|
||||||
|
|
||||||
|
if (contact.avatar != null && contact.avatar!!.attachmentId != null) {
|
||||||
|
val attachment = attachmentIdMap[contact.avatar!!.attachmentId]
|
||||||
|
|
||||||
|
val updatedAvatar = Contact.Avatar(
|
||||||
|
contact.avatar!!.attachmentId,
|
||||||
|
attachment,
|
||||||
|
contact.avatar!!.isProfile
|
||||||
|
)
|
||||||
|
|
||||||
|
contacts += Contact(contact, updatedAvatar)
|
||||||
|
} else {
|
||||||
|
contacts += contact
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return contacts
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
Log.w(TAG, "Failed to parse shared contacts.", e)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.w(TAG, "Failed to parse shared contacts.", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
private fun BackupMessageRecord.parseLinkPreviews(attachments: List<DatabaseAttachment>?): List<LinkPreview> {
|
private fun BackupMessageRecord.parseLinkPreviews(attachments: List<DatabaseAttachment>?): List<LinkPreview> {
|
||||||
if (linkPreview.isNullOrEmpty()) {
|
if (linkPreview.isNullOrEmpty()) {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
|
@ -536,6 +581,86 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun BackupMessageRecord.toContactMessage(reactionRecords: List<ReactionRecord>?, attachments: List<DatabaseAttachment>?): ContactMessage {
|
||||||
|
val sharedContacts = parseSharedContacts(attachments)
|
||||||
|
|
||||||
|
val contacts = sharedContacts.map {
|
||||||
|
ContactAttachment(
|
||||||
|
name = it.name.toBackup(),
|
||||||
|
avatar = (it.avatar?.attachment as? DatabaseAttachment)?.toBackupAttachment()?.pointer,
|
||||||
|
organization = it.organization,
|
||||||
|
number = it.phoneNumbers.map { phone ->
|
||||||
|
ContactAttachment.Phone(
|
||||||
|
value_ = phone.number,
|
||||||
|
type = phone.type.toBackup(),
|
||||||
|
label = phone.label
|
||||||
|
)
|
||||||
|
},
|
||||||
|
email = it.emails.map { email ->
|
||||||
|
ContactAttachment.Email(
|
||||||
|
value_ = email.email,
|
||||||
|
label = email.label,
|
||||||
|
type = email.type.toBackup()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
address = it.postalAddresses.map { address ->
|
||||||
|
ContactAttachment.PostalAddress(
|
||||||
|
type = address.type.toBackup(),
|
||||||
|
label = address.label,
|
||||||
|
street = address.street,
|
||||||
|
pobox = address.poBox,
|
||||||
|
neighborhood = address.neighborhood,
|
||||||
|
city = address.city,
|
||||||
|
region = address.region,
|
||||||
|
postcode = address.postalCode,
|
||||||
|
country = address.country
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return ContactMessage(
|
||||||
|
contact = contacts,
|
||||||
|
reactions = reactionRecords.toBackupReactions()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Contact.Name.toBackup(): ContactAttachment.Name {
|
||||||
|
return ContactAttachment.Name(
|
||||||
|
givenName = givenName,
|
||||||
|
familyName = familyName,
|
||||||
|
prefix = prefix,
|
||||||
|
suffix = suffix,
|
||||||
|
middleName = middleName,
|
||||||
|
displayName = displayName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Contact.Phone.Type.toBackup(): ContactAttachment.Phone.Type {
|
||||||
|
return when (this) {
|
||||||
|
Contact.Phone.Type.HOME -> ContactAttachment.Phone.Type.HOME
|
||||||
|
Contact.Phone.Type.MOBILE -> ContactAttachment.Phone.Type.MOBILE
|
||||||
|
Contact.Phone.Type.WORK -> ContactAttachment.Phone.Type.WORK
|
||||||
|
Contact.Phone.Type.CUSTOM -> ContactAttachment.Phone.Type.CUSTOM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Contact.Email.Type.toBackup(): ContactAttachment.Email.Type {
|
||||||
|
return when (this) {
|
||||||
|
Contact.Email.Type.HOME -> ContactAttachment.Email.Type.HOME
|
||||||
|
Contact.Email.Type.MOBILE -> ContactAttachment.Email.Type.MOBILE
|
||||||
|
Contact.Email.Type.WORK -> ContactAttachment.Email.Type.WORK
|
||||||
|
Contact.Email.Type.CUSTOM -> ContactAttachment.Email.Type.CUSTOM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Contact.PostalAddress.Type.toBackup(): ContactAttachment.PostalAddress.Type {
|
||||||
|
return when (this) {
|
||||||
|
Contact.PostalAddress.Type.HOME -> ContactAttachment.PostalAddress.Type.HOME
|
||||||
|
Contact.PostalAddress.Type.WORK -> ContactAttachment.PostalAddress.Type.WORK
|
||||||
|
Contact.PostalAddress.Type.CUSTOM -> ContactAttachment.PostalAddress.Type.CUSTOM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun BackupMessageRecord.toStandardMessage(reactionRecords: List<ReactionRecord>?, mentions: List<Mention>?, attachments: List<DatabaseAttachment>?): StandardMessage {
|
private fun BackupMessageRecord.toStandardMessage(reactionRecords: List<ReactionRecord>?, mentions: List<Mention>?, attachments: List<DatabaseAttachment>?): StandardMessage {
|
||||||
val text = if (body == null) {
|
val text = if (body == null) {
|
||||||
null
|
null
|
||||||
|
@ -545,10 +670,13 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
|
||||||
bodyRanges = (this.bodyRanges?.toBackupBodyRanges() ?: emptyList()) + (mentions?.toBackupBodyRanges() ?: emptyList())
|
bodyRanges = (this.bodyRanges?.toBackupBodyRanges() ?: emptyList()) + (mentions?.toBackupBodyRanges() ?: emptyList())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val linkPreviews = this.parseLinkPreviews(attachments)
|
val linkPreviews = parseLinkPreviews(attachments)
|
||||||
val linkPreviewAttachments = linkPreviews.mapNotNull { it.thumbnail.orElse(null) }.toSet()
|
val linkPreviewAttachments = linkPreviews.mapNotNull { it.thumbnail.orElse(null) }.toSet()
|
||||||
val quotedAttachments = attachments?.filter { it.quote && !linkPreviewAttachments.contains(it) } ?: emptyList()
|
val quotedAttachments = attachments?.filter { it.quote } ?: emptyList()
|
||||||
val messageAttachments = attachments?.filter { !it.quote && !linkPreviewAttachments.contains(it) } ?: emptyList()
|
val messageAttachments = attachments
|
||||||
|
?.filterNot { it.quote }
|
||||||
|
?.filterNot { linkPreviewAttachments.contains(it) }
|
||||||
|
?: emptyList()
|
||||||
return StandardMessage(
|
return StandardMessage(
|
||||||
quote = this.toQuote(quotedAttachments),
|
quote = this.toQuote(quotedAttachments),
|
||||||
text = text,
|
text = text,
|
||||||
|
@ -898,6 +1026,7 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
|
||||||
remoteDeleted = this.requireBoolean(MessageTable.REMOTE_DELETED),
|
remoteDeleted = this.requireBoolean(MessageTable.REMOTE_DELETED),
|
||||||
sealedSender = this.requireBoolean(MessageTable.UNIDENTIFIED),
|
sealedSender = this.requireBoolean(MessageTable.UNIDENTIFIED),
|
||||||
linkPreview = this.requireString(MessageTable.LINK_PREVIEWS),
|
linkPreview = this.requireString(MessageTable.LINK_PREVIEWS),
|
||||||
|
sharedContacts = this.requireString(MessageTable.SHARED_CONTACTS),
|
||||||
quoteTargetSentTimestamp = this.requireLong(MessageTable.QUOTE_ID),
|
quoteTargetSentTimestamp = this.requireLong(MessageTable.QUOTE_ID),
|
||||||
quoteAuthor = this.requireLong(MessageTable.QUOTE_AUTHOR),
|
quoteAuthor = this.requireLong(MessageTable.QUOTE_AUTHOR),
|
||||||
quoteBody = this.requireString(MessageTable.QUOTE_BODY),
|
quoteBody = this.requireString(MessageTable.QUOTE_BODY),
|
||||||
|
@ -934,6 +1063,7 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
|
||||||
val remoteDeleted: Boolean,
|
val remoteDeleted: Boolean,
|
||||||
val sealedSender: Boolean,
|
val sealedSender: Boolean,
|
||||||
val linkPreview: String?,
|
val linkPreview: String?,
|
||||||
|
val sharedContacts: String?,
|
||||||
val quoteTargetSentTimestamp: Long,
|
val quoteTargetSentTimestamp: Long,
|
||||||
val quoteAuthor: Long,
|
val quoteAuthor: Long,
|
||||||
val quoteBody: String?,
|
val quoteBody: String?,
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.thoughtcrime.securesms.backup.v2.BackupState
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.BodyRange
|
import org.thoughtcrime.securesms.backup.v2.proto.BodyRange
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatItem
|
import org.thoughtcrime.securesms.backup.v2.proto.ChatItem
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.ChatUpdateMessage
|
import org.thoughtcrime.securesms.backup.v2.proto.ChatUpdateMessage
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.proto.ContactAttachment
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
|
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupCall
|
import org.thoughtcrime.securesms.backup.v2.proto.GroupCall
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.IndividualCall
|
import org.thoughtcrime.securesms.backup.v2.proto.IndividualCall
|
||||||
|
@ -36,6 +37,7 @@ import org.thoughtcrime.securesms.backup.v2.proto.SendStatus
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.SimpleChatUpdate
|
import org.thoughtcrime.securesms.backup.v2.proto.SimpleChatUpdate
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.StandardMessage
|
import org.thoughtcrime.securesms.backup.v2.proto.StandardMessage
|
||||||
import org.thoughtcrime.securesms.backup.v2.proto.Sticker
|
import org.thoughtcrime.securesms.backup.v2.proto.Sticker
|
||||||
|
import org.thoughtcrime.securesms.contactshare.Contact
|
||||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||||
import org.thoughtcrime.securesms.database.CallTable
|
import org.thoughtcrime.securesms.database.CallTable
|
||||||
import org.thoughtcrime.securesms.database.GroupReceiptTable
|
import org.thoughtcrime.securesms.database.GroupReceiptTable
|
||||||
|
@ -316,6 +318,60 @@ class ChatItemImportInserter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.contactMessage != null) {
|
||||||
|
val contacts = this.contactMessage.contact.map { backupContact ->
|
||||||
|
Contact(
|
||||||
|
backupContact.name.toLocal(),
|
||||||
|
backupContact.organization,
|
||||||
|
backupContact.number.map { phone ->
|
||||||
|
Contact.Phone(
|
||||||
|
phone.value_ ?: "",
|
||||||
|
phone.type.toLocal(),
|
||||||
|
phone.label
|
||||||
|
)
|
||||||
|
},
|
||||||
|
backupContact.email.map { email ->
|
||||||
|
Contact.Email(
|
||||||
|
email.value_ ?: "",
|
||||||
|
email.type.toLocal(),
|
||||||
|
email.label
|
||||||
|
)
|
||||||
|
},
|
||||||
|
backupContact.address.map { address ->
|
||||||
|
Contact.PostalAddress(
|
||||||
|
address.type.toLocal(),
|
||||||
|
address.label,
|
||||||
|
address.street,
|
||||||
|
address.pobox,
|
||||||
|
address.neighborhood,
|
||||||
|
address.city,
|
||||||
|
address.region,
|
||||||
|
address.postcode,
|
||||||
|
address.country
|
||||||
|
)
|
||||||
|
},
|
||||||
|
Contact.Avatar(null, backupContact.avatar.toLocalAttachment(voiceNote = false, borderless = false, gif = false, wasDownloaded = true), true)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val contactAttachments = contacts.mapNotNull { it.avatarAttachment }
|
||||||
|
if (contacts.isNotEmpty()) {
|
||||||
|
followUp = { messageRowId ->
|
||||||
|
val attachmentMap = if (contactAttachments.isNotEmpty()) {
|
||||||
|
SignalDatabase.attachments.insertAttachmentsForMessage(messageRowId, contactAttachments, emptyList())
|
||||||
|
} else {
|
||||||
|
emptyMap()
|
||||||
|
}
|
||||||
|
db.update(
|
||||||
|
MessageTable.TABLE_NAME,
|
||||||
|
contentValuesOf(
|
||||||
|
MessageTable.SHARED_CONTACTS to SignalDatabase.messages.getSerializedSharedContacts(attachmentMap, contacts)
|
||||||
|
),
|
||||||
|
"${MessageTable.ID} = ?",
|
||||||
|
SqlUtil.buildArgs(messageRowId)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.standardMessage != null) {
|
if (this.standardMessage != null) {
|
||||||
val bodyRanges = this.standardMessage.text?.bodyRanges
|
val bodyRanges = this.standardMessage.text?.bodyRanges
|
||||||
if (!bodyRanges.isNullOrEmpty()) {
|
if (!bodyRanges.isNullOrEmpty()) {
|
||||||
|
@ -963,6 +1019,42 @@ class ChatItemImportInserter(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ContactAttachment.Name?.toLocal(): Contact.Name {
|
||||||
|
return Contact.Name(this?.displayName, this?.givenName, this?.familyName, this?.prefix, this?.suffix, this?.middleName)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ContactAttachment.Phone.Type?.toLocal(): Contact.Phone.Type {
|
||||||
|
return when (this) {
|
||||||
|
ContactAttachment.Phone.Type.HOME -> Contact.Phone.Type.HOME
|
||||||
|
ContactAttachment.Phone.Type.MOBILE -> Contact.Phone.Type.MOBILE
|
||||||
|
ContactAttachment.Phone.Type.WORK -> Contact.Phone.Type.WORK
|
||||||
|
ContactAttachment.Phone.Type.CUSTOM,
|
||||||
|
ContactAttachment.Phone.Type.UNKNOWN,
|
||||||
|
null -> Contact.Phone.Type.CUSTOM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ContactAttachment.Email.Type?.toLocal(): Contact.Email.Type {
|
||||||
|
return when (this) {
|
||||||
|
ContactAttachment.Email.Type.HOME -> Contact.Email.Type.HOME
|
||||||
|
ContactAttachment.Email.Type.MOBILE -> Contact.Email.Type.MOBILE
|
||||||
|
ContactAttachment.Email.Type.WORK -> Contact.Email.Type.WORK
|
||||||
|
ContactAttachment.Email.Type.CUSTOM,
|
||||||
|
ContactAttachment.Email.Type.UNKNOWN,
|
||||||
|
null -> Contact.Email.Type.CUSTOM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ContactAttachment.PostalAddress.Type?.toLocal(): Contact.PostalAddress.Type {
|
||||||
|
return when (this) {
|
||||||
|
ContactAttachment.PostalAddress.Type.HOME -> Contact.PostalAddress.Type.HOME
|
||||||
|
ContactAttachment.PostalAddress.Type.WORK -> Contact.PostalAddress.Type.WORK
|
||||||
|
ContactAttachment.PostalAddress.Type.CUSTOM,
|
||||||
|
ContactAttachment.PostalAddress.Type.UNKNOWN,
|
||||||
|
null -> Contact.PostalAddress.Type.CUSTOM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun MessageAttachment.toLocalAttachment(contentType: String?, fileName: String?): Attachment? {
|
private fun MessageAttachment.toLocalAttachment(contentType: String?, fileName: String?): Attachment? {
|
||||||
return pointer?.toLocalAttachment(
|
return pointer?.toLocalAttachment(
|
||||||
voiceNote = flag == MessageAttachment.Flag.VOICE_MESSAGE,
|
voiceNote = flag == MessageAttachment.Flag.VOICE_MESSAGE,
|
||||||
|
|
|
@ -34,6 +34,7 @@ fun MessageTable.getMessagesForBackup(backupTime: Long, archiveMedia: Boolean):
|
||||||
MessageTable.REMOTE_DELETED,
|
MessageTable.REMOTE_DELETED,
|
||||||
MessageTable.UNIDENTIFIED,
|
MessageTable.UNIDENTIFIED,
|
||||||
MessageTable.LINK_PREVIEWS,
|
MessageTable.LINK_PREVIEWS,
|
||||||
|
MessageTable.SHARED_CONTACTS,
|
||||||
MessageTable.QUOTE_ID,
|
MessageTable.QUOTE_ID,
|
||||||
MessageTable.QUOTE_AUTHOR,
|
MessageTable.QUOTE_AUTHOR,
|
||||||
MessageTable.QUOTE_BODY,
|
MessageTable.QUOTE_BODY,
|
||||||
|
|
|
@ -160,7 +160,7 @@ public class Contact implements Parcelable {
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private final String middleName;
|
private final String middleName;
|
||||||
|
|
||||||
Name(@JsonProperty("displayName") @Nullable String displayName,
|
public Name(@JsonProperty("displayName") @Nullable String displayName,
|
||||||
@JsonProperty("givenName") @Nullable String givenName,
|
@JsonProperty("givenName") @Nullable String givenName,
|
||||||
@JsonProperty("familyName") @Nullable String familyName,
|
@JsonProperty("familyName") @Nullable String familyName,
|
||||||
@JsonProperty("prefix") @Nullable String prefix,
|
@JsonProperty("prefix") @Nullable String prefix,
|
||||||
|
@ -254,9 +254,9 @@ public class Contact implements Parcelable {
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private boolean selected;
|
private boolean selected;
|
||||||
|
|
||||||
Phone(@JsonProperty("number") @NonNull String number,
|
public Phone(@JsonProperty("number") @NonNull String number,
|
||||||
@JsonProperty("type") @NonNull Type type,
|
@JsonProperty("type") @NonNull Type type,
|
||||||
@JsonProperty("label") @Nullable String label)
|
@JsonProperty("label") @Nullable String label)
|
||||||
{
|
{
|
||||||
this.number = number;
|
this.number = number;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
@ -333,9 +333,9 @@ public class Contact implements Parcelable {
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private boolean selected;
|
private boolean selected;
|
||||||
|
|
||||||
Email(@JsonProperty("email") @NonNull String email,
|
public Email(@JsonProperty("email") @NonNull String email,
|
||||||
@JsonProperty("type") @NonNull Type type,
|
@JsonProperty("type") @NonNull Type type,
|
||||||
@JsonProperty("label") @Nullable String label)
|
@JsonProperty("label") @Nullable String label)
|
||||||
{
|
{
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
@ -430,15 +430,15 @@ public class Contact implements Parcelable {
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private boolean selected;
|
private boolean selected;
|
||||||
|
|
||||||
PostalAddress(@JsonProperty("type") @NonNull Type type,
|
public PostalAddress(@JsonProperty("type") @NonNull Type type,
|
||||||
@JsonProperty("label") @Nullable String label,
|
@JsonProperty("label") @Nullable String label,
|
||||||
@JsonProperty("street") @Nullable String street,
|
@JsonProperty("street") @Nullable String street,
|
||||||
@JsonProperty("poBox") @Nullable String poBox,
|
@JsonProperty("poBox") @Nullable String poBox,
|
||||||
@JsonProperty("neighborhood") @Nullable String neighborhood,
|
@JsonProperty("neighborhood") @Nullable String neighborhood,
|
||||||
@JsonProperty("city") @Nullable String city,
|
@JsonProperty("city") @Nullable String city,
|
||||||
@JsonProperty("region") @Nullable String region,
|
@JsonProperty("region") @Nullable String region,
|
||||||
@JsonProperty("postalCode") @Nullable String postalCode,
|
@JsonProperty("postalCode") @Nullable String postalCode,
|
||||||
@JsonProperty("country") @Nullable String country)
|
@JsonProperty("country") @Nullable String country)
|
||||||
{
|
{
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
|
|
@ -3339,7 +3339,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSerializedSharedContacts(insertedAttachmentIds: Map<Attachment, AttachmentId>, contacts: List<Contact>): String? {
|
fun getSerializedSharedContacts(insertedAttachmentIds: Map<Attachment, AttachmentId>, contacts: List<Contact>): String? {
|
||||||
if (contacts.isEmpty()) {
|
if (contacts.isEmpty()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue