Add support for Contact.nickname field.

This commit is contained in:
Greyson Parrelli 2024-09-27 10:46:37 -04:00
parent 5bdc7c2740
commit 62b5276c75
10 changed files with 61 additions and 127 deletions

View file

@ -65,7 +65,6 @@ import org.thoughtcrime.securesms.payments.Direction
import org.thoughtcrime.securesms.payments.FailureReason import org.thoughtcrime.securesms.payments.FailureReason
import org.thoughtcrime.securesms.payments.State import org.thoughtcrime.securesms.payments.State
import org.thoughtcrime.securesms.payments.proto.PaymentMetaData import org.thoughtcrime.securesms.payments.proto.PaymentMetaData
import org.thoughtcrime.securesms.profiles.ProfileName
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.stickers.StickerLocator import org.thoughtcrime.securesms.stickers.StickerLocator
@ -1021,8 +1020,7 @@ class ChatItemImportInserter(
} }
private fun ContactAttachment.Name?.toLocal(): Contact.Name { private fun ContactAttachment.Name?.toLocal(): Contact.Name {
val displayName = ProfileName.fromParts(this?.givenName, this?.familyName).toString() return Contact.Name(this?.givenName, this?.familyName, this?.prefix, this?.suffix, this?.middleName, null)
return Contact.Name(displayName, this?.givenName, this?.familyName, this?.prefix, this?.suffix, this?.middleName)
} }
private fun ContactAttachment.Phone.Type?.toLocal(): Contact.Phone.Type { private fun ContactAttachment.Phone.Type?.toLocal(): Contact.Phone.Type {

View file

@ -142,9 +142,6 @@ public class Contact implements Parcelable {
public static class Name implements Parcelable { public static class Name implements Parcelable {
@JsonProperty
private final String displayName;
@JsonProperty @JsonProperty
private final String givenName; private final String givenName;
@ -160,30 +157,29 @@ public class Contact implements Parcelable {
@JsonProperty @JsonProperty
private final String middleName; private final String middleName;
@JsonProperty
private final String nickname;
public Name( 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,
@JsonProperty("suffix") @Nullable String suffix, @JsonProperty("suffix") @Nullable String suffix,
@JsonProperty("middleName") @Nullable String middleName) @JsonProperty("middleName") @Nullable String middleName,
@JsonProperty("nickname") @Nullable String nickname)
{ {
this.displayName = displayName;
this.givenName = givenName; this.givenName = givenName;
this.familyName = familyName; this.familyName = familyName;
this.prefix = prefix; this.prefix = prefix;
this.suffix = suffix; this.suffix = suffix;
this.middleName = middleName; this.middleName = middleName;
this.nickname = nickname;
} }
private Name(Parcel in) { private Name(Parcel in) {
this(in.readString(), in.readString(), in.readString(), in.readString(), in.readString(), in.readString()); this(in.readString(), in.readString(), in.readString(), in.readString(), in.readString(), in.readString());
} }
public @Nullable String getDisplayName() {
return displayName;
}
public @Nullable String getGivenName() { public @Nullable String getGivenName() {
return givenName; return givenName;
} }
@ -204,8 +200,12 @@ public class Contact implements Parcelable {
return middleName; return middleName;
} }
public @Nullable String getNickname() {
return nickname;
}
public boolean isEmpty() { public boolean isEmpty() {
return TextUtils.isEmpty(displayName) && return TextUtils.isEmpty(nickname) &&
TextUtils.isEmpty(givenName) && TextUtils.isEmpty(givenName) &&
TextUtils.isEmpty(familyName) && TextUtils.isEmpty(familyName) &&
TextUtils.isEmpty(prefix) && TextUtils.isEmpty(prefix) &&
@ -220,12 +220,12 @@ public class Contact implements Parcelable {
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(displayName);
dest.writeString(givenName); dest.writeString(givenName);
dest.writeString(familyName); dest.writeString(familyName);
dest.writeString(prefix); dest.writeString(prefix);
dest.writeString(suffix); dest.writeString(suffix);
dest.writeString(middleName); dest.writeString(middleName);
dest.writeString(nickname);
} }
public static final Creator<Name> CREATOR = new Creator<Name>() { public static final Creator<Name> CREATOR = new Creator<Name>() {

View file

@ -59,7 +59,7 @@ public class ContactModelMapper {
.build()); .build());
} }
SharedContact.Name name = new SharedContact.Name.Builder().setDisplay(contact.getName().getDisplayName()) SharedContact.Name name = new SharedContact.Name.Builder().setNickname(contact.getName().getNickname())
.setGiven(contact.getName().getGivenName()) .setGiven(contact.getName().getGivenName())
.setFamily(contact.getName().getFamilyName()) .setFamily(contact.getName().getFamilyName())
.setPrefix(contact.getName().getPrefix()) .setPrefix(contact.getName().getPrefix())
@ -74,66 +74,14 @@ public class ContactModelMapper {
.withAddresses(postalAddresses); .withAddresses(postalAddresses);
} }
public static Contact remoteToLocal(@NonNull SharedContact sharedContact) {
Name name = new Name(sharedContact.getName().getDisplay().orElse(null),
sharedContact.getName().getGiven().orElse(null),
sharedContact.getName().getFamily().orElse(null),
sharedContact.getName().getPrefix().orElse(null),
sharedContact.getName().getSuffix().orElse(null),
sharedContact.getName().getMiddle().orElse(null));
List<Phone> phoneNumbers = new LinkedList<>();
if (sharedContact.getPhone().isPresent()) {
for (SharedContact.Phone phone : sharedContact.getPhone().get()) {
phoneNumbers.add(new Phone(phone.getValue(),
remoteToLocalType(phone.getType()),
phone.getLabel().orElse(null)));
}
}
List<Email> emails = new LinkedList<>();
if (sharedContact.getEmail().isPresent()) {
for (SharedContact.Email email : sharedContact.getEmail().get()) {
emails.add(new Email(email.getValue(),
remoteToLocalType(email.getType()),
email.getLabel().orElse(null)));
}
}
List<PostalAddress> postalAddresses = new LinkedList<>();
if (sharedContact.getAddress().isPresent()) {
for (SharedContact.PostalAddress postalAddress : sharedContact.getAddress().get()) {
postalAddresses.add(new PostalAddress(remoteToLocalType(postalAddress.getType()),
postalAddress.getLabel().orElse(null),
postalAddress.getStreet().orElse(null),
postalAddress.getPobox().orElse(null),
postalAddress.getNeighborhood().orElse(null),
postalAddress.getCity().orElse(null),
postalAddress.getRegion().orElse(null),
postalAddress.getPostcode().orElse(null),
postalAddress.getCountry().orElse(null)));
}
}
Avatar avatar = null;
if (sharedContact.getAvatar().isPresent()) {
Attachment attachment = PointerAttachment.forPointer(Optional.of(sharedContact.getAvatar().get().getAttachment().asPointer())).get();
boolean isProfile = sharedContact.getAvatar().get().isProfile();
avatar = new Avatar(null, attachment, isProfile);
}
return new Contact(name, sharedContact.getOrganization().orElse(null), phoneNumbers, emails, postalAddresses, avatar);
}
public static Contact remoteToLocal(@NonNull DataMessage.Contact contact) { public static Contact remoteToLocal(@NonNull DataMessage.Contact contact) {
DataMessage.Contact.Name contactName = contact.name != null ? contact.name : new DataMessage.Contact.Name(); DataMessage.Contact.Name contactName = contact.name != null ? contact.name : new DataMessage.Contact.Name();
Name name = new Name(contactName.displayName, Name name = new Name(contactName.givenName,
contactName.givenName,
contactName.familyName, contactName.familyName,
contactName.prefix, contactName.prefix,
contactName.suffix, contactName.suffix,
contactName.middleName); contactName.middleName,
contactName.nickname);
List<Phone> phoneNumbers = new ArrayList<>(contact.number.size()); List<Phone> phoneNumbers = new ArrayList<>(contact.number.size());
for (DataMessage.Contact.Phone phone : contact.number) { for (DataMessage.Contact.Phone phone : contact.number) {
@ -182,17 +130,6 @@ public class ContactModelMapper {
return new Contact(name, contact.organization, phoneNumbers, emails, postalAddresses, avatar); return new Contact(name, contact.organization, phoneNumbers, emails, postalAddresses, avatar);
} }
private static Phone.Type remoteToLocalType(@Nullable SharedContact.Phone.Type type) {
if (type == null) return Phone.Type.CUSTOM;
switch (type) {
case HOME: return Phone.Type.HOME;
case MOBILE: return Phone.Type.MOBILE;
case WORK: return Phone.Type.WORK;
default: return Phone.Type.CUSTOM;
}
}
private static Phone.Type remoteToLocalType(@Nullable DataMessage.Contact.Phone.Type type) { private static Phone.Type remoteToLocalType(@Nullable DataMessage.Contact.Phone.Type type) {
if (type == null) return Phone.Type.CUSTOM; if (type == null) return Phone.Type.CUSTOM;
@ -204,17 +141,6 @@ public class ContactModelMapper {
} }
} }
private static Email.Type remoteToLocalType(@Nullable SharedContact.Email.Type type) {
if (type == null) return Email.Type.CUSTOM;
switch (type) {
case HOME: return Email.Type.HOME;
case MOBILE: return Email.Type.MOBILE;
case WORK: return Email.Type.WORK;
default: return Email.Type.CUSTOM;
}
}
private static Email.Type remoteToLocalType(@Nullable DataMessage.Contact.Email.Type type) { private static Email.Type remoteToLocalType(@Nullable DataMessage.Contact.Email.Type type) {
if (type == null) return Email.Type.CUSTOM; if (type == null) return Email.Type.CUSTOM;

View file

@ -36,7 +36,7 @@ public class ContactNameEditViewModel extends ViewModel {
} }
Name getName() { Name getName() {
return new Name(displayName.getValue(), givenName, familyName, prefix, suffix, middleName); return new Name(givenName, familyName, prefix, suffix, middleName, null);
} }
void updateGivenName(@NonNull String givenName) { void updateGivenName(@NonNull String givenName) {

View file

@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.contactshare.Contact.PostalAddress;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.mms.PartAuthority; import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter; import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
import org.thoughtcrime.securesms.profiles.ProfileName;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.SpanUtil; import org.thoughtcrime.securesms.util.SpanUtil;
@ -65,8 +66,12 @@ public final class ContactUtil {
return ""; return "";
} }
if (!TextUtils.isEmpty(contact.getName().getDisplayName())) { if (!TextUtils.isEmpty(contact.getName().getNickname())) {
return contact.getName().getDisplayName(); return contact.getName().getNickname();
}
if (!TextUtils.isEmpty(contact.getName().getGivenName())) {
return ProfileName.fromParts(contact.getName().getGivenName(), contact.getName().getFamilyName()).toString();
} }
if (!TextUtils.isEmpty(contact.getOrganization())) { if (!TextUtils.isEmpty(contact.getOrganization())) {
@ -152,8 +157,11 @@ public final class ContactUtil {
Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE); intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
if (!TextUtils.isEmpty(contact.getName().getDisplayName())) { if (!TextUtils.isEmpty(contact.getName().getNickname())) {
intent.putExtra(ContactsContract.Intents.Insert.NAME, contact.getName().getDisplayName()); intent.putExtra(ContactsContract.Intents.Insert.NAME, contact.getName().getNickname());
} else if (!TextUtils.isEmpty(contact.getName().getGivenName())) {
String displayName = ProfileName.fromParts(contact.getName().getGivenName(), contact.getName().getFamilyName()).toString();
intent.putExtra(ContactsContract.Intents.Insert.NAME, displayName);
} }
if (!TextUtils.isEmpty(contact.getOrganization())) { if (!TextUtils.isEmpty(contact.getOrganization())) {

View file

@ -108,7 +108,7 @@ public class SharedContactRepository {
NameDetails nameDetails = SystemContactsRepository.getNameDetails(context, contactId); NameDetails nameDetails = SystemContactsRepository.getNameDetails(context, contactId);
if (nameDetails != null) { if (nameDetails != null) {
Name name = new Name(nameDetails.getDisplayName(), nameDetails.getGivenName(), nameDetails.getFamilyName(), nameDetails.getPrefix(), nameDetails.getSuffix(), nameDetails.getMiddleName()); Name name = new Name(nameDetails.getGivenName(), nameDetails.getFamilyName(), nameDetails.getPrefix(), nameDetails.getSuffix(), nameDetails.getMiddleName(), null);
if (!name.isEmpty()) { if (!name.isEmpty()) {
return name; return name;
} }
@ -116,7 +116,7 @@ public class SharedContactRepository {
String org = SystemContactsRepository.getOrganizationName(context, contactId); String org = SystemContactsRepository.getOrganizationName(context, contactId);
if (!TextUtils.isEmpty(org)) { if (!TextUtils.isEmpty(org)) {
return new Name(org, org, null, null, null, null); return new Name(org, null, null, null, null, null);
} }
return null; return null;

View file

@ -52,11 +52,12 @@ public final class VCardUtil {
return null; return null;
} }
Contact.Name name = new Contact.Name(displayName, Contact.Name name = new Contact.Name(
vName != null ? vName.getGiven() : null, vName != null ? vName.getGiven() : null,
vName != null ? vName.getFamily() : null, vName != null ? vName.getFamily() : null,
vName != null && !vName.getPrefixes().isEmpty() ? vName.getPrefixes().get(0) : null, vName != null && !vName.getPrefixes().isEmpty() ? vName.getPrefixes().get(0) : null,
vName != null && !vName.getSuffixes().isEmpty() ? vName.getSuffixes().get(0) : null, vName != null && !vName.getSuffixes().isEmpty() ? vName.getSuffixes().get(0) : null,
null,
null); null);

View file

@ -1754,12 +1754,12 @@ public class SignalServiceMessageSender {
for (SharedContact contact : contacts) { for (SharedContact contact : contacts) {
DataMessage.Contact.Name.Builder nameBuilder = new DataMessage.Contact.Name.Builder(); DataMessage.Contact.Name.Builder nameBuilder = new DataMessage.Contact.Name.Builder();
if (contact.getName().getFamily().isPresent()) nameBuilder.familyName(contact.getName().getFamily().get()); if (contact.getName().getFamily().isPresent()) nameBuilder.familyName(contact.getName().getFamily().get());
if (contact.getName().getGiven().isPresent()) nameBuilder.givenName(contact.getName().getGiven().get()); if (contact.getName().getGiven().isPresent()) nameBuilder.givenName(contact.getName().getGiven().get());
if (contact.getName().getMiddle().isPresent()) nameBuilder.middleName(contact.getName().getMiddle().get()); if (contact.getName().getMiddle().isPresent()) nameBuilder.middleName(contact.getName().getMiddle().get());
if (contact.getName().getPrefix().isPresent()) nameBuilder.prefix(contact.getName().getPrefix().get()); if (contact.getName().getPrefix().isPresent()) nameBuilder.prefix(contact.getName().getPrefix().get());
if (contact.getName().getSuffix().isPresent()) nameBuilder.suffix(contact.getName().getSuffix().get()); if (contact.getName().getSuffix().isPresent()) nameBuilder.suffix(contact.getName().getSuffix().get());
if (contact.getName().getDisplay().isPresent()) nameBuilder.displayName(contact.getName().getDisplay().get()); if (contact.getName().getNickname().isPresent()) nameBuilder.nickname(contact.getName().getNickname().get());
DataMessage.Contact.Builder contactBuilder = new DataMessage.Contact.Builder().name(nameBuilder.build()); DataMessage.Contact.Builder contactBuilder = new DataMessage.Contact.Builder().name(nameBuilder.build());

View file

@ -11,9 +11,9 @@ import java.util.Optional;
public class SharedContact { public class SharedContact {
private final Name name; private final Name name;
private final Optional<Avatar> avatar; private final Optional<Avatar> avatar;
private final Optional<List<Phone>> phone; private final Optional<List<Phone>> phone;
private final Optional<List<Email>> email; private final Optional<List<Email>> email;
private final Optional<List<PostalAddress>> address; private final Optional<List<PostalAddress>> address;
private final Optional<String> organization; private final Optional<String> organization;
@ -103,28 +103,28 @@ public class SharedContact {
public static class Name { public static class Name {
private final Optional<String> display;
private final Optional<String> given; private final Optional<String> given;
private final Optional<String> family; private final Optional<String> family;
private final Optional<String> prefix; private final Optional<String> prefix;
private final Optional<String> suffix; private final Optional<String> suffix;
private final Optional<String> middle; private final Optional<String> middle;
private final Optional<String> nickname;
public Name(Optional<String> display, Optional<String> given, Optional<String> family, Optional<String> prefix, Optional<String> suffix, Optional<String> middle) { public Name(Optional<String> given, Optional<String> family, Optional<String> prefix, Optional<String> suffix, Optional<String> middle, Optional<String> nickname) {
this.display = display; this.given = given;
this.given = given; this.family = family;
this.family = family; this.prefix = prefix;
this.prefix = prefix; this.suffix = suffix;
this.suffix = suffix; this.middle = middle;
this.middle = middle; this.nickname = nickname;
} }
public static Builder newBuilder() { public static Builder newBuilder() {
return new Builder(); return new Builder();
} }
public Optional<String> getDisplay() { public Optional<String> getNickname() {
return display; return nickname;
} }
public Optional<String> getGiven() { public Optional<String> getGiven() {
@ -148,15 +148,15 @@ public class SharedContact {
} }
public static class Builder { public static class Builder {
private String display; private String nickname;
private String given; private String given;
private String family; private String family;
private String prefix; private String prefix;
private String suffix; private String suffix;
private String middle; private String middle;
public Builder setDisplay(String display) { public Builder setNickname(String nickname) {
this.display = display; this.nickname = nickname;
return this; return this;
} }
@ -186,12 +186,12 @@ public class SharedContact {
} }
public Name build() { public Name build() {
return new Name(Optional.ofNullable(display), return new Name(Optional.ofNullable(given),
Optional.ofNullable(given),
Optional.ofNullable(family), Optional.ofNullable(family),
Optional.ofNullable(prefix), Optional.ofNullable(prefix),
Optional.ofNullable(suffix), Optional.ofNullable(suffix),
Optional.ofNullable(middle)); Optional.ofNullable(middle),
Optional.ofNullable(nickname));
} }
} }
} }

View file

@ -177,7 +177,8 @@ message DataMessage {
optional string prefix = 3; optional string prefix = 3;
optional string suffix = 4; optional string suffix = 4;
optional string middleName = 5; optional string middleName = 5;
optional string displayName = 6; reserved /*displayName*/ 6;
optional string nickname = 7;
} }
message Phone { message Phone {