diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 078b8f4005..3f6360d521 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1652,6 +1652,10 @@ "message": "Verify Safety Number", "description": "Label on button included with safety number change notification in the conversation" }, + "cannotGenerateSafetyNumber": { + "message": "This user can't be verified until you've exchanged messages with them.", + "description": "Shown on the safety number screen if you have never exchanged messages with that contact" + }, "yourSafetyNumberWith": { "message": "Your safety number with $name1$:", "description": "Heading for safety number view", diff --git a/ts/components/SafetyNumberViewer.stories.tsx b/ts/components/SafetyNumberViewer.stories.tsx index 697c604bb8..85b4262f4e 100644 --- a/ts/components/SafetyNumberViewer.stories.tsx +++ b/ts/components/SafetyNumberViewer.stories.tsx @@ -3,7 +3,7 @@ import { action } from '@storybook/addon-actions'; import { boolean, text } from '@storybook/addon-knobs'; import { storiesOf } from '@storybook/react'; -import { SafetyNumberViewer } from './SafetyNumberViewer'; +import { PropsType, SafetyNumberViewer } from './SafetyNumberViewer'; import { ConversationType } from '../state/ducks/conversations'; import { setup as setupI18n } from '../../js/modules/i18n'; import enMessages from '../../_locales/en/messages.json'; @@ -45,88 +45,102 @@ const contactWithNothing = { phoneNumber: undefined, } as ConversationType; -const defaultProps = { - contact: contactWithAllData, +const createProps = (overrideProps: Partial = {}): PropsType => ({ + contact: overrideProps.contact || contactWithAllData, generateSafetyNumber: action('generate-safety-number'), i18n, - safetyNumber: 'XXX', - safetyNumberChanged: false, + safetyNumber: text('safetyNumber', overrideProps.safetyNumber || 'XXX'), + safetyNumberChanged: boolean( + 'safetyNumberChanged', + overrideProps.safetyNumberChanged !== undefined + ? overrideProps.safetyNumberChanged + : false + ), toggleVerified: action('toggle-verified'), - verificationDisabled: false, -}; + verificationDisabled: boolean( + 'verificationDisabled', + overrideProps.verificationDisabled !== undefined + ? overrideProps.verificationDisabled + : false + ), + onClose: overrideProps.onClose, +}); -const permutations = [ - { - title: 'Safety Number', - props: {}, - }, - { - title: 'Safety Number (not verified)', - props: { - contact: { - ...contactWithAllData, - verified: false, - }, - }, - }, - { - title: 'Verification Disabled', - props: { - verificationDisabled: true, - }, - }, - { - title: 'Safety Number Changed', - props: { - safetyNumberChanged: true, - }, - }, - { - title: 'Safety Number (dialog close)', - props: { - onClose: action('close'), - }, - }, - { - title: 'Just Profile', - props: { - contact: contactWithJustProfile, - }, - }, - { - title: 'Just Number', - props: { - contact: contactWithJustNumber, - }, - }, - { - title: 'No display info', - props: { - contact: contactWithNothing, - }, - }, -]; +const story = storiesOf('Components/SafetyNumberViewer', module); -storiesOf('Components/SafetyNumberViewer', module) - .add('Knobs Playground', () => { - const safetyNumber = text('safetyNumber', 'XXX'); - const safetyNumberChanged = boolean('safetyNumberChanged', false); - const verificationDisabled = boolean('verificationDisabled', false); +story.add('Safety Number', () => { + return ; +}); - return ( - - ); - }) - .add('Iterations', () => { - return permutations.map(({ props, title }) => ( - <> -

{title}

- - - )); - }); +story.add('Safety Number (not verified)', () => { + return ( + + ); +}); + +story.add('Verification Disabled', () => { + return ( + + ); +}); + +story.add('Safety Number Changed', () => { + return ( + + ); +}); + +story.add('Safety Number (dialog close)', () => { + return ( + + ); +}); + +story.add('Just Profile and Number', () => { + return ( + + ); +}); + +story.add('Just Number', () => { + return ( + + ); +}); + +story.add('No Phone Number (cannot verify)', () => { + return ( + + ); +}); diff --git a/ts/components/SafetyNumberViewer.tsx b/ts/components/SafetyNumberViewer.tsx index 389794599c..07d6c5f016 100644 --- a/ts/components/SafetyNumberViewer.tsx +++ b/ts/components/SafetyNumberViewer.tsx @@ -4,7 +4,7 @@ import { LocalizerType } from '../types/Util'; import { getPlaceholder } from '../util/safetyNumber'; import { Intl } from './Intl'; -type SafetyNumberViewerProps = { +export type PropsType = { contact?: ConversationType; generateSafetyNumber: (contact: ConversationType) => void; i18n: LocalizerType; @@ -24,7 +24,7 @@ export const SafetyNumberViewer = ({ safetyNumberChanged, toggleVerified, verificationDisabled, -}: SafetyNumberViewerProps): JSX.Element | null => { +}: PropsType): JSX.Element | null => { React.useEffect(() => { if (!contact) { return; @@ -37,8 +37,19 @@ export const SafetyNumberViewer = ({ return null; } + if (!contact.phoneNumber) { + return ( +
+
+ {i18n('cannotGenerateSafetyNumber')} +
+
+ ); + } + const showNumber = Boolean(contact.name || contact.profileName); - const numberFragment = showNumber ? ` · ${contact.phoneNumber}` : ''; + const numberFragment = + showNumber && contact.phoneNumber ? ` · ${contact.phoneNumber}` : ''; const name = `${contact.title}${numberFragment}`; const boldName = ( {name}