diff --git a/go.mod b/go.mod index 3c1ffd16b..2e13aba99 100644 --- a/go.mod +++ b/go.mod @@ -63,7 +63,7 @@ require ( go.uber.org/zap v1.24.0 golang.org/x/crypto v0.4.0 golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb - google.golang.org/protobuf v1.28.1 + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v9 v9.31.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 diff --git a/protocol/contact.go b/protocol/contact.go index 19d13124c..28f901153 100644 --- a/protocol/contact.go +++ b/protocol/contact.go @@ -40,18 +40,6 @@ type ContactDeviceInfo struct { FCMToken string `json:"fcmToken"` } -func (c *Contact) CanonicalName() string { - if c.LocalNickname != "" { - return c.LocalNickname - } - - if c.ENSVerified { - return c.EnsName - } - - return c.Alias -} - func (c *Contact) CanonicalImage(profilePicturesVisibility settings.ProfilePicturesVisibilityType) string { if profilePicturesVisibility == settings.ProfilePicturesVisibilityNone || (profilePicturesVisibility == settings.ProfilePicturesVisibilityContactsOnly && !c.added()) { return c.Identicon @@ -191,10 +179,49 @@ func (c *Contact) mutual() bool { return c.added() && c.hasAddedUs() } +func (c *Contact) active() bool { + return c.mutual() && !c.Blocked +} + func (c *Contact) dismissed() bool { return c.ContactRequestLocalState == ContactRequestStateDismissed } +func (c *Contact) names() []string { + var names []string + + if c.LocalNickname != "" { + names = append(names, c.LocalNickname) + } + + if c.ENSVerified && len(c.EnsName) != 0 { + names = append(names, c.EnsName) + } + + if c.DisplayName != "" { + names = append(names, c.DisplayName) + } + + return append(names, c.Alias) + +} + +func (c *Contact) PrimaryName() string { + return c.names()[0] +} + +func (c *Contact) SecondaryName() string { + // Only shown if the user has a nickname + if c.LocalNickname == "" { + return "" + } + names := c.names() + if len(names) > 1 { + return names[1] + } + return "" +} + type ContactRequestProcessingResponse struct { processed bool newContactRequestReceived bool @@ -380,6 +407,11 @@ func (c *Contact) MarshalJSON() ([]byte, error) { Added bool `json:"added"` ContactRequestState ContactRequestState `json:"contactRequestState"` HasAddedUs bool `json:"hasAddedUs"` + Mutual bool `json:"mutual"` + + Active bool `json:"active"` + PrimaryName string `json:"primaryName"` + SecondaryName string `json:"secondaryName,omitempty"` }{ Alias: (*Alias)(c), } @@ -392,6 +424,11 @@ func (c *Contact) MarshalJSON() ([]byte, error) { item.Added = c.added() item.HasAddedUs = c.hasAddedUs() + item.Mutual = c.mutual() + item.Active = c.active() + item.PrimaryName = c.PrimaryName() + item.SecondaryName = c.SecondaryName() + item.Active = c.active() if c.mutual() { item.ContactRequestState = ContactRequestStateMutual diff --git a/protocol/contact_test.go b/protocol/contact_test.go index aeb80fb07..e5f68e16c 100644 --- a/protocol/contact_test.go +++ b/protocol/contact_test.go @@ -549,7 +549,12 @@ func TestContactContactRequestAccepted(t *testing.T) { } func TestMarshalContactJSON(t *testing.T) { - contact := &Contact{} + contact := &Contact{ + LocalNickname: "primary-name", + Alias: "secondary-name", + ContactRequestLocalState: ContactRequestStateSent, + ContactRequestRemoteState: ContactRequestStateReceived, + } id, err := crypto.GenerateKey() require.NoError(t, err) contact.ID = common.PubkeyToHex(&id.PublicKey) @@ -557,8 +562,14 @@ func TestMarshalContactJSON(t *testing.T) { encodedContact, err := json.Marshal(contact) require.NoError(t, err) - require.True(t, strings.Contains(string(encodedContact), "compressedKey\":\"zQ")) + require.True(t, strings.Contains(string(encodedContact), "compressedKey\":\"zQ")) + require.True(t, strings.Contains(string(encodedContact), "mutual\":true")) + require.True(t, strings.Contains(string(encodedContact), "added\":true")) + require.True(t, strings.Contains(string(encodedContact), "hasAddedUs\":true")) + require.True(t, strings.Contains(string(encodedContact), "active\":true")) + require.True(t, strings.Contains(string(encodedContact), "primaryName\":\"primary-name")) + require.True(t, strings.Contains(string(encodedContact), "secondaryName\":\"secondary-name")) } func TestContactContactRequestPropagatedStateReceivedOutOfDateLocalStateOnTheirSide(t *testing.T) { @@ -711,3 +722,46 @@ func TestContactContactRequestPropagatedStateReceivedOutOfDateRemoteState(t *tes require.False(t, c.hasAddedUs()) require.False(t, c.mutual()) } + +func TestPrimaryName(t *testing.T) { + // Has only Alias + + contact := &Contact{ + Alias: "alias", + } + + require.Equal(t, "alias", contact.PrimaryName()) + + // Has display name + + contact.DisplayName = "display-name" + + require.Equal(t, "display-name", contact.PrimaryName()) + require.Equal(t, "", contact.SecondaryName()) + + // Has non verified ens name + + contact.EnsName = "ens-name" + require.Equal(t, "display-name", contact.PrimaryName()) + require.Equal(t, "", contact.SecondaryName()) + + // Has verified ens name + contact.ENSVerified = true + require.Equal(t, "ens-name", contact.PrimaryName()) + require.Equal(t, "", contact.SecondaryName()) + + contact.LocalNickname = "nickname" + // Has nickname and ENS name + require.Equal(t, "nickname", contact.PrimaryName()) + require.Equal(t, "ens-name", contact.SecondaryName()) + + // Has nickname and display name + contact.EnsName = "" + require.Equal(t, "nickname", contact.PrimaryName()) + require.Equal(t, "display-name", contact.SecondaryName()) + + // Has nickname and alias + contact.DisplayName = "" + require.Equal(t, "nickname", contact.PrimaryName()) + require.Equal(t, "alias", contact.SecondaryName()) +} diff --git a/protocol/local_notifications.go b/protocol/local_notifications.go index 68ffdbaf4..f75374541 100644 --- a/protocol/local_notifications.go +++ b/protocol/local_notifications.go @@ -89,7 +89,7 @@ func (n NotificationBody) toMessageNotification(id string, contacts *contactMap, if n.Chat.PrivateGroupChat() || n.Chat.Public() || n.Chat.CommunityChat() { title = n.Chat.Name } else if n.Chat.OneToOne() { - title = n.Contact.CanonicalName() + title = n.Contact.PrimaryName() } @@ -103,7 +103,7 @@ func (n NotificationBody) toMessageNotification(id string, contacts *contactMap, return nil, err } } - canonicalNames[mentionID] = contact.CanonicalName() + canonicalNames[mentionID] = contact.PrimaryName() } // We don't pass idenity as only interested in the simplified text @@ -123,7 +123,7 @@ func (n NotificationBody) toMessageNotification(id string, contacts *contactMap, IsConversation: true, IsGroupConversation: true, Author: localnotifications.NotificationAuthor{ - Name: n.Contact.CanonicalName(), + Name: n.Contact.PrimaryName(), Icon: n.Contact.CanonicalImage(settings.ProfilePicturesVisibilityType(profilePicturesVisibility)), ID: n.Contact.ID, }, @@ -137,13 +137,13 @@ func (n NotificationBody) toPrivateGroupInviteNotification(id string, profilePic return &localnotifications.Notification{ ID: gethcommon.HexToHash(id), Body: n, - Title: n.Contact.CanonicalName() + " invited you to " + n.Chat.Name, - Message: n.Contact.CanonicalName() + " wants you to join group " + n.Chat.Name, + Title: n.Contact.PrimaryName() + " invited you to " + n.Chat.Name, + Message: n.Contact.PrimaryName() + " wants you to join group " + n.Chat.Name, BodyType: localnotifications.TypeMessage, Category: localnotifications.CategoryGroupInvite, Deeplink: n.Chat.DeepLink(), Author: localnotifications.NotificationAuthor{ - Name: n.Contact.CanonicalName(), + Name: n.Contact.PrimaryName(), Icon: n.Contact.CanonicalImage(settings.ProfilePicturesVisibilityType(profilePicturesVisibility)), ID: n.Contact.ID, }, @@ -155,8 +155,8 @@ func (n NotificationBody) toCommunityRequestToJoinNotification(id string) *local return &localnotifications.Notification{ ID: gethcommon.HexToHash(id), Body: n, - Title: n.Contact.CanonicalName() + " wants to join " + n.Community.Name(), - Message: n.Contact.CanonicalName() + " wants to join message " + n.Community.Name(), + Title: n.Contact.PrimaryName() + " wants to join " + n.Community.Name(), + Message: n.Contact.PrimaryName() + " wants to join message " + n.Community.Name(), BodyType: localnotifications.TypeMessage, Category: localnotifications.CategoryCommunityRequestToJoin, Deeplink: "status-im://cr/" + n.Community.IDString(), diff --git a/protocol/messenger_contact_verification.go b/protocol/messenger_contact_verification.go index bb724e640..fb8b43ee5 100644 --- a/protocol/messenger_contact_verification.go +++ b/protocol/messenger_contact_verification.go @@ -1032,7 +1032,7 @@ func (m *Messenger) GetLatestVerificationRequestFrom(contactID string) (*verific func (m *Messenger) createOrUpdateOutgoingContactVerificationNotification(contact *Contact, response *MessengerResponse, vr *verification.Request, chatMessage *common.Message, replyMessage *common.Message) error { notification := &ActivityCenterNotification{ ID: types.FromHex(vr.ID), - Name: contact.CanonicalName(), + Name: contact.PrimaryName(), Type: ActivityCenterNotificationTypeContactVerification, Author: chatMessage.From, Message: chatMessage, @@ -1051,7 +1051,7 @@ func (m *Messenger) createOrUpdateOutgoingContactVerificationNotification(contac func (m *Messenger) createOrUpdateIncomingContactVerificationNotification(contact *Contact, messageState *ReceivedMessageState, vr *verification.Request, chatMessage *common.Message, replyMessage *common.Message) error { notification := &ActivityCenterNotification{ ID: types.FromHex(vr.ID), - Name: contact.CanonicalName(), + Name: contact.PrimaryName(), Type: ActivityCenterNotificationTypeContactVerification, Author: messageState.CurrentMessageState.Contact.ID, Message: chatMessage, diff --git a/protocol/messenger_contacts.go b/protocol/messenger_contacts.go index ab367f640..50a8c058c 100644 --- a/protocol/messenger_contacts.go +++ b/protocol/messenger_contacts.go @@ -513,7 +513,7 @@ func (m *Messenger) generateOutgoingContactRequestNotification(contact *Contact, return &ActivityCenterNotification{ ID: types.FromHex(contactRequest.ID), Type: ActivityCenterNotificationTypeContactRequest, - Name: contact.CanonicalName(), + Name: contact.PrimaryName(), Author: m.myHexIdentity(), Message: contactRequest, Timestamp: m.getTimesource().GetCurrentTime(), diff --git a/protocol/messenger_handler.go b/protocol/messenger_handler.go index 3ae76530c..a6f7d45bf 100644 --- a/protocol/messenger_handler.go +++ b/protocol/messenger_handler.go @@ -367,7 +367,7 @@ func (m *Messenger) createIncomingContactRequestNotification(contact *Contact, m notification := &ActivityCenterNotification{ ID: types.FromHex(contactRequest.ID), - Name: contact.CanonicalName(), + Name: contact.PrimaryName(), Message: contactRequest, Type: ActivityCenterNotificationTypeContactRequest, Author: messageState.CurrentMessageState.Contact.ID,