From 8d6b8f39ce23241b4b4ce17a93d1266e4078a28e Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Wed, 15 Jan 2025 13:45:20 -0500 Subject: [PATCH] Add backup support for contact nicknames and notes. --- .../backupTests/account_data_01.binproto | Bin 478 -> 477 bytes .../backupTests/account_data_02.binproto | Bin 575 -> 574 bytes .../backupTests/account_data_04.binproto | Bin 497 -> 496 bytes .../backupTests/account_data_05.binproto | Bin 436 -> 435 bytes .../backupTests/account_data_07.binproto | Bin 386 -> 385 bytes .../backupTests/account_data_08.binproto | Bin 359 -> 358 bytes .../backupTests/account_data_10.binproto | Bin 410 -> 409 bytes .../backupTests/account_data_11.binproto | Bin 393 -> 392 bytes .../backupTests/account_data_13.binproto | Bin 385 -> 384 bytes .../backupTests/account_data_14.binproto | Bin 417 -> 416 bytes .../backupTests/account_data_16.binproto | Bin 352 -> 351 bytes .../backupTests/account_data_17.binproto | Bin 392 -> 391 bytes .../backupTests/account_data_19.binproto | Bin 386 -> 385 bytes .../backupTests/account_data_20.binproto | Bin 359 -> 358 bytes .../backupTests/account_data_22.binproto | Bin 410 -> 409 bytes .../backupTests/account_data_23.binproto | Bin 393 -> 392 bytes .../backupTests/account_data_25.binproto | Bin 385 -> 384 bytes .../backupTests/account_data_26.binproto | Bin 417 -> 416 bytes .../chat_item_simple_updates_09.binproto | Bin 550 -> 528 bytes .../chat_item_simple_updates_10.binproto | Bin 550 -> 528 bytes ...dard_message_with_link_preview_00.binproto | Bin 632 -> 630 bytes ...dard_message_with_link_preview_01.binproto | Bin 819 -> 817 bytes ...dard_message_with_link_preview_02.binproto | Bin 910 -> 908 bytes ...dard_message_with_link_preview_03.binproto | Bin 807 -> 805 bytes ...dard_message_with_link_preview_04.binproto | Bin 803 -> 801 bytes ...dard_message_with_link_preview_05.binproto | Bin 849 -> 847 bytes ...dard_message_with_link_preview_06.binproto | Bin 803 -> 801 bytes ...dard_message_with_link_preview_07.binproto | Bin 782 -> 780 bytes ...dard_message_with_link_preview_08.binproto | Bin 751 -> 749 bytes ...dard_message_with_link_preview_09.binproto | Bin 629 -> 627 bytes ...dard_message_with_link_preview_10.binproto | Bin 818 -> 816 bytes ...dard_message_with_link_preview_11.binproto | Bin 910 -> 908 bytes ...dard_message_with_link_preview_12.binproto | Bin 805 -> 803 bytes ...dard_message_with_link_preview_13.binproto | Bin 805 -> 803 bytes ...dard_message_with_link_preview_14.binproto | Bin 849 -> 847 bytes .../recipient_contacts_00.binproto | Bin 418 -> 428 bytes .../recipient_contacts_01.binproto | Bin 516 -> 556 bytes .../recipient_contacts_02.binproto | Bin 503 -> 552 bytes .../recipient_contacts_03.binproto | Bin 517 -> 540 bytes .../recipient_contacts_04.binproto | Bin 0 -> 440 bytes .../backupTests/recipient_groups_01.binproto | Bin 1496 -> 1495 bytes .../backupTests/recipient_groups_02.binproto | Bin 1454 -> 1453 bytes .../RecipientTableArchiveExtensions.kt | 3 + .../v2/exporters/ChatItemArchiveExporter.kt | 63 ++++++++---------- .../v2/exporters/ContactArchiveExporter.kt | 16 +++++ .../v2/importer/ChatItemArchiveImporter.kt | 12 ++-- .../v2/importer/ContactArchiveImporter.kt | 5 +- app/src/main/protowire/Backup.proto | 27 +++++++- 48 files changed, 83 insertions(+), 43 deletions(-) create mode 100644 app/src/androidTest/assets/backupTests/recipient_contacts_04.binproto diff --git a/app/src/androidTest/assets/backupTests/account_data_01.binproto b/app/src/androidTest/assets/backupTests/account_data_01.binproto index d377221e413072839a82677639ddb0a38eb2d0bb..c35b0efd0866d352515a84e3d17ef626337c7f69 100644 GIT binary patch delta 38 ucmcb|e3yBGAIl>quKN>%%7mpdN=gcft@QPaGt=`DbM*3y(l_2=Vgvvi;|@ju delta 39 vcmcc1e2;m8AIoDVt_Kr?%0#3yN=gcft@QO%D-v@Ha#Hn@^K&=eW?}>YD;y54 diff --git a/app/src/androidTest/assets/backupTests/account_data_02.binproto b/app/src/androidTest/assets/backupTests/account_data_02.binproto index cde12d0e3a7e000d4cd108a4daf97692e41695eb..9e1ae760de01352f68f48bc14b9596b489f7b661 100644 GIT binary patch delta 38 ucmdnbvX5ngAIo88t^*T;Dufj>N=gcft@QPaGt=`DbM*3y(l_2qWCQ>Wt`0T; delta 39 vcmdnTvY%ywAIlMDu7eYUDnt}BN=gcft@QO%D-v@Ha#Hn@^K&=eO=JWB9Ci+# diff --git a/app/src/androidTest/assets/backupTests/account_data_04.binproto b/app/src/androidTest/assets/backupTests/account_data_04.binproto index 518cada9f14b79c13d37a355b45f57ec7eb3eabd..8034235838ee59dc815869b0be4b36f1d8b7a2a5 100644 GIT binary patch delta 38 ucmey!{DFCbAIn!Ju1^z#(uJimN=gcft@QPaGt=`DbM*3y(l?$}VFUmqVh)x7 delta 39 vcmeys{E>NrAImo;uFn&L(nX{*N=gcft@QO%D-v@Ha#Hn@^K&Atr2y>l4Z;8b diff --git a/app/src/androidTest/assets/backupTests/account_data_08.binproto b/app/src/androidTest/assets/backupTests/account_data_08.binproto index 5b8f37e5b691f8ab88453364a10d4314778115a3..f0a2957dd4da1def829635847a8b33a857a1f53f 100644 GIT binary patch delta 37 tcmaFP^o(hOAIob-t``%7(uEZ=N=gcft@QPaGt=`DbM*3y(kGss1ppBF4#ofg delta 38 ucmaFH^qgseAIlp?u9p*o(nSk delta 38 tcmeBR?qr_e$I{2d)jct&TtqRWq@AtH30D?4eI~^ diff --git a/app/src/androidTest/assets/backupTests/account_data_13.binproto b/app/src/androidTest/assets/backupTests/account_data_13.binproto index 4e7a218b5aa027d67b2b5dee2453cc208d585baf..8c3fc91d8fccbda385aabeacd4de3ff572970786 100644 GIT binary patch delta 37 scmZoBor2yN=gcft@QPaGt=`DbM*3y(kI?K3;^%y4g3HA delta 38 ucmZ3$ypVZZ)j2V!OjseKq@BoH30C14dnm; diff --git a/app/src/androidTest/assets/backupTests/account_data_19.binproto b/app/src/androidTest/assets/backupTests/account_data_19.binproto index a25173823d8c29d73bf429852e6d76b841d2cb8c..13ab22f66e4e79f9176c00458e26c83c9c3b9cc5 100644 GIT binary patch delta 37 scmZo-Ze*U|$I`~c)jTn%Tv#fjq@Atr2y>l4Z;8b diff --git a/app/src/androidTest/assets/backupTests/account_data_20.binproto b/app/src/androidTest/assets/backupTests/account_data_20.binproto index 01ada5d0b24e3d1112f2ebc59b32492950ff5e4d..f13087a10518722579b15749da612f118e29e3e9 100644 GIT binary patch delta 37 tcmaFP^o(hOAIob-t``%7(uEZ=N=gcft@QPaGt=`DbM*3y(kGss1ppBF4#ofg delta 38 ucmaFH^qgseAIlp?u9p*o(nSk delta 38 tcmeBR?qr_e$I{2d)jct&TtqRWq@AtH30D?4eI~^ diff --git a/app/src/androidTest/assets/backupTests/account_data_25.binproto b/app/src/androidTest/assets/backupTests/account_data_25.binproto index 34d548fbc32682d9c7c9aa291efa6b634ab6e286..f7cb99d37e04f986c4ff86d396b472f1c9e07aa3 100644 GIT binary patch delta 37 scmZoBor2yN=gcft@QPaGt=`DbM*3y(kI?K3;^%y4g3HA delta 38 ucmZ3$ypVZly-k;zymwIVUMASYEXIX_q5-?tzo(<{nf XX)7a_Oh!pbL9vy-K9YjTbxfN9*i#w# diff --git a/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_02.binproto b/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_02.binproto index 0907cfca7873df7ef1d5b7a7a7c18d405d72b3d3..3d9f682c3a12ad78bbb432a6be8434987f88dc9f 100644 GIT binary patch delta 91 zcmeBU?_uBYi&1_8vr;cJ2a^D!#I}!z9zHbmV&h`rV3A^o`pzU2&J{XYlF3P{I5Ryj nF-I@IC|%#*w;(0cE6QK#Dk diff --git a/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_03.binproto b/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_03.binproto index aa6edcd0fa0fb6f91e6874192e6087c7b066f71a..c95e1666f58597cb7cbec1af62014f79c68789a8 100644 GIT binary patch delta 101 zcmZ3^wv=tdFGiM?OiIfp|6`O3XlD{Ke>`$R&*_KRJ(SCjcSPi!<1#5N$;?a4RVYp@$V|;sC@IP;F3Bt`O;yM! qDJdwn($`O|NX#wBN!3fv&(-($ElA1qit<-F$H*mvMZx48rkwzPmL&cF diff --git a/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_04.binproto b/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_04.binproto index 35e7dcdfdacdcf50469f3572ed08b45bf027801f..efbf24412d7b9bf25c3b196742d8951a11414ec2 100644 GIT binary patch delta 74 zcmZ3?wvcVZFGiN7OiGI;|6`P4Yh@Dh;BuR+z+|jdoSB}Nn4_0pl&^z+|kGT9KGrkdvyHoS&=j?^}?P=@sR# Xw2YBUCZnXJpx8=ZA4$RFTBaoc!4?^b diff --git a/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_05.binproto b/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_05.binproto index c82676d0409cea32112fe84c5acced24f63297e3..9e62fecec9b7610f4b830e70ad457d5522466977 100644 GIT binary patch delta 74 zcmcb}cAjm+FGiNjOiC9f|6>$q+rcCh&J{XYn#oD4I5RyjF-I@IC|%#*w;(0cE6QJK W8zYx=MoCFQv6a3)LVj{5(+L32w;BQf delta 76 zcmX@lc9CtvFGiNDOiGs~|6>$q+r=al!4)=Hn#oBgwIVUMASYEXIX_q5-?tzo(<{nf XX*(mAOh!pbL9vy-K9YjT?Mx>C2>2S- diff --git a/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_06.binproto b/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_06.binproto index b1e20b5f966b5b8e0634970a361e6cc80cfc9aa7..3f5f30f87af05b56bad11f7ff0b22318bf8a0c31 100644 GIT binary patch delta 74 zcmZ3?wvcVZFGiN7OiGI;|6`P4Yh@BLtWmQi;-mllTz>Ge~fZ$?-+$VxZEZyF&S$WXQt;R=IG@YrR)3q7Nlf)MfofB WF>*;~l#~<{Tj}c~>W^#TBi9vGnj delta 76 zcmeBS>toySi;-m#lT!cWe~fZ$9~gx^x!fl!F&XQmRwU*YB((OnE*|E9mxOy delta 91 zcmaFM`kr;eFGl&#j7lFEIhX_(CH8zg^zfmf7aJD~2a6Fy)GbD#2(GZnl1xt8sTGO2 m1v#mD$@#hZ{=Nk%nO;%;N)cQ#86_nJ#a8Lusr>ihc^q-1(U`70@K S$z+t26ck(O>tmDGU;qG2W*Sof diff --git a/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_10.binproto b/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_10.binproto index 38801c695ee831e47097bba06e6d1938c110e422..bd1e92988c6f067ba7deb510d6c866ddb86685a3 100644 GIT binary patch delta 74 zcmdnQwt;QKFGiLvOiCLk|6`P4o5CdI!R0ntfyr2_I5RyjF-I@IC|%#*w;(0cE6QJK W3nQ0wMoCFQv6a3)LVj{R(`Epl8W|n{ delta 76 zcmdnMwux=SFGiMaOiG(4|6`P4o5m#M$>ly-fyr1WwIVUMASYEXIX_q5-?tzo(<{nf XX)7a_Oh!pbL9vy-K9YjTwM?4<*2Ed| diff --git a/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_11.binproto b/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_11.binproto index 22abeb9a34d1fa1453d2260f9e69b7386fb2df28..c2a41897382189a30b3a7e8cfc21391bb70151ed 100644 GIT binary patch delta 91 zcmeBU?_uBYi&1_8vr;cJ2a^D!#Qu+m9zHbmV&h`rU~yuI`pzU2&J{XYlF3P{I5Ryj nF-I@IC|%#*w;(0cE6QK#Dtqr#<1(47z@(s)T9KGrkdvyHoS&=j?^}?P=@sR# XbdHfrCZnXJpx8=ZA4$RFET)|RyY?A` diff --git a/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_13.binproto b/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_13.binproto index e5290a2876ec566e91a4b12c0dffcde04f7f93ad..e147e981b6c7ba5038731acb56f7edc4bc9a6e4e 100644 GIT binary patch delta 74 zcmZ3=wwP_hFGiN-OiD{8|6`P6Yh@Dh;BuR+#AK{hoSB}Nn4_0pl&^#AK|KT9KGrkdvyHoS&=j?^}?P=@sR# Xw2YBUCZnXJpx8=ZA4$RFdZr}+#55U~ diff --git a/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_14.binproto b/app/src/androidTest/assets/backupTests/chat_item_standard_message_with_link_preview_14.binproto index 1668122cbbf3c432ebba4f62acdee5a7318f0476..f210e1ecdc45ed722061cb53c673a09cf73c8f24 100644 GIT binary patch delta 74 zcmcb}cAjm+FGiNjOiC9f|6>$q+rcCh&J{XYn#oD4I5RyjF-I@IC|%#*w;(0cE6QJK W8zYx=MoCFQv6a3)LVj{5(+L32w;BQf delta 76 zcmX@lc9CtvFGiNDOiGs~|6>$q+r=al!4)=Hn#oBgwIVUMASYEXIX_q5-?tzo(<{nf XX*(mAOh!pbL9vy-K9YjT?Mx>C2>2S- diff --git a/app/src/androidTest/assets/backupTests/recipient_contacts_00.binproto b/app/src/androidTest/assets/backupTests/recipient_contacts_00.binproto index d2c7a24431abc45d700e50eb380c2f6b85c84d48..861f5b165cbdc721e35d01e26ac7ec6f2bd14c27 100644 GIT binary patch delta 32 ncmZ3)yoPy0CL_C(kOK#ckj>-*MgyKMM)thKlKjHbR4WDmiCYM5 delta 22 dcmZ3(yoh;2CL_CrkQoPykkRAi=hd_ diff --git a/app/src/androidTest/assets/backupTests/recipient_contacts_04.binproto b/app/src/androidTest/assets/backupTests/recipient_contacts_04.binproto new file mode 100644 index 0000000000000000000000000000000000000000..233f69b78536e460b912cb08c8cc7cab93b1894e GIT binary patch literal 440 zcmea}U=+CVYr*{QhEfXsyKEj#$*x#(ig%Lc-3T4SDnN=53x$z@T~eE!J@?C1T;m9#SLhTl_rk?tZezH8@o%F+$t_T-1YmD}2wTN(wQD2D?ZwdU*l8%qYRAz^K7!z-Tc+#)&b} zi80BEG1-GLfH8tGfiZ)zfU$zHfswI;k!cnqI|rjE0|Uc<5Q_=O`VVF?i!%IY_|GQ9 z!ojG;0HTnCZUr|99&XICO5IDG0vU5l0{EgCZnXJpx8=Zzc@2JFEK|izbJk3 HYnHbFzW)+G delta 52 zcmcc4eS>>LB@5?SCZSVI99&XICpWREG0vO3l0{EMHlw7Zpx8=ZKeZw;w;(4~FF8MV I@++3N0MV=xsQ>@~ diff --git a/app/src/androidTest/assets/backupTests/recipient_groups_02.binproto b/app/src/androidTest/assets/backupTests/recipient_groups_02.binproto index fefcdcd7047a99e4ac873466a0bc47993a59490b..34eee1a7d2829f632ad4ff0458e47841df3990f3 100644 GIT binary patch delta 51 zcmZ3-y_S1JB@5>wCZYLE99&YfCO5HYF}|O?mc>?BF{7lUpx8=Zzc@2JFEK|izbJk3 HKb8#ur&AHJ delta 52 zcmZ3>y^ecBB@5?bCZPpP99&YfCpWQZF@Bi5mc>>?DWjyMpx8=ZKeZw;w;(4~FF8MV I@?Vw>0J)qJ8vp?): List? { +private fun BackupMessageRecord.toRemoteSharedContact(attachments: List?): Contact? { if (this.sharedContacts.isNullOrEmpty()) { - return emptyList() + return null } val attachmentIdMap: Map = attachments?.associateBy { it.attachmentId } ?: emptyMap() return try { - val contacts: MutableList = 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 - } + if (jsonContacts.length() == 0) { + return null } - contacts + val contact: Contact = Contact.deserialize(jsonContacts.getJSONObject(0).toString()) + + return 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 + ) + + Contact(contact, updatedAvatar) + } else { + contact + } } catch (e: JSONException) { Log.w(TAG, ExportSkips.failedToParseSharedContact(this.dateSent), e) null @@ -768,28 +766,28 @@ private fun BackupMessageRecord.toRemoteViewOnceMessage(mediaArchiveEnabled: Boo } private fun BackupMessageRecord.toRemoteContactMessage(mediaArchiveEnabled: Boolean, reactionRecords: List?, attachments: List?): ContactMessage? { - val sharedContacts = toRemoteSharedContacts(attachments) ?: return null + val sharedContact = toRemoteSharedContact(attachments) ?: return null - val contacts = sharedContacts.map { - ContactAttachment( - name = it.name.toRemote(), - avatar = (it.avatar?.attachment as? DatabaseAttachment)?.toRemoteMessageAttachment(mediaArchiveEnabled)?.pointer, - organization = it.organization ?: "", - number = it.phoneNumbers.map { phone -> + return ContactMessage( + contact = ContactAttachment( + name = sharedContact.name.toRemote(), + avatar = (sharedContact.avatar?.attachment as? DatabaseAttachment)?.toRemoteMessageAttachment(mediaArchiveEnabled)?.pointer, + organization = sharedContact.organization ?: "", + number = sharedContact.phoneNumbers.map { phone -> ContactAttachment.Phone( value_ = phone.number, type = phone.type.toRemote(), label = phone.label ?: "" ) }, - email = it.emails.map { email -> + email = sharedContact.emails.map { email -> ContactAttachment.Email( value_ = email.email, label = email.label ?: "", type = email.type.toRemote() ) }, - address = it.postalAddresses.map { address -> + address = sharedContact.postalAddresses.map { address -> ContactAttachment.PostalAddress( type = address.type.toRemote(), label = address.label ?: "", @@ -802,10 +800,7 @@ private fun BackupMessageRecord.toRemoteContactMessage(mediaArchiveEnabled: Bool country = address.country ?: "" ) } - ) - } - return ContactMessage( - contact = contacts, + ), reactions = reactionRecords.toRemote() ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ContactArchiveExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ContactArchiveExporter.kt index a67acee845..e482d27460 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ContactArchiveExporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ContactArchiveExporter.kt @@ -76,6 +76,8 @@ class ContactArchiveExporter(private val cursor: Cursor, private val selfId: Lon .hideStory(RecipientTableCursorUtil.getExtras(cursor)?.hideStory() ?: false) .identityKey(cursor.requireString(IdentityTable.IDENTITY_KEY)?.let { Base64.decode(it).toByteString() }) .identityState(cursor.optionalInt(IdentityTable.VERIFIED).map { IdentityTable.VerifiedStatus.forState(it) }.orElse(IdentityTable.VerifiedStatus.DEFAULT).toRemote()) + .note(cursor.requireString(RecipientTable.NOTE) ?: "") + .nickname(cursor.readNickname()) val registeredState = RecipientTable.RegisteredState.fromId(cursor.requireInt(RecipientTable.REGISTERED)) if (registeredState == RecipientTable.RegisteredState.REGISTERED) { @@ -95,6 +97,20 @@ class ContactArchiveExporter(private val cursor: Cursor, private val selfId: Lon } } +private fun Cursor.readNickname(): Contact.Name? { + val given = this.requireString(RecipientTable.NICKNAME_GIVEN_NAME) + val family = this.requireString(RecipientTable.NICKNAME_FAMILY_NAME) + + if (given.isNullOrEmpty()) { + return null + } + + return Contact.Name( + given = given, + family = family ?: "" + ) +} + private fun Recipient.HiddenState.toRemote(): Contact.Visibility { return when (this) { Recipient.HiddenState.NOT_HIDDEN -> return Contact.Visibility.VISIBLE diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ChatItemArchiveImporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ChatItemArchiveImporter.kt index 3c430baa45..cbba360def 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ChatItemArchiveImporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ChatItemArchiveImporter.kt @@ -310,7 +310,7 @@ class ChatItemArchiveImporter( } if (this.contactMessage != null) { - val contacts = this.contactMessage.contact.map { backupContact -> + val contact = this.contactMessage.contact?.let { backupContact -> Contact( backupContact.name.toLocal(), backupContact.organization, @@ -345,18 +345,18 @@ class ChatItemArchiveImporter( ) } - val contactAttachments = contacts.mapNotNull { it.avatarAttachment } - if (contacts.isNotEmpty()) { + if (contact != null) { + val contactAttachment: Attachment? = contact.avatarAttachment followUp = { messageRowId -> - val attachmentMap = if (contactAttachments.isNotEmpty()) { - SignalDatabase.attachments.insertAttachmentsForMessage(messageRowId, contactAttachments, emptyList()) + val attachmentMap = if (contactAttachment != null) { + SignalDatabase.attachments.insertAttachmentsForMessage(messageRowId, listOf(contactAttachment), emptyList()) } else { emptyMap() } db.update( MessageTable.TABLE_NAME, contentValuesOf( - MessageTable.SHARED_CONTACTS to SignalDatabase.messages.getSerializedSharedContacts(attachmentMap, contacts) + MessageTable.SHARED_CONTACTS to SignalDatabase.messages.getSerializedSharedContacts(attachmentMap, listOf(contact)) ), "${MessageTable.ID} = ?", SqlUtil.buildArgs(messageRowId) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ContactArchiveImporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ContactArchiveImporter.kt index 0acffd8168..cac6c8cb27 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ContactArchiveImporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ContactArchiveImporter.kt @@ -49,7 +49,10 @@ object ContactArchiveImporter { RecipientTable.PROFILE_KEY to if (profileKey == null) null else Base64.encodeWithPadding(profileKey), RecipientTable.PROFILE_SHARING to contact.profileSharing.toInt(), RecipientTable.USERNAME to contact.username, - RecipientTable.EXTRAS to contact.toLocalExtras().encode() + RecipientTable.EXTRAS to contact.toLocalExtras().encode(), + RecipientTable.NOTE to contact.note, + RecipientTable.NICKNAME_GIVEN_NAME to contact.nickname?.given, + RecipientTable.NICKNAME_FAMILY_NAME to contact.nickname?.family ) if (contact.registered != null) { diff --git a/app/src/main/protowire/Backup.proto b/app/src/main/protowire/Backup.proto index fbb5301963..48a6f248c0 100644 --- a/app/src/main/protowire/Backup.proto +++ b/app/src/main/protowire/Backup.proto @@ -147,6 +147,11 @@ message Contact { HIDDEN_MESSAGE_REQUEST = 2; } + message Name { + string given = 1; + string family = 2; + } + optional bytes aci = 1; // should be 16 bytes optional bytes pni = 2; // should be 16 bytes optional string username = 3; @@ -166,6 +171,8 @@ message Contact { bool hideStory = 13; optional bytes identityKey = 14; IdentityState identityState = 15; + Name nickname = 16; // absent iff both `given` and `family` are empty + string note = 17; } message Group { @@ -373,6 +380,7 @@ message ChatItem { PaymentNotification paymentNotification = 16; GiftBadge giftBadge = 17; ViewOnceMessage viewOnceMessage = 18; + DirectStoryReplyMessage directStoryReplyMessage = 19; // group story reply messages are not backed up } } @@ -437,10 +445,25 @@ message StandardMessage { } message ContactMessage { - repeated ContactAttachment contact = 1; + ContactAttachment contact = 1; repeated Reaction reactions = 2; } +message DirectStoryReplyMessage { + message TextReply { + Text text = 1; + FilePointer longText = 2; + } + + oneof reply { + TextReply textReply = 1; + string emoji = 2; + } + + repeated Reaction reactions = 3; + optional uint64 storySentTimestamp = 4; +} + message PaymentNotification { message TransactionDetails { message MobileCoinTxoIdentification { // Used to map to payments on the ledger @@ -1234,4 +1257,4 @@ message ChatFolder { FolderType folderType = 6; repeated uint64 includedRecipientIds = 7; // generated recipient id of groups, contacts, and/or note to self repeated uint64 excludedRecipientIds = 8; // generated recipient id of groups, contacts, and/or note to self -} \ No newline at end of file +}