diff --git a/protos/Backups.proto b/protos/Backups.proto index 3f7f66322f6b..03bcaf9480f0 100644 --- a/protos/Backups.proto +++ b/protos/Backups.proto @@ -477,6 +477,7 @@ message ContactAttachment { optional string prefix = 3; optional string suffix = 4; optional string middleName = 5; + optional string nickname = 6; } message Phone { diff --git a/protos/SignalService.proto b/protos/SignalService.proto index ce106b505c9a..3bfdcbd357bf 100644 --- a/protos/SignalService.proto +++ b/protos/SignalService.proto @@ -212,7 +212,8 @@ message DataMessage { optional string prefix = 3; optional string suffix = 4; optional string middleName = 5; - optional string displayName = 6; + reserved /* displayName */ 6; + optional string nickname = 7; } message Phone { diff --git a/ts/components/conversation/ContactDetail.stories.tsx b/ts/components/conversation/ContactDetail.stories.tsx index b1c2af07ea0d..f734d35979d7 100644 --- a/ts/components/conversation/ContactDetail.stories.tsx +++ b/ts/components/conversation/ContactDetail.stories.tsx @@ -101,7 +101,6 @@ const fullContact = { prefix: 'Dr.', suffix: 'Jr.', middleName: 'James', - displayName: 'Jerry Jordan', }, number: [ { diff --git a/ts/components/conversation/TimelineMessage.stories.tsx b/ts/components/conversation/TimelineMessage.stories.tsx index 13a941e54597..2e9630b6dbdd 100644 --- a/ts/components/conversation/TimelineMessage.stories.tsx +++ b/ts/components/conversation/TimelineMessage.stories.tsx @@ -1916,7 +1916,6 @@ const fullContact = { prefix: 'Dr.', suffix: 'Jr.', middleName: 'James', - displayName: 'Jerry Jordan', }, number: [ { @@ -1987,7 +1986,7 @@ export const EmbeddedContactLoadingAvatar = Template.bind({}); EmbeddedContactLoadingAvatar.args = { contact: { name: { - displayName: 'Jerry Jordan', + nickname: 'Jerry', }, avatar: { avatar: fakeAttachment({ diff --git a/ts/test-node/types/EmbeddedContact_test.ts b/ts/test-node/types/EmbeddedContact_test.ts index fd6c96a2f7ba..5ba81be21993 100644 --- a/ts/test-node/types/EmbeddedContact_test.ts +++ b/ts/test-node/types/EmbeddedContact_test.ts @@ -47,21 +47,21 @@ describe('Contact', () => { }; describe('getName', () => { - it('returns displayName if provided', () => { + it('returns displayName if available', () => { const contact = { name: { - displayName: 'displayName', + nickname: 'nickname', givenName: 'givenName', familyName: 'familyName', }, organization: 'Somewhere, Inc.', }; - const expected = 'displayName'; + const expected = 'nickname'; const actual = getName(contact); assert.strictEqual(actual, expected); }); - it('returns organization if no displayName', () => { + it('returns full name if no displayName', () => { const contact = { name: { givenName: 'givenName', @@ -69,23 +69,21 @@ describe('Contact', () => { }, organization: 'Somewhere, Inc.', }; + const expected = 'givenName familyName'; + const actual = getName(contact); + assert.strictEqual(actual, expected); + }); + + it('returns organization if no displayName or full name', () => { + const contact = { + name: {}, + organization: 'Somewhere, Inc.', + }; const expected = 'Somewhere, Inc.'; const actual = getName(contact); assert.strictEqual(actual, expected); }); - it('returns givenName + familyName if no displayName or organization', () => { - const contact = { - name: { - givenName: 'givenName', - familyName: 'familyName', - }, - }; - const expected = 'givenName familyName'; - const actual = getName(contact); - assert.strictEqual(actual, expected); - }); - it('returns just givenName', () => { const contact = { name: { @@ -117,7 +115,7 @@ describe('Contact', () => { it('eliminates avatar if it has had an attachment download error', () => { const contact = { name: { - displayName: 'displayName', + nickname: 'nickname', givenName: 'givenName', familyName: 'familyName', }, @@ -132,7 +130,7 @@ describe('Contact', () => { }; const expected = { name: { - displayName: 'displayName', + nickname: 'nickname', givenName: 'givenName', familyName: 'familyName', }, @@ -153,7 +151,7 @@ describe('Contact', () => { it('does not calculate absolute path if avatar is pending', () => { const contact = { name: { - displayName: 'displayName', + nickname: 'nickname', givenName: 'givenName', familyName: 'familyName', }, @@ -169,7 +167,7 @@ describe('Contact', () => { }; const expected = { name: { - displayName: 'displayName', + nickname: 'nickname', givenName: 'givenName', familyName: 'familyName', }, @@ -199,7 +197,7 @@ describe('Contact', () => { const contact = { name: { - displayName: 'displayName', + nickname: 'nickname', givenName: 'givenName', familyName: 'familyName', }, @@ -214,7 +212,7 @@ describe('Contact', () => { }; const expected = { name: { - displayName: 'displayName', + nickname: 'nickname', givenName: 'givenName', familyName: 'familyName', }, @@ -251,7 +249,7 @@ describe('Contact', () => { contact: [ { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -282,7 +280,7 @@ describe('Contact', () => { contact: [ { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -295,7 +293,7 @@ describe('Contact', () => { }; const expected = { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -324,7 +322,7 @@ describe('Contact', () => { contact: [ { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -340,7 +338,7 @@ describe('Contact', () => { }; const expected = { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -372,7 +370,7 @@ describe('Contact', () => { contact: [ { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -404,7 +402,7 @@ describe('Contact', () => { }; const expected = { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -454,7 +452,7 @@ describe('Contact', () => { contact: [ { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -472,7 +470,7 @@ describe('Contact', () => { }; const expected = { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, email: [ { @@ -501,7 +499,7 @@ describe('Contact', () => { contact: [ { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -519,7 +517,7 @@ describe('Contact', () => { }; const expected = { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -551,7 +549,7 @@ describe('Contact', () => { contact: [ { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [ { @@ -568,7 +566,7 @@ describe('Contact', () => { }; const expected = { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, }; const result = await upgradeVersion(message.contact[0], { @@ -635,7 +633,7 @@ describe('Contact', () => { const messageId = 'the-message-id'; const contact = { name: { - displayName: 'Someone Somewhere', + nickname: 'Someone Somewhere', }, number: [], email: [], diff --git a/ts/test-node/types/Message2_test.ts b/ts/test-node/types/Message2_test.ts index 8b0f42a00153..60b46da6be51 100644 --- a/ts/test-node/types/Message2_test.ts +++ b/ts/test-node/types/Message2_test.ts @@ -673,7 +673,7 @@ describe('Message', () => { contact: [ { name: { - displayName: 'Someone somewhere', + nickname: 'Someone somewhere', }, }, ], @@ -683,7 +683,7 @@ describe('Message', () => { contact: [ { name: { - displayName: 'Someone somewhere', + nickname: 'Someone somewhere', }, }, ], diff --git a/ts/textsecure/SendMessage.ts b/ts/textsecure/SendMessage.ts index d7b10b11bcbd..bfb51c97dc00 100644 --- a/ts/textsecure/SendMessage.ts +++ b/ts/textsecure/SendMessage.ts @@ -435,7 +435,7 @@ class Message { prefix: contact.name.prefix, suffix: contact.name.suffix, middleName: contact.name.middleName, - displayName: contact.name.displayName, + nickname: contact.name.nickname, }; contactProto.name = new Proto.DataMessage.Contact.Name(nameProto); } diff --git a/ts/types/EmbeddedContact.ts b/ts/types/EmbeddedContact.ts index 701a2c9a7817..0ab1699d4ba7 100644 --- a/ts/types/EmbeddedContact.ts +++ b/ts/types/EmbeddedContact.ts @@ -49,7 +49,7 @@ type Name = { prefix?: string; suffix?: string; middleName?: string; - displayName?: string; + nickname?: string; }; export enum ContactFormType { @@ -190,17 +190,31 @@ export function embeddedContactSelector( }; } +export function getDisplayName({ + name, + organization, +}: ReadonlyDeep): string | undefined { + // See https://github.com/signalapp/Signal-iOS-Private/blob/210a46037f12cdc6ad97ac6dceb64fbc43469f67/SignalServiceKit/Messages/Interactions/ContactShare/OWSContactName.swift#L87-L104 + if (name?.nickname) { + return name.nickname; + } + if (name?.givenName && name?.familyName) { + return `${name.givenName} ${name.familyName}`; + } + if (organization) { + return organization; + } + return undefined; +} + export function getName( contact: ReadonlyDeep ): string | undefined { - const { name, organization } = contact; - const displayName = (name && name.displayName) || undefined; + const { name } = contact; const givenName = (name && name.givenName) || undefined; const familyName = (name && name.familyName) || undefined; - const backupName = - (givenName && familyName && `${givenName} ${familyName}`) || undefined; - return displayName || organization || backupName || givenName || familyName; + return getDisplayName(contact) || givenName || familyName; } export function parseAndWriteAvatar( @@ -292,9 +306,9 @@ export function _validate( contact: EmbeddedContactType, { messageId }: { messageId: string } ): Error | undefined { - const { name, number, email, address, organization } = contact; + const { number, email, address, organization } = contact; - if ((!name || !name.displayName) && !organization) { + if (!getDisplayName(contact) && !organization) { return new Error( `Message ${messageId}: Contact had neither 'displayName' nor 'organization'` );