Make it more difficult to blur avatars

This commit is contained in:
Evan Hahn 2021-05-07 17:21:10 -05:00 committed by GitHub
parent 1276368f94
commit d28678dbf9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
79 changed files with 1118 additions and 889 deletions

View file

@ -43,11 +43,13 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
overrideProps.conversationType || 'direct' overrideProps.conversationType || 'direct'
), ),
i18n, i18n,
isMe: false,
loading: boolean('loading', overrideProps.loading || false), loading: boolean('loading', overrideProps.loading || false),
name: text('name', overrideProps.name || ''), name: text('name', overrideProps.name || ''),
noteToSelf: boolean('noteToSelf', overrideProps.noteToSelf || false), noteToSelf: boolean('noteToSelf', overrideProps.noteToSelf || false),
onClick: action('onClick'), onClick: action('onClick'),
phoneNumber: text('phoneNumber', overrideProps.phoneNumber || ''), phoneNumber: text('phoneNumber', overrideProps.phoneNumber || ''),
sharedGroupNames: [],
size: 80, size: 80,
title: overrideProps.title || '', title: overrideProps.title || '',
}); });

View file

@ -40,14 +40,14 @@ export type Props = {
color?: ColorType; color?: ColorType;
loading?: boolean; loading?: boolean;
acceptedMessageRequest?: boolean; acceptedMessageRequest: boolean;
conversationType: 'group' | 'direct'; conversationType: 'group' | 'direct';
isMe?: boolean; isMe: boolean;
name?: string; name?: string;
noteToSelf?: boolean; noteToSelf?: boolean;
phoneNumber?: string; phoneNumber?: string;
profileName?: string; profileName?: string;
sharedGroupNames?: Array<string>; sharedGroupNames: Array<string>;
size: AvatarSize; size: AvatarSize;
title: string; title: string;
unblurredAvatarPath?: string; unblurredAvatarPath?: string;

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -28,6 +28,7 @@ const conversationTypeMap: Record<string, Props['conversationType']> = {
}; };
const createProps = (overrideProps: Partial<Props> = {}): Props => ({ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
acceptedMessageRequest: true,
avatarPath: text('avatarPath', overrideProps.avatarPath || ''), avatarPath: text('avatarPath', overrideProps.avatarPath || ''),
color: select('color', colorMap, overrideProps.color || 'blue'), color: select('color', colorMap, overrideProps.color || 'blue'),
conversationType: select( conversationType: select(
@ -36,6 +37,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
overrideProps.conversationType || 'direct' overrideProps.conversationType || 'direct'
), ),
i18n, i18n,
isMe: true,
name: text('name', overrideProps.name || ''), name: text('name', overrideProps.name || ''),
noteToSelf: boolean('noteToSelf', overrideProps.noteToSelf || false), noteToSelf: boolean('noteToSelf', overrideProps.noteToSelf || false),
onClick: action('onClick'), onClick: action('onClick'),
@ -43,6 +45,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
onViewPreferences: action('onViewPreferences'), onViewPreferences: action('onViewPreferences'),
phoneNumber: text('phoneNumber', overrideProps.phoneNumber || ''), phoneNumber: text('phoneNumber', overrideProps.phoneNumber || ''),
profileName: text('profileName', overrideProps.profileName || ''), profileName: text('profileName', overrideProps.profileName || ''),
sharedGroupNames: [],
size: 80, size: 80,
style: {}, style: {},
title: text('title', overrideProps.title || ''), title: text('title', overrideProps.title || ''),

View file

@ -24,18 +24,19 @@ import enMessages from '../../_locales/en/messages.json';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
const getConversation = () => ({ const getConversation = () =>
id: '3051234567', getDefaultConversation({
avatarPath: undefined, id: '3051234567',
color: select('Callee color', Colors, 'ultramarine' as ColorType), avatarPath: undefined,
title: text('Callee Title', 'Rick Sanchez'), color: select('Callee color', Colors, 'ultramarine' as ColorType),
name: text('Callee Name', 'Rick Sanchez'), title: text('Callee Title', 'Rick Sanchez'),
phoneNumber: '3051234567', name: text('Callee Name', 'Rick Sanchez'),
profileName: 'Rick Sanchez', phoneNumber: '3051234567',
markedUnread: false, profileName: 'Rick Sanchez',
type: 'direct' as ConversationTypeType, markedUnread: false,
lastUpdated: Date.now(), type: 'direct' as ConversationTypeType,
}); lastUpdated: Date.now(),
});
const getCommonActiveCallData = () => ({ const getCommonActiveCallData = () => ({
conversation: getConversation(), conversation: getConversation(),

View file

@ -14,6 +14,7 @@ type Props = {
| 'acceptedMessageRequest' | 'acceptedMessageRequest'
| 'avatarPath' | 'avatarPath'
| 'color' | 'color'
| 'isMe'
| 'name' | 'name'
| 'phoneNumber' | 'phoneNumber'
| 'profileName' | 'profileName'
@ -49,10 +50,12 @@ export const CallNeedPermissionScreen: React.FC<Props> = ({
noteToSelf={false} noteToSelf={false}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={conversation.isMe}
name={conversation.name} name={conversation.name}
phoneNumber={conversation.phoneNumber} phoneNumber={conversation.phoneNumber}
profileName={conversation.profileName} profileName={conversation.profileName}
title={conversation.title} title={conversation.title}
sharedGroupNames={conversation.sharedGroupNames}
size={112} size={112}
/> />

View file

@ -28,7 +28,7 @@ const MAX_PARTICIPANTS = 32;
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
const conversation = { const conversation = getDefaultConversation({
id: '3051234567', id: '3051234567',
avatarPath: undefined, avatarPath: undefined,
color: Colors[0], color: Colors[0],
@ -36,10 +36,7 @@ const conversation = {
name: 'Rick Sanchez', name: 'Rick Sanchez',
phoneNumber: '3051234567', phoneNumber: '3051234567',
profileName: 'Rick Sanchez', profileName: 'Rick Sanchez',
markedUnread: false, });
type: 'direct' as const,
lastUpdated: Date.now(),
};
type OverridePropsBase = { type OverridePropsBase = {
hasLocalAudio?: boolean; hasLocalAudio?: boolean;

View file

@ -273,15 +273,20 @@ export const CallScreen: React.FC<PropsType> = ({
<div className="module-ongoing-call__local-preview-fullsize"> <div className="module-ongoing-call__local-preview-fullsize">
<CallBackgroundBlur avatarPath={me.avatarPath} color={me.color}> <CallBackgroundBlur avatarPath={me.avatarPath} color={me.color}>
<Avatar <Avatar
acceptedMessageRequest
avatarPath={me.avatarPath} avatarPath={me.avatarPath}
color={me.color || 'ultramarine'} color={me.color || 'ultramarine'}
noteToSelf={false} noteToSelf={false}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe
name={me.name} name={me.name}
phoneNumber={me.phoneNumber} phoneNumber={me.phoneNumber}
profileName={me.profileName} profileName={me.profileName}
title={me.title} title={me.title}
// `sharedGroupNames` makes no sense for yourself, but `<Avatar>` needs it
// to determine blurring.
sharedGroupNames={[]}
size={80} size={80}
/> />
<div className="module-calling__video-off--container"> <div className="module-calling__video-off--container">
@ -336,15 +341,19 @@ export const CallScreen: React.FC<PropsType> = ({
{!hasLocalVideo && !isLonelyInGroup ? ( {!hasLocalVideo && !isLonelyInGroup ? (
<CallBackgroundBlur avatarPath={me.avatarPath} color={me.color}> <CallBackgroundBlur avatarPath={me.avatarPath} color={me.color}>
<Avatar <Avatar
acceptedMessageRequest
avatarPath={me.avatarPath} avatarPath={me.avatarPath}
color={me.color || 'ultramarine'} color={me.color || 'ultramarine'}
noteToSelf={false} noteToSelf={false}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe
name={me.name} name={me.name}
phoneNumber={me.phoneNumber} phoneNumber={me.phoneNumber}
profileName={me.profileName} profileName={me.profileName}
title={me.title} title={me.title}
// See comment above about `sharedGroupNames`.
sharedGroupNames={[]}
size={80} size={80}
/> />
</CallBackgroundBlur> </CallBackgroundBlur>

View file

@ -93,12 +93,17 @@ export const CallingParticipantsList = React.memo(
> >
<div> <div>
<Avatar <Avatar
acceptedMessageRequest={
participant.acceptedMessageRequest
}
avatarPath={participant.avatarPath} avatarPath={participant.avatarPath}
color={participant.color} color={participant.color}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={participant.isMe}
profileName={participant.profileName} profileName={participant.profileName}
title={participant.title} title={participant.title}
sharedGroupNames={participant.sharedGroupNames}
size={32} size={32}
/> />
{participant.uuid === ourUuid ? ( {participant.uuid === ourUuid ? (

View file

@ -7,7 +7,7 @@ import { boolean } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { ColorType } from '../types/Colors'; import { ColorType } from '../types/Colors';
import { ConversationTypeType } from '../state/ducks/conversations'; import { ConversationType } from '../state/ducks/conversations';
import { CallingPip, PropsType } from './CallingPip'; import { CallingPip, PropsType } from './CallingPip';
import { import {
ActiveCallType, ActiveCallType,
@ -16,13 +16,14 @@ import {
GroupCallConnectionState, GroupCallConnectionState,
GroupCallJoinState, GroupCallJoinState,
} from '../types/Calling'; } from '../types/Calling';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
import { fakeGetGroupCallVideoFrameSource } from '../test-both/helpers/fakeGetGroupCallVideoFrameSource'; import { fakeGetGroupCallVideoFrameSource } from '../test-both/helpers/fakeGetGroupCallVideoFrameSource';
import { setup as setupI18n } from '../../js/modules/i18n'; import { setup as setupI18n } from '../../js/modules/i18n';
import enMessages from '../../_locales/en/messages.json'; import enMessages from '../../_locales/en/messages.json';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
const conversation = { const conversation: ConversationType = getDefaultConversation({
id: '3051234567', id: '3051234567',
avatarPath: undefined, avatarPath: undefined,
color: 'ultramarine' as ColorType, color: 'ultramarine' as ColorType,
@ -30,10 +31,7 @@ const conversation = {
name: 'Rick Sanchez', name: 'Rick Sanchez',
phoneNumber: '3051234567', phoneNumber: '3051234567',
profileName: 'Rick Sanchez', profileName: 'Rick Sanchez',
markedUnread: false, });
type: 'direct' as ConversationTypeType,
lastUpdated: Date.now(),
};
const getCommonActiveCallData = () => ({ const getCommonActiveCallData = () => ({
conversation, conversation,
@ -73,7 +71,7 @@ story.add('Default', () => {
return <CallingPip {...props} />; return <CallingPip {...props} />;
}); });
story.add('Contact (with avatar)', () => { story.add('Contact (with avatar and no video)', () => {
const props = createProps({ const props = createProps({
activeCall: { activeCall: {
...defaultCall, ...defaultCall,
@ -81,6 +79,7 @@ story.add('Contact (with avatar)', () => {
...conversation, ...conversation,
avatarPath: 'https://www.fillmurray.com/64/64', avatarPath: 'https://www.fillmurray.com/64/64',
}, },
remoteParticipants: [{ hasRemoteVideo: false }],
}, },
}); });
return <CallingPip {...props} />; return <CallingPip {...props} />;

View file

@ -32,11 +32,14 @@ const NoVideo = ({
i18n: LocalizerType; i18n: LocalizerType;
}): JSX.Element => { }): JSX.Element => {
const { const {
acceptedMessageRequest,
avatarPath, avatarPath,
color, color,
isMe,
name, name,
phoneNumber, phoneNumber,
profileName, profileName,
sharedGroupNames,
title, title,
} = activeCall.conversation; } = activeCall.conversation;
@ -45,16 +48,19 @@ const NoVideo = ({
<CallBackgroundBlur avatarPath={avatarPath} color={color}> <CallBackgroundBlur avatarPath={avatarPath} color={color}>
<div className="module-calling-pip__video--avatar"> <div className="module-calling-pip__video--avatar">
<Avatar <Avatar
acceptedMessageRequest={acceptedMessageRequest}
avatarPath={avatarPath} avatarPath={avatarPath}
color={color || 'ultramarine'} color={color || 'ultramarine'}
noteToSelf={false} noteToSelf={false}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={isMe}
name={name} name={name}
phoneNumber={phoneNumber} phoneNumber={phoneNumber}
profileName={profileName} profileName={profileName}
title={title} title={title}
size={52} size={52}
sharedGroupNames={sharedGroupNames}
/> />
</div> </div>
</CallBackgroundBlur> </CallBackgroundBlur>

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -8,6 +8,7 @@ import { boolean, select } from '@storybook/addon-knobs';
import { storiesOf } from '@storybook/react'; import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
import { CompositionInput, Props } from './CompositionInput'; import { CompositionInput, Props } from './CompositionInput';
import { setup as setupI18n } from '../../js/modules/i18n'; import { setup as setupI18n } from '../../js/modules/i18n';
import enMessages from '../../_locales/en/messages.json'; import enMessages from '../../_locales/en/messages.json';
@ -105,20 +106,12 @@ story.add('Emojis', () => {
story.add('Mentions', () => { story.add('Mentions', () => {
const props = createProps({ const props = createProps({
sortedGroupMembers: [ sortedGroupMembers: [
{ getDefaultConversation({
id: '0',
type: 'direct',
lastUpdated: 0,
title: 'Kate Beaton', title: 'Kate Beaton',
markedUnread: false, }),
}, getDefaultConversation({
{
id: '0',
type: 'direct',
lastUpdated: 0,
title: 'Parry Gripp', title: 'Parry Gripp',
markedUnread: false, }),
},
], ],
draftText: 'send _ a message', draftText: 'send _ a message',
draftBodyRanges: [ draftBodyRanges: [

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -26,6 +26,7 @@ storiesOf('Components/ContactListItem', module)
name="Someone 🔥 Somewhere" name="Someone 🔥 Somewhere"
phoneNumber="(202) 555-0011" phoneNumber="(202) 555-0011"
profileName="🔥Flames🔥" profileName="🔥Flames🔥"
sharedGroupNames={[]}
avatarPath={gifUrl} avatarPath={gifUrl}
onClick={onClick} onClick={onClick}
/> />
@ -38,10 +39,12 @@ storiesOf('Components/ContactListItem', module)
type="direct" type="direct"
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title="Someone 🔥 Somewhere" title="Someone 🔥 Somewhere"
name="Someone 🔥 Somewhere" name="Someone 🔥 Somewhere"
phoneNumber="(202) 555-0011" phoneNumber="(202) 555-0011"
profileName="🔥Flames🔥" profileName="🔥Flames🔥"
sharedGroupNames={[]}
about="👍 Free to chat" about="👍 Free to chat"
avatarPath={gifUrl} avatarPath={gifUrl}
onClick={onClick} onClick={onClick}
@ -50,10 +53,12 @@ storiesOf('Components/ContactListItem', module)
type="direct" type="direct"
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title="Another ❄️ Yes" title="Another ❄️ Yes"
name="Another ❄️ Yes" name="Another ❄️ Yes"
phoneNumber="(202) 555-0011" phoneNumber="(202) 555-0011"
profileName="❄Ice❄" profileName="❄Ice❄"
sharedGroupNames={[]}
about="🙏 Be kind" about="🙏 Be kind"
avatarPath={gifUrl} avatarPath={gifUrl}
onClick={onClick} onClick={onClick}
@ -67,11 +72,13 @@ storiesOf('Components/ContactListItem', module)
type="direct" type="direct"
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
isAdmin isAdmin
title="Someone 🔥 Somewhere" title="Someone 🔥 Somewhere"
name="Someone 🔥 Somewhere" name="Someone 🔥 Somewhere"
phoneNumber="(202) 555-0011" phoneNumber="(202) 555-0011"
profileName="🔥Flames🔥" profileName="🔥Flames🔥"
sharedGroupNames={[]}
about="👍 This is my really long status message that I have in order to test line breaking" about="👍 This is my really long status message that I have in order to test line breaking"
avatarPath={gifUrl} avatarPath={gifUrl}
onClick={onClick} onClick={onClick}
@ -83,8 +90,11 @@ storiesOf('Components/ContactListItem', module)
<ContactListItem <ContactListItem
type="group" type="group"
i18n={i18n} i18n={i18n}
isMe={false}
isAdmin isAdmin
title="Group!" title="Group!"
sharedGroupNames={[]}
acceptedMessageRequest
about="👍 Free to chat" about="👍 Free to chat"
onClick={onClick} onClick={onClick}
/> />
@ -96,9 +106,11 @@ storiesOf('Components/ContactListItem', module)
type="direct" type="direct"
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
isAdmin isAdmin
title="(202) 555-0011" title="(202) 555-0011"
phoneNumber="(202) 555-0011" phoneNumber="(202) 555-0011"
sharedGroupNames={[]}
about="👍 Free to chat" about="👍 Free to chat"
avatarPath={gifUrl} avatarPath={gifUrl}
onClick={onClick} onClick={onClick}
@ -111,11 +123,13 @@ storiesOf('Components/ContactListItem', module)
type="direct" type="direct"
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title="Someone 🔥 Somewhere" title="Someone 🔥 Somewhere"
name="Someone 🔥 Somewhere" name="Someone 🔥 Somewhere"
color="teal" color="teal"
phoneNumber="(202) 555-0011" phoneNumber="(202) 555-0011"
profileName="🔥Flames🔥" profileName="🔥Flames🔥"
sharedGroupNames={[]}
about="👍 Free to chat" about="👍 Free to chat"
onClick={onClick} onClick={onClick}
/> />
@ -128,9 +142,11 @@ storiesOf('Components/ContactListItem', module)
acceptedMessageRequest acceptedMessageRequest
color="blue" color="blue"
i18n={i18n} i18n={i18n}
isMe={false}
phoneNumber="(202) 555-0011" phoneNumber="(202) 555-0011"
title="🔥Flames🔥" title="🔥Flames🔥"
profileName="🔥Flames🔥" profileName="🔥Flames🔥"
sharedGroupNames={[]}
about="👍 Free to chat" about="👍 Free to chat"
onClick={onClick} onClick={onClick}
/> />
@ -142,7 +158,9 @@ storiesOf('Components/ContactListItem', module)
type="direct" type="direct"
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
phoneNumber="(202) 555-0011" phoneNumber="(202) 555-0011"
sharedGroupNames={[]}
title="(202) 555-0011" title="(202) 555-0011"
onClick={onClick} onClick={onClick}
/> />
@ -154,8 +172,10 @@ storiesOf('Components/ContactListItem', module)
type="direct" type="direct"
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title="(202) 555-0011" title="(202) 555-0011"
about="👍 Free to chat" about="👍 Free to chat"
sharedGroupNames={[]}
phoneNumber="(202) 555-0011" phoneNumber="(202) 555-0011"
onClick={onClick} onClick={onClick}
/> />
@ -167,7 +187,9 @@ storiesOf('Components/ContactListItem', module)
type="direct" type="direct"
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title="Unknown contact" title="Unknown contact"
sharedGroupNames={[]}
onClick={onClick} onClick={onClick}
/> />
); );

View file

@ -39,6 +39,7 @@ export class ContactListItem extends React.Component<Props> {
avatarPath, avatarPath,
color, color,
i18n, i18n,
isMe,
name, name,
phoneNumber, phoneNumber,
profileName, profileName,
@ -55,6 +56,7 @@ export class ContactListItem extends React.Component<Props> {
color={color} color={color}
conversationType={type} conversationType={type}
i18n={i18n} i18n={i18n}
isMe={isMe}
name={name} name={name}
phoneNumber={phoneNumber} phoneNumber={phoneNumber}
profileName={profileName} profileName={profileName}

View file

@ -34,6 +34,7 @@ export const ContactPill: FunctionComponent<PropsType> = ({
color, color,
firstName, firstName,
i18n, i18n,
isMe,
id, id,
name, name,
phoneNumber, phoneNumber,
@ -54,6 +55,7 @@ export const ContactPill: FunctionComponent<PropsType> = ({
noteToSelf={false} noteToSelf={false}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={isMe}
name={name} name={name}
phoneNumber={phoneNumber} phoneNumber={phoneNumber}
profileName={profileName} profileName={profileName}

View file

@ -12,6 +12,7 @@ import enMessages from '../../_locales/en/messages.json';
import { ContactPills } from './ContactPills'; import { ContactPills } from './ContactPills';
import { ContactPill, PropsType as ContactPillPropsType } from './ContactPill'; import { ContactPill, PropsType as ContactPillPropsType } from './ContactPill';
import { gifUrl } from '../storybook/Fixtures'; import { gifUrl } from '../storybook/Fixtures';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
@ -19,30 +20,32 @@ const story = storiesOf('Components/Contact Pills', module);
type ContactType = Omit<ContactPillPropsType, 'i18n' | 'onClickRemove'>; type ContactType = Omit<ContactPillPropsType, 'i18n' | 'onClickRemove'>;
const contacts: Array<ContactType> = times(50, index => ({ const contacts: Array<ContactType> = times(50, index =>
color: 'red', getDefaultConversation({
id: `contact-${index}`, color: 'red',
isMe: false, id: `contact-${index}`,
name: `Contact ${index}`, name: `Contact ${index}`,
phoneNumber: '(202) 555-0001', phoneNumber: '(202) 555-0001',
profileName: `C${index}`, profileName: `C${index}`,
title: `Contact ${index}`, title: `Contact ${index}`,
})); })
);
const contactPillProps = ( const contactPillProps = (
overrideProps?: ContactType overrideProps?: ContactType
): ContactPillPropsType => ({ ): ContactPillPropsType => ({
...(overrideProps || { ...(overrideProps ||
avatarPath: gifUrl, getDefaultConversation({
color: 'red', avatarPath: gifUrl,
firstName: 'John', color: 'red',
id: 'abc123', firstName: 'John',
isMe: false, id: 'abc123',
name: 'John Bon Bon Jovi', isMe: false,
phoneNumber: '(202) 555-0001', name: 'John Bon Bon Jovi',
profileName: 'JohnB', phoneNumber: '(202) 555-0001',
title: 'John Bon Bon Jovi', profileName: 'JohnB',
}), title: 'John Bon Bon Jovi',
})),
i18n, i18n,
onClickRemove: action('onClickRemove'), onClickRemove: action('onClickRemove'),
}); });

View file

@ -24,32 +24,21 @@ const i18n = setupI18n('en', enMessages);
const story = storiesOf('Components/ConversationList', module); const story = storiesOf('Components/ConversationList', module);
const defaultConversations: Array<ConversationListItemPropsType> = [ const defaultConversations: Array<ConversationListItemPropsType> = [
{ getDefaultConversation({
id: 'fred-convo', id: 'fred-convo',
isSelected: false,
lastUpdated: Date.now(),
markedUnread: false,
title: 'Fred Willard', title: 'Fred Willard',
type: 'direct', }),
}, getDefaultConversation({
{
id: 'marc-convo', id: 'marc-convo',
isSelected: true, isSelected: true,
lastUpdated: Date.now(),
markedUnread: false,
unreadCount: 12, unreadCount: 12,
title: 'Marc Barraca', title: 'Marc Barraca',
type: 'direct', }),
}, getDefaultConversation({
{
id: 'long-name-convo', id: 'long-name-convo',
isSelected: false,
lastUpdated: Date.now(),
markedUnread: false,
title: title:
'Pablo Diego José Francisco de Paula Juan Nepomuceno María de los Remedios Cipriano de la Santísima Trinidad Ruiz y Picasso', 'Pablo Diego José Francisco de Paula Juan Nepomuceno María de los Remedios Cipriano de la Santísima Trinidad Ruiz y Picasso',
type: 'direct', }),
},
getDefaultConversation(), getDefaultConversation(),
]; ];
@ -247,6 +236,7 @@ story.add('Contact checkboxes: disabled', () => (
'lastUpdated', 'lastUpdated',
new Date(overrideProps.lastUpdated || Date.now() - 5 * 60 * 1000) new Date(overrideProps.lastUpdated || Date.now() - 5 * 60 * 1000)
), ),
sharedGroupNames: [],
}); });
const renderConversation = ( const renderConversation = (

View file

@ -4,7 +4,6 @@
import React, { useRef, useEffect } from 'react'; import React, { useRef, useEffect } from 'react';
import { SetRendererCanvasType } from '../state/ducks/calling'; import { SetRendererCanvasType } from '../state/ducks/calling';
import { ConversationType } from '../state/ducks/conversations'; import { ConversationType } from '../state/ducks/conversations';
import { ColorType } from '../types/Colors';
import { LocalizerType } from '../types/Util'; import { LocalizerType } from '../types/Util';
import { Avatar } from './Avatar'; import { Avatar } from './Avatar';
@ -43,33 +42,43 @@ export const DirectCallRemoteParticipant: React.FC<PropsType> = ({
function renderAvatar( function renderAvatar(
i18n: LocalizerType, i18n: LocalizerType,
{ {
acceptedMessageRequest,
avatarPath, avatarPath,
color, color,
isMe,
name, name,
phoneNumber, phoneNumber,
profileName, profileName,
sharedGroupNames,
title, title,
}: { }: Pick<
avatarPath?: string; ConversationType,
color?: ColorType; | 'acceptedMessageRequest'
title: string; | 'avatarPath'
name?: string; | 'color'
phoneNumber?: string; | 'isMe'
profileName?: string; | 'name'
} | 'phoneNumber'
| 'profileName'
| 'sharedGroupNames'
| 'title'
>
): JSX.Element { ): JSX.Element {
return ( return (
<div className="module-ongoing-call__remote-video-disabled"> <div className="module-ongoing-call__remote-video-disabled">
<Avatar <Avatar
acceptedMessageRequest={acceptedMessageRequest}
avatarPath={avatarPath} avatarPath={avatarPath}
color={color || 'ultramarine'} color={color || 'ultramarine'}
noteToSelf={false} noteToSelf={false}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={isMe}
name={name} name={name}
phoneNumber={phoneNumber} phoneNumber={phoneNumber}
profileName={profileName} profileName={profileName}
title={title} title={title}
sharedGroupNames={sharedGroupNames}
size={112} size={112}
/> />
</div> </div>

View file

@ -54,13 +54,16 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
const { getFrameBuffer, getGroupCallVideoFrameSource, i18n } = props; const { getFrameBuffer, getGroupCallVideoFrameSource, i18n } = props;
const { const {
acceptedMessageRequest,
avatarPath, avatarPath,
color, color,
demuxId, demuxId,
hasRemoteAudio, hasRemoteAudio,
hasRemoteVideo, hasRemoteVideo,
isBlocked, isBlocked,
isMe,
profileName, profileName,
sharedGroupNames,
title, title,
videoAspectRatio, videoAspectRatio,
} = props.remoteParticipant; } = props.remoteParticipant;
@ -285,13 +288,16 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
</> </>
) : ( ) : (
<Avatar <Avatar
acceptedMessageRequest={acceptedMessageRequest}
avatarPath={avatarPath} avatarPath={avatarPath}
color={color || 'ultramarine'} color={color || 'ultramarine'}
noteToSelf={false} noteToSelf={false}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={isMe}
profileName={profileName} profileName={profileName}
title={title} title={title}
sharedGroupNames={sharedGroupNames}
size={avatarSize} size={avatarSize}
/> />
)} )}

View file

@ -99,8 +99,15 @@ GroupDialog.Contacts = ({ contacts, i18n }: Readonly<ContactsPropsType>) => (
{contacts.map(contact => ( {contacts.map(contact => (
<li key={contact.id} className="module-GroupDialog__contacts__contact"> <li key={contact.id} className="module-GroupDialog__contacts__contact">
<Avatar <Avatar
{...contact} acceptedMessageRequest={contact.acceptedMessageRequest}
avatarPath={contact.avatarPath}
color={contact.color}
conversationType={contact.type} conversationType={contact.type}
isMe={contact.isMe}
noteToSelf={contact.isMe}
title={contact.title}
unblurredAvatarPath={contact.unblurredAvatarPath}
sharedGroupNames={contact.sharedGroupNames}
size={AvatarSize.TWENTY_EIGHT} size={AvatarSize.TWENTY_EIGHT}
i18n={i18n} i18n={i18n}
/> />

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -8,37 +8,30 @@ import { boolean } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { GroupV1MigrationDialog, PropsType } from './GroupV1MigrationDialog'; import { GroupV1MigrationDialog, PropsType } from './GroupV1MigrationDialog';
import { ConversationType } from '../state/ducks/conversations';
import { setup as setupI18n } from '../../js/modules/i18n'; import { setup as setupI18n } from '../../js/modules/i18n';
import enMessages from '../../_locales/en/messages.json'; import enMessages from '../../_locales/en/messages.json';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
const contact1 = { const contact1: ConversationType = getDefaultConversation({
title: 'Alice', title: 'Alice',
number: '+1 (300) 555-0000', phoneNumber: '+1 (300) 555-0000',
id: 'guid-1', id: 'guid-1',
markedUnread: false, });
type: 'direct' as const,
lastUpdated: Date.now(),
};
const contact2 = { const contact2: ConversationType = getDefaultConversation({
title: 'Bob', title: 'Bob',
number: '+1 (300) 555-0001', phoneNumber: '+1 (300) 555-0001',
id: 'guid-2', id: 'guid-2',
markedUnread: false, });
type: 'direct' as const,
lastUpdated: Date.now(),
};
const contact3 = { const contact3: ConversationType = getDefaultConversation({
title: 'Chet', title: 'Chet',
number: '+1 (300) 555-0002', phoneNumber: '+1 (300) 555-0002',
id: 'guid-3', id: 'guid-3',
markedUnread: false, });
type: 'direct' as const,
lastUpdated: Date.now(),
};
function booleanOr(value: boolean | undefined, defaultValue: boolean): boolean { function booleanOr(value: boolean | undefined, defaultValue: boolean): boolean {
return isBoolean(value) ? value : defaultValue; return isBoolean(value) ? value : defaultValue;

View file

@ -4,7 +4,7 @@
import * as React from 'react'; import * as React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { LocalizerType } from '../types/Util'; import { LocalizerType } from '../types/Util';
import { Avatar } from './Avatar'; import { Avatar, AvatarBlur } from './Avatar';
import { Spinner } from './Spinner'; import { Spinner } from './Spinner';
import { Button, ButtonVariant } from './Button'; import { Button, ButtonVariant } from './Button';
@ -77,10 +77,14 @@ export const GroupV2JoinDialog = React.memo((props: PropsType) => {
/> />
<div className="module-group-v2-join-dialog__avatar"> <div className="module-group-v2-join-dialog__avatar">
<Avatar <Avatar
acceptedMessageRequest={false}
avatarPath={avatar ? avatar.url : undefined} avatarPath={avatar ? avatar.url : undefined}
blur={AvatarBlur.NoBlur}
loading={avatar && !avatar.url} loading={avatar && !avatar.url}
conversationType="group" conversationType="group"
title={title} title={title}
isMe={false}
sharedGroupNames={[]}
size={80} size={80}
i18n={i18n} i18n={i18n}
/> />

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -10,6 +10,7 @@ import { IncomingCallBar } from './IncomingCallBar';
import { Colors, ColorType } from '../types/Colors'; import { Colors, ColorType } from '../types/Colors';
import { setup as setupI18n } from '../../js/modules/i18n'; import { setup as setupI18n } from '../../js/modules/i18n';
import enMessages from '../../_locales/en/messages.json'; import enMessages from '../../_locales/en/messages.json';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
@ -21,15 +22,15 @@ const defaultProps = {
isIncoming: true, isIncoming: true,
isVideoCall: true, isVideoCall: true,
}, },
conversation: { conversation: getDefaultConversation({
id: '3051234567', id: '3051234567',
avatarPath: undefined, avatarPath: undefined,
contactColor: 'ultramarine' as ColorType, color: 'ultramarine' as ColorType,
name: 'Rick Sanchez', name: 'Rick Sanchez',
phoneNumber: '3051234567', phoneNumber: '3051234567',
profileName: 'Rick Sanchez', profileName: 'Rick Sanchez',
title: 'Rick Sanchez', title: 'Rick Sanchez',
}, }),
declineCall: action('decline-call'), declineCall: action('decline-call'),
i18n, i18n,
}; };

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import React from 'react'; import React from 'react';
@ -7,7 +7,7 @@ import { Tooltip } from './Tooltip';
import { Theme } from '../util/theme'; import { Theme } from '../util/theme';
import { ContactName } from './conversation/ContactName'; import { ContactName } from './conversation/ContactName';
import { LocalizerType } from '../types/Util'; import { LocalizerType } from '../types/Util';
import { ColorType } from '../types/Colors'; import { ConversationType } from '../state/ducks/conversations';
import { AcceptCallType, DeclineCallType } from '../state/ducks/calling'; import { AcceptCallType, DeclineCallType } from '../state/ducks/calling';
export type PropsType = { export type PropsType = {
@ -17,15 +17,19 @@ export type PropsType = {
call: { call: {
isVideoCall: boolean; isVideoCall: boolean;
}; };
conversation: { conversation: Pick<
id: string; ConversationType,
avatarPath?: string; | 'acceptedMessageRequest'
color?: ColorType; | 'avatarPath'
title: string; | 'color'
name?: string; | 'id'
phoneNumber?: string; | 'isMe'
profileName?: string; | 'name'
}; | 'phoneNumber'
| 'profileName'
| 'sharedGroupNames'
| 'title'
>;
}; };
type CallButtonProps = { type CallButtonProps = {
@ -66,12 +70,15 @@ export const IncomingCallBar = ({
const { isVideoCall } = call; const { isVideoCall } = call;
const { const {
id: conversationId, id: conversationId,
acceptedMessageRequest,
avatarPath, avatarPath,
color, color,
title, isMe,
name, name,
phoneNumber, phoneNumber,
profileName, profileName,
sharedGroupNames,
title,
} = conversation; } = conversation;
return ( return (
@ -79,15 +86,18 @@ export const IncomingCallBar = ({
<div className="module-incoming-call__contact"> <div className="module-incoming-call__contact">
<div className="module-incoming-call__contact--avatar"> <div className="module-incoming-call__contact--avatar">
<Avatar <Avatar
acceptedMessageRequest={acceptedMessageRequest}
avatarPath={avatarPath} avatarPath={avatarPath}
color={color || 'ultramarine'} color={color || 'ultramarine'}
noteToSelf={false} noteToSelf={false}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={isMe}
name={name} name={name}
phoneNumber={phoneNumber} phoneNumber={phoneNumber}
profileName={profileName} profileName={profileName}
title={title} title={title}
sharedGroupNames={sharedGroupNames}
size={52} size={52}
/> />
</div> </div>

View file

@ -9,83 +9,62 @@ import { storiesOf } from '@storybook/react';
import { LeftPane, LeftPaneMode, PropsType } from './LeftPane'; import { LeftPane, LeftPaneMode, PropsType } from './LeftPane';
import { CaptchaDialog } from './CaptchaDialog'; import { CaptchaDialog } from './CaptchaDialog';
import { PropsData as ConversationListItemPropsType } from './conversationList/ConversationListItem'; import { ConversationType } from '../state/ducks/conversations';
import { MessageSearchResult } from './conversationList/MessageSearchResult'; import { MessageSearchResult } from './conversationList/MessageSearchResult';
import { setup as setupI18n } from '../../js/modules/i18n'; import { setup as setupI18n } from '../../js/modules/i18n';
import enMessages from '../../_locales/en/messages.json'; import enMessages from '../../_locales/en/messages.json';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
const story = storiesOf('Components/LeftPane', module); const story = storiesOf('Components/LeftPane', module);
const defaultConversations: Array<ConversationListItemPropsType> = [ const defaultConversations: Array<ConversationType> = [
{ getDefaultConversation({
id: 'fred-convo', id: 'fred-convo',
isSelected: false,
lastUpdated: Date.now(),
markedUnread: false,
title: 'Fred Willard', title: 'Fred Willard',
type: 'direct', }),
}, getDefaultConversation({
{
id: 'marc-convo', id: 'marc-convo',
isSelected: true, isSelected: true,
lastUpdated: Date.now(),
markedUnread: false,
title: 'Marc Barraca', title: 'Marc Barraca',
type: 'direct', }),
},
]; ];
const defaultGroups: Array<ConversationListItemPropsType> = [ const defaultGroups: Array<ConversationType> = [
{ getDefaultConversation({
id: 'biking-group', id: 'biking-group',
isSelected: false,
lastUpdated: Date.now(),
markedUnread: false,
title: 'Mtn Biking Arizona 🚵☀️⛰', title: 'Mtn Biking Arizona 🚵☀️⛰',
type: 'group', type: 'group',
}, sharedGroupNames: [],
{ }),
getDefaultConversation({
id: 'dance-group', id: 'dance-group',
isSelected: false,
lastUpdated: Date.now(),
markedUnread: false,
title: 'Are we dancers? 💃', title: 'Are we dancers? 💃',
type: 'group', type: 'group',
}, sharedGroupNames: [],
}),
]; ];
const defaultArchivedConversations: Array<ConversationListItemPropsType> = [ const defaultArchivedConversations: Array<ConversationType> = [
{ getDefaultConversation({
id: 'michelle-archive-convo', id: 'michelle-archive-convo',
isSelected: false,
lastUpdated: Date.now(),
markedUnread: false,
title: 'Michelle Mercure', title: 'Michelle Mercure',
type: 'direct', isArchived: true,
}, }),
]; ];
const pinnedConversations: Array<ConversationListItemPropsType> = [ const pinnedConversations: Array<ConversationType> = [
{ getDefaultConversation({
id: 'philly-convo', id: 'philly-convo',
isPinned: true, isPinned: true,
isSelected: false,
lastUpdated: Date.now(),
markedUnread: false,
title: 'Philip Glass', title: 'Philip Glass',
type: 'direct', }),
}, getDefaultConversation({
{
id: 'robbo-convo', id: 'robbo-convo',
isPinned: true, isPinned: true,
isSelected: false,
lastUpdated: Date.now(),
markedUnread: false,
title: 'Robert Moog', title: 'Robert Moog',
type: 'direct', }),
},
]; ];
const defaultModeSpecificProps = { const defaultModeSpecificProps = {

View file

@ -368,6 +368,7 @@ export class MainHeader extends React.Component<PropsType, StateType> {
<Reference> <Reference>
{({ ref }) => ( {({ ref }) => (
<Avatar <Avatar
acceptedMessageRequest
avatarPath={avatarPath} avatarPath={avatarPath}
className="module-main-header__avatar" className="module-main-header__avatar"
color={color} color={color}
@ -378,6 +379,9 @@ export class MainHeader extends React.Component<PropsType, StateType> {
phoneNumber={phoneNumber} phoneNumber={phoneNumber}
profileName={profileName} profileName={profileName}
title={title} title={title}
// `sharedGroupNames` makes no sense for yourself, but `<Avatar>` needs it
// to determine blurring.
sharedGroupNames={[]}
size={28} size={28}
innerRef={ref} innerRef={ref}
onClick={this.showAvatarPopup} onClick={this.showAvatarPopup}
@ -389,8 +393,10 @@ export class MainHeader extends React.Component<PropsType, StateType> {
<Popper placement="bottom-end"> <Popper placement="bottom-end">
{({ ref, style }) => ( {({ ref, style }) => (
<AvatarPopup <AvatarPopup
acceptedMessageRequest
innerRef={ref} innerRef={ref}
i18n={i18n} i18n={i18n}
isMe
style={{ ...style, zIndex: 1 }} style={{ ...style, zIndex: 1 }}
color={color} color={color}
conversationType="direct" conversationType="direct"
@ -400,6 +406,8 @@ export class MainHeader extends React.Component<PropsType, StateType> {
title={title} title={title}
avatarPath={avatarPath} avatarPath={avatarPath}
size={28} size={28}
// See the comment above about `sharedGroupNames`.
sharedGroupNames={[]}
onViewPreferences={() => { onViewPreferences={() => {
showSettings(); showSettings();
this.hideAvatarPopup(); this.hideAvatarPopup();

View file

@ -10,26 +10,13 @@ import { NewlyCreatedGroupInvitedContactsDialog } from './NewlyCreatedGroupInvit
import { setup as setupI18n } from '../../js/modules/i18n'; import { setup as setupI18n } from '../../js/modules/i18n';
import enMessages from '../../_locales/en/messages.json'; import enMessages from '../../_locales/en/messages.json';
import { ConversationType } from '../state/ducks/conversations'; import { ConversationType } from '../state/ducks/conversations';
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
const conversations: Array<ConversationType> = [ const conversations: Array<ConversationType> = [
{ getDefaultConversation({ title: 'Fred Willard' }),
id: 'fred-convo', getDefaultConversation({ title: 'Marc Barraca' }),
isSelected: false,
lastUpdated: Date.now(),
markedUnread: false,
title: 'Fred Willard',
type: 'direct',
},
{
id: 'marc-convo',
isSelected: true,
lastUpdated: Date.now(),
markedUnread: false,
title: 'Marc Barraca',
type: 'direct',
},
]; ];
const story = storiesOf( const story = storiesOf(

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -6,13 +6,13 @@ import { action } from '@storybook/addon-actions';
import { storiesOf } from '@storybook/react'; import { storiesOf } from '@storybook/react';
import { SafetyNumberChangeDialog } from './SafetyNumberChangeDialog'; import { SafetyNumberChangeDialog } from './SafetyNumberChangeDialog';
import { ConversationType } from '../state/ducks/conversations'; import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
import { setup as setupI18n } from '../../js/modules/i18n'; import { setup as setupI18n } from '../../js/modules/i18n';
import enMessages from '../../_locales/en/messages.json'; import enMessages from '../../_locales/en/messages.json';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
const contactWithAllData = { const contactWithAllData = getDefaultConversation({
id: 'abc', id: 'abc',
avatarPath: undefined, avatarPath: undefined,
color: 'signal-blue', color: 'signal-blue',
@ -20,9 +20,9 @@ const contactWithAllData = {
title: 'Rick Sanchez', title: 'Rick Sanchez',
name: 'Rick Sanchez', name: 'Rick Sanchez',
phoneNumber: '(305) 123-4567', phoneNumber: '(305) 123-4567',
} as ConversationType; });
const contactWithJustProfile = { const contactWithJustProfile = getDefaultConversation({
id: 'def', id: 'def',
avatarPath: undefined, avatarPath: undefined,
color: 'signal-blue', color: 'signal-blue',
@ -30,9 +30,9 @@ const contactWithJustProfile = {
profileName: '-*Smartest Dude*-', profileName: '-*Smartest Dude*-',
name: undefined, name: undefined,
phoneNumber: '(305) 123-4567', phoneNumber: '(305) 123-4567',
} as ConversationType; });
const contactWithJustNumber = { const contactWithJustNumber = getDefaultConversation({
id: 'xyz', id: 'xyz',
avatarPath: undefined, avatarPath: undefined,
color: 'signal-blue', color: 'signal-blue',
@ -40,9 +40,9 @@ const contactWithJustNumber = {
name: undefined, name: undefined,
title: '(305) 123-4567', title: '(305) 123-4567',
phoneNumber: '(305) 123-4567', phoneNumber: '(305) 123-4567',
} as ConversationType; });
const contactWithNothing = { const contactWithNothing = getDefaultConversation({
id: 'some-guid', id: 'some-guid',
avatarPath: undefined, avatarPath: undefined,
color: 'signal-blue', color: 'signal-blue',
@ -50,7 +50,7 @@ const contactWithNothing = {
name: undefined, name: undefined,
phoneNumber: undefined, phoneNumber: undefined,
title: 'Unknown contact', title: 'Unknown contact',
} as ConversationType; });
storiesOf('Components/SafetyNumberChangeDialog', module) storiesOf('Components/SafetyNumberChangeDialog', module)
.add('Single Contact Dialog', () => { .add('Single Contact Dialog', () => {

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -91,6 +91,7 @@ export const SafetyNumberChangeDialog = ({
color={contact.color} color={contact.color}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={contact.isMe}
name={contact.name} name={contact.name}
phoneNumber={contact.phoneNumber} phoneNumber={contact.phoneNumber}
profileName={contact.profileName} profileName={contact.profileName}

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -7,6 +7,7 @@ import { action } from '@storybook/addon-actions';
import { boolean } from '@storybook/addon-knobs'; import { boolean } from '@storybook/addon-knobs';
import { storiesOf } from '@storybook/react'; import { storiesOf } from '@storybook/react';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
import { ContactModal, PropsType } from './ContactModal'; import { ContactModal, PropsType } from './ContactModal';
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
@ -16,16 +17,13 @@ const i18n = setupI18n('en', enMessages);
const story = storiesOf('Components/Conversation/ContactModal', module); const story = storiesOf('Components/Conversation/ContactModal', module);
const defaultContact: ConversationType = { const defaultContact: ConversationType = getDefaultConversation({
id: 'abcdef', id: 'abcdef',
lastUpdated: Date.now(),
markedUnread: false,
areWeAdmin: false, areWeAdmin: false,
title: 'Pauline Oliveros', title: 'Pauline Oliveros',
type: 'direct',
phoneNumber: '(333) 444-5515', phoneNumber: '(333) 444-5515',
about: '👍 Free to chat', about: '👍 Free to chat',
}; });
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
areWeAdmin: boolean('areWeAdmin', overrideProps.areWeAdmin || false), areWeAdmin: boolean('areWeAdmin', overrideProps.areWeAdmin || false),

View file

@ -111,6 +111,7 @@ export const ContactModal = ({
color={contact.color} color={contact.color}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={contact.isMe}
name={contact.name} name={contact.name}
profileName={contact.profileName} profileName={contact.profileName}
sharedGroupNames={contact.sharedGroupNames} sharedGroupNames={contact.sharedGroupNames}

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import React, { ComponentProps } from 'react'; import React, { ComponentProps } from 'react';
@ -6,6 +6,7 @@ import React, { ComponentProps } from 'react';
import { storiesOf } from '@storybook/react'; import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { import {
@ -27,9 +28,10 @@ type ConversationHeaderStory = {
}; };
const commonProps = { const commonProps = {
...getDefaultConversation(),
showBackButton: false, showBackButton: false,
outgoingCallButtonStyle: OutgoingCallButtonStyle.Both, outgoingCallButtonStyle: OutgoingCallButtonStyle.Both,
markedUnread: false,
i18n, i18n,

View file

@ -30,6 +30,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
about={getAbout()} about={getAbout()}
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={getTitle()} title={getTitle()}
avatarPath={getAvatarPath()} avatarPath={getAvatarPath()}
name={getName()} name={getName()}
@ -50,6 +51,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
about={getAbout()} about={getAbout()}
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={getTitle()} title={getTitle()}
avatarPath={getAvatarPath()} avatarPath={getAvatarPath()}
name={getName()} name={getName()}
@ -70,6 +72,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
about={getAbout()} about={getAbout()}
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={getTitle()} title={getTitle()}
avatarPath={getAvatarPath()} avatarPath={getAvatarPath()}
name={getName()} name={getName()}
@ -90,6 +93,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
about={getAbout()} about={getAbout()}
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={getTitle()} title={getTitle()}
avatarPath={getAvatarPath()} avatarPath={getAvatarPath()}
name={getName()} name={getName()}
@ -110,6 +114,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
about={getAbout()} about={getAbout()}
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={text('title', 'Cayce Bollard (profile)')} title={text('title', 'Cayce Bollard (profile)')}
avatarPath={getAvatarPath()} avatarPath={getAvatarPath()}
name={text('name', '')} name={text('name', '')}
@ -130,6 +135,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
about={getAbout()} about={getAbout()}
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={text('title', '+1 (646) 327-2700')} title={text('title', '+1 (646) 327-2700')}
avatarPath={getAvatarPath()} avatarPath={getAvatarPath()}
name={text('name', '')} name={text('name', '')}
@ -148,6 +154,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
<div style={{ width: '480px' }}> <div style={{ width: '480px' }}>
<ConversationHero <ConversationHero
i18n={i18n} i18n={i18n}
isMe={false}
title={text('title', 'Unknown contact')} title={text('title', 'Unknown contact')}
acceptedMessageRequest acceptedMessageRequest
avatarPath={getAvatarPath()} avatarPath={getAvatarPath()}
@ -167,6 +174,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
<div style={{ width: '480px' }}> <div style={{ width: '480px' }}>
<ConversationHero <ConversationHero
i18n={i18n} i18n={i18n}
isMe={false}
title={text('title', 'Unknown contact')} title={text('title', 'Unknown contact')}
acceptedMessageRequest={false} acceptedMessageRequest={false}
avatarPath={getAvatarPath()} avatarPath={getAvatarPath()}
@ -187,10 +195,12 @@ storiesOf('Components/Conversation/ConversationHero', module)
<ConversationHero <ConversationHero
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={text('title', 'NYC Rock Climbers')} title={text('title', 'NYC Rock Climbers')}
name={text('groupName', 'NYC Rock Climbers')} name={text('groupName', 'NYC Rock Climbers')}
conversationType="group" conversationType="group"
membersCount={numberKnob('membersCount', 22)} membersCount={numberKnob('membersCount', 22)}
sharedGroupNames={[]}
unblurAvatar={action('unblurAvatar')} unblurAvatar={action('unblurAvatar')}
updateSharedGroups={updateSharedGroups} updateSharedGroups={updateSharedGroups}
/> />
@ -203,10 +213,12 @@ storiesOf('Components/Conversation/ConversationHero', module)
<ConversationHero <ConversationHero
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={text('title', 'NYC Rock Climbers')} title={text('title', 'NYC Rock Climbers')}
name={text('groupName', 'NYC Rock Climbers')} name={text('groupName', 'NYC Rock Climbers')}
conversationType="group" conversationType="group"
membersCount={1} membersCount={1}
sharedGroupNames={[]}
unblurAvatar={action('unblurAvatar')} unblurAvatar={action('unblurAvatar')}
updateSharedGroups={updateSharedGroups} updateSharedGroups={updateSharedGroups}
/> />
@ -219,10 +231,12 @@ storiesOf('Components/Conversation/ConversationHero', module)
<ConversationHero <ConversationHero
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={text('title', 'NYC Rock Climbers')} title={text('title', 'NYC Rock Climbers')}
name={text('groupName', 'NYC Rock Climbers')} name={text('groupName', 'NYC Rock Climbers')}
conversationType="group" conversationType="group"
membersCount={0} membersCount={0}
sharedGroupNames={[]}
unblurAvatar={action('unblurAvatar')} unblurAvatar={action('unblurAvatar')}
updateSharedGroups={updateSharedGroups} updateSharedGroups={updateSharedGroups}
/> />
@ -235,10 +249,12 @@ storiesOf('Components/Conversation/ConversationHero', module)
<ConversationHero <ConversationHero
acceptedMessageRequest acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={text('title', 'Unknown group')} title={text('title', 'Unknown group')}
name={text('groupName', '')} name={text('groupName', '')}
conversationType="group" conversationType="group"
membersCount={0} membersCount={0}
sharedGroupNames={[]}
unblurAvatar={action('unblurAvatar')} unblurAvatar={action('unblurAvatar')}
updateSharedGroups={updateSharedGroups} updateSharedGroups={updateSharedGroups}
/> />
@ -249,11 +265,13 @@ storiesOf('Components/Conversation/ConversationHero', module)
return ( return (
<div style={{ width: '480px' }}> <div style={{ width: '480px' }}>
<ConversationHero <ConversationHero
acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe isMe
title={getTitle()} title={getTitle()}
conversationType="direct" conversationType="direct"
phoneNumber={getPhoneNumber()} phoneNumber={getPhoneNumber()}
sharedGroupNames={[]}
unblurAvatar={action('unblurAvatar')} unblurAvatar={action('unblurAvatar')}
updateSharedGroups={updateSharedGroups} updateSharedGroups={updateSharedGroups}
/> />

View file

@ -17,7 +17,7 @@ export type Props = {
about?: string; about?: string;
acceptedMessageRequest?: boolean; acceptedMessageRequest?: boolean;
i18n: LocalizerType; i18n: LocalizerType;
isMe?: boolean; isMe: boolean;
membersCount?: number; membersCount?: number;
onHeightChange?: () => unknown; onHeightChange?: () => unknown;
phoneNumber?: string; phoneNumber?: string;
@ -179,18 +179,21 @@ export const ConversationHero = ({
{({ measureRef }) => ( {({ measureRef }) => (
<div className="module-conversation-hero" ref={measureRef}> <div className="module-conversation-hero" ref={measureRef}>
<Avatar <Avatar
i18n={i18n} acceptedMessageRequest={acceptedMessageRequest}
blur={avatarBlur}
color={color}
noteToSelf={isMe}
avatarPath={avatarPath} avatarPath={avatarPath}
blur={avatarBlur}
className="module-conversation-hero__avatar"
color={color}
conversationType={conversationType} conversationType={conversationType}
i18n={i18n}
isMe={isMe}
name={name} name={name}
noteToSelf={isMe}
onClick={avatarOnClick} onClick={avatarOnClick}
profileName={profileName} profileName={profileName}
title={title} sharedGroupNames={sharedGroupNames}
size={112} size={112}
className="module-conversation-hero__avatar" title={title}
/> />
<h1 className="module-conversation-hero__profile-name"> <h1 className="module-conversation-hero__profile-name">
{isMe ? ( {isMe ? (

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
/* eslint-disable-next-line max-classes-per-file */ /* eslint-disable-next-line max-classes-per-file */
@ -7,29 +7,24 @@ import { storiesOf } from '@storybook/react';
import { isBoolean } from 'lodash'; import { isBoolean } from 'lodash';
import { boolean } from '@storybook/addon-knobs'; import { boolean } from '@storybook/addon-knobs';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { GroupV1Migration, PropsType } from './GroupV1Migration'; import { GroupV1Migration, PropsType } from './GroupV1Migration';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
const contact1 = { const contact1 = getDefaultConversation({
title: 'Alice', title: 'Alice',
number: '+1 (300) 555-000', phoneNumber: '+1 (300) 555-000',
id: 'guid-1', id: 'guid-1',
markedUnread: false, });
type: 'direct' as const,
lastUpdated: Date.now(),
};
const contact2 = { const contact2 = getDefaultConversation({
title: 'Bob', title: 'Bob',
number: '+1 (300) 555-000', phoneNumber: '+1 (300) 555-000',
id: 'guid-2', id: 'guid-2',
markedUnread: false, });
type: 'direct' as const,
lastUpdated: Date.now(),
};
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
areWeInvited: boolean( areWeInvited: boolean(

View file

@ -5,7 +5,7 @@ import * as React from 'react';
import { isBoolean } from 'lodash'; import { isBoolean } from 'lodash';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { boolean, number, text, select } from '@storybook/addon-knobs'; import { boolean, number, text } from '@storybook/addon-knobs';
import { storiesOf } from '@storybook/react'; import { storiesOf } from '@storybook/react';
import { SignalService } from '../../protobuf'; import { SignalService } from '../../protobuf';
@ -25,6 +25,7 @@ import { computePeaks } from '../GlobalAudioContext';
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { pngUrl } from '../../storybook/Fixtures'; import { pngUrl } from '../../storybook/Fixtures';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
@ -67,18 +68,9 @@ const renderAudioAttachment: Props['renderAudioAttachment'] = props => (
<MessageAudioContainer {...props} /> <MessageAudioContainer {...props} />
); );
const createAuthorProp = (
overrides: Partial<Props['author']> = {}
): Props['author'] => ({
id: 'some-id',
color: select('authorColor', Colors, Colors[0]),
...overrides,
title: text('authorTitle', overrides.title || ''),
});
const createProps = (overrideProps: Partial<Props> = {}): Props => ({ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
attachments: overrideProps.attachments, attachments: overrideProps.attachments,
author: overrideProps.author || createAuthorProp(), author: overrideProps.author || getDefaultConversation(),
reducedMotion: boolean('reducedMotion', false), reducedMotion: boolean('reducedMotion', false),
bodyRanges: overrideProps.bodyRanges, bodyRanges: overrideProps.bodyRanges,
canReply: true, canReply: true,
@ -220,7 +212,7 @@ story.add('Pending', () => {
story.add('Collapsed Metadata', () => { story.add('Collapsed Metadata', () => {
const props = createProps({ const props = createProps({
author: createAuthorProp({ title: 'Fred Willard' }), author: getDefaultConversation({ title: 'Fred Willard' }),
collapseMetadata: true, collapseMetadata: true,
conversationType: 'group', conversationType: 'group',
text: 'Hello there from a pal!', text: 'Hello there from a pal!',
@ -254,83 +246,83 @@ story.add('Reactions (wider message)', () => {
reactions: [ reactions: [
{ {
emoji: '👍', emoji: '👍',
from: { from: getDefaultConversation({
isMe: true, isMe: true,
id: '+14155552672', id: '+14155552672',
phoneNumber: '+14155552672', phoneNumber: '+14155552672',
name: 'Me', name: 'Me',
title: 'Me', title: 'Me',
}, }),
timestamp: Date.now() - 10, timestamp: Date.now() - 10,
}, },
{ {
emoji: '👍', emoji: '👍',
from: { from: getDefaultConversation({
id: '+14155552672', id: '+14155552672',
phoneNumber: '+14155552672', phoneNumber: '+14155552672',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now() - 10, timestamp: Date.now() - 10,
}, },
{ {
emoji: '👍', emoji: '👍',
from: { from: getDefaultConversation({
id: '+14155552673', id: '+14155552673',
phoneNumber: '+14155552673', phoneNumber: '+14155552673',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now() - 10, timestamp: Date.now() - 10,
}, },
{ {
emoji: '😂', emoji: '😂',
from: { from: getDefaultConversation({
id: '+14155552674', id: '+14155552674',
phoneNumber: '+14155552674', phoneNumber: '+14155552674',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now() - 10, timestamp: Date.now() - 10,
}, },
{ {
emoji: '😂', emoji: '😂',
from: { from: getDefaultConversation({
id: '+14155552676', id: '+14155552676',
phoneNumber: '+14155552676', phoneNumber: '+14155552676',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now() - 10, timestamp: Date.now() - 10,
}, },
{ {
emoji: '😡', emoji: '😡',
from: { from: getDefaultConversation({
id: '+14155552677', id: '+14155552677',
phoneNumber: '+14155552677', phoneNumber: '+14155552677',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now() - 10, timestamp: Date.now() - 10,
}, },
{ {
emoji: '👎', emoji: '👎',
from: { from: getDefaultConversation({
id: '+14155552678', id: '+14155552678',
phoneNumber: '+14155552678', phoneNumber: '+14155552678',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now() - 10, timestamp: Date.now() - 10,
}, },
{ {
emoji: '❤️', emoji: '❤️',
from: { from: getDefaultConversation({
id: '+14155552679', id: '+14155552679',
phoneNumber: '+14155552679', phoneNumber: '+14155552679',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now() - 10, timestamp: Date.now() - 10,
}, },
], ],
@ -346,83 +338,83 @@ story.add('Reactions (short message)', () => {
reactions: [ reactions: [
{ {
emoji: '👍', emoji: '👍',
from: { from: getDefaultConversation({
isMe: true, isMe: true,
id: '+14155552672', id: '+14155552672',
phoneNumber: '+14155552672', phoneNumber: '+14155552672',
name: 'Me', name: 'Me',
title: 'Me', title: 'Me',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
{ {
emoji: '👍', emoji: '👍',
from: { from: getDefaultConversation({
id: '+14155552672', id: '+14155552672',
phoneNumber: '+14155552672', phoneNumber: '+14155552672',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
{ {
emoji: '👍', emoji: '👍',
from: { from: getDefaultConversation({
id: '+14155552673', id: '+14155552673',
phoneNumber: '+14155552673', phoneNumber: '+14155552673',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
{ {
emoji: '😂', emoji: '😂',
from: { from: getDefaultConversation({
id: '+14155552674', id: '+14155552674',
phoneNumber: '+14155552674', phoneNumber: '+14155552674',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
{ {
emoji: '😂', emoji: '😂',
from: { from: getDefaultConversation({
id: '+14155552676', id: '+14155552676',
phoneNumber: '+14155552676', phoneNumber: '+14155552676',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
{ {
emoji: '😡', emoji: '😡',
from: { from: getDefaultConversation({
id: '+14155552677', id: '+14155552677',
phoneNumber: '+14155552677', phoneNumber: '+14155552677',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
{ {
emoji: '👎', emoji: '👎',
from: { from: getDefaultConversation({
id: '+14155552678', id: '+14155552678',
phoneNumber: '+14155552678', phoneNumber: '+14155552678',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
{ {
emoji: '❤️', emoji: '❤️',
from: { from: getDefaultConversation({
id: '+14155552679', id: '+14155552679',
phoneNumber: '+14155552679', phoneNumber: '+14155552679',
name: 'Amelia Briggs', name: 'Amelia Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
], ],
@ -433,7 +425,7 @@ story.add('Reactions (short message)', () => {
story.add('Avatar in Group', () => { story.add('Avatar in Group', () => {
const props = createProps({ const props = createProps({
author: createAuthorProp({ avatarPath: pngUrl }), author: getDefaultConversation({ avatarPath: pngUrl }),
conversationType: 'group', conversationType: 'group',
status: 'sent', status: 'sent',
text: 'Hello it is me, the saxophone.', text: 'Hello it is me, the saxophone.',
@ -1000,7 +992,7 @@ story.add('Colors', () => {
{Colors.map(color => ( {Colors.map(color => (
<Message <Message
{...createProps({ {...createProps({
author: createAuthorProp({ color }), author: getDefaultConversation({ color }),
text: text:
'Hello there from a pal! I am sending a long message so that it will wrap a bit, since I like that look.', 'Hello there from a pal! I am sending a long message so that it will wrap a bit, since I like that look.',
})} })}

View file

@ -9,6 +9,7 @@ import { storiesOf } from '@storybook/react';
import { PropsData as MessageDataPropsType } from './Message'; import { PropsData as MessageDataPropsType } from './Message';
import { MessageDetail, Props } from './MessageDetail'; import { MessageDetail, Props } from './MessageDetail';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
@ -17,10 +18,10 @@ const i18n = setupI18n('en', enMessages);
const story = storiesOf('Components/Conversation/MessageDetail', module); const story = storiesOf('Components/Conversation/MessageDetail', module);
const defaultMessage: MessageDataPropsType = { const defaultMessage: MessageDataPropsType = {
author: { author: getDefaultConversation({
id: 'some-id', id: 'some-id',
title: 'Max', title: 'Max',
}, }),
canReply: true, canReply: true,
canDeleteForEveryone: true, canDeleteForEveryone: true,
canDownload: true, canDownload: true,
@ -39,13 +40,15 @@ const defaultMessage: MessageDataPropsType = {
const createProps = (overrideProps: Partial<Props> = {}): Props => ({ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
contacts: overrideProps.contacts || [ contacts: overrideProps.contacts || [
{ {
color: 'green', ...getDefaultConversation({
color: 'green',
title: 'Just Max',
}),
isOutgoingKeyError: false, isOutgoingKeyError: false,
isUnidentifiedDelivery: false, isUnidentifiedDelivery: false,
onSendAnyway: action('onSendAnyway'), onSendAnyway: action('onSendAnyway'),
onShowSafetyNumber: action('onShowSafetyNumber'), onShowSafetyNumber: action('onShowSafetyNumber'),
status: 'delivered', status: 'delivered',
title: 'Just Max',
}, },
], ],
errors: overrideProps.errors || [], errors: overrideProps.errors || [],
@ -98,49 +101,59 @@ story.add('Message Statuses', () => {
const props = createProps({ const props = createProps({
contacts: [ contacts: [
{ {
color: 'green', ...getDefaultConversation({
color: 'green',
title: 'Max',
}),
isOutgoingKeyError: false, isOutgoingKeyError: false,
isUnidentifiedDelivery: false, isUnidentifiedDelivery: false,
onSendAnyway: action('onSendAnyway'), onSendAnyway: action('onSendAnyway'),
onShowSafetyNumber: action('onShowSafetyNumber'), onShowSafetyNumber: action('onShowSafetyNumber'),
status: 'sent', status: 'sent',
title: 'Max',
}, },
{ {
color: 'blue', ...getDefaultConversation({
color: 'blue',
title: 'Sally',
}),
isOutgoingKeyError: false, isOutgoingKeyError: false,
isUnidentifiedDelivery: false, isUnidentifiedDelivery: false,
onSendAnyway: action('onSendAnyway'), onSendAnyway: action('onSendAnyway'),
onShowSafetyNumber: action('onShowSafetyNumber'), onShowSafetyNumber: action('onShowSafetyNumber'),
status: 'sending', status: 'sending',
title: 'Sally',
}, },
{ {
color: 'brown', ...getDefaultConversation({
color: 'brown',
title: 'Terry',
}),
isOutgoingKeyError: false, isOutgoingKeyError: false,
isUnidentifiedDelivery: false, isUnidentifiedDelivery: false,
onSendAnyway: action('onSendAnyway'), onSendAnyway: action('onSendAnyway'),
onShowSafetyNumber: action('onShowSafetyNumber'), onShowSafetyNumber: action('onShowSafetyNumber'),
status: 'partial-sent', status: 'partial-sent',
title: 'Terry',
}, },
{ {
color: 'light_green', ...getDefaultConversation({
color: 'light_green',
title: 'Theo',
}),
isOutgoingKeyError: false, isOutgoingKeyError: false,
isUnidentifiedDelivery: false, isUnidentifiedDelivery: false,
onSendAnyway: action('onSendAnyway'), onSendAnyway: action('onSendAnyway'),
onShowSafetyNumber: action('onShowSafetyNumber'), onShowSafetyNumber: action('onShowSafetyNumber'),
status: 'delivered', status: 'delivered',
title: 'Theo',
}, },
{ {
color: 'blue_grey', ...getDefaultConversation({
color: 'blue_grey',
title: 'Nikki',
}),
isOutgoingKeyError: false, isOutgoingKeyError: false,
isUnidentifiedDelivery: false, isUnidentifiedDelivery: false,
onSendAnyway: action('onSendAnyway'), onSendAnyway: action('onSendAnyway'),
onShowSafetyNumber: action('onShowSafetyNumber'), onShowSafetyNumber: action('onShowSafetyNumber'),
status: 'read', status: 'read',
title: 'Nikki',
}, },
], ],
message: { message: {
@ -191,16 +204,21 @@ story.add('All Errors', () => {
}, },
contacts: [ contacts: [
{ {
color: 'green', ...getDefaultConversation({
color: 'green',
title: 'Max',
}),
isOutgoingKeyError: true, isOutgoingKeyError: true,
isUnidentifiedDelivery: false, isUnidentifiedDelivery: false,
onSendAnyway: action('onSendAnyway'), onSendAnyway: action('onSendAnyway'),
onShowSafetyNumber: action('onShowSafetyNumber'), onShowSafetyNumber: action('onShowSafetyNumber'),
status: 'error', status: 'error',
title: 'Max',
}, },
{ {
color: 'blue', ...getDefaultConversation({
color: 'blue',
title: 'Sally',
}),
errors: [ errors: [
{ {
name: 'Big Error', name: 'Big Error',
@ -212,16 +230,17 @@ story.add('All Errors', () => {
onSendAnyway: action('onSendAnyway'), onSendAnyway: action('onSendAnyway'),
onShowSafetyNumber: action('onShowSafetyNumber'), onShowSafetyNumber: action('onShowSafetyNumber'),
status: 'error', status: 'error',
title: 'Sally',
}, },
{ {
color: 'brown', ...getDefaultConversation({
color: 'brown',
title: 'Terry',
}),
isOutgoingKeyError: true, isOutgoingKeyError: true,
isUnidentifiedDelivery: true, isUnidentifiedDelivery: true,
onSendAnyway: action('onSendAnyway'), onSendAnyway: action('onSendAnyway'),
onShowSafetyNumber: action('onShowSafetyNumber'), onShowSafetyNumber: action('onShowSafetyNumber'),
status: 'error', status: 'error',
title: 'Terry',
}, },
], ],
}); });

View file

@ -15,21 +15,25 @@ import {
PropsData as MessagePropsDataType, PropsData as MessagePropsDataType,
} from './Message'; } from './Message';
import { LocalizerType } from '../../types/Util'; import { LocalizerType } from '../../types/Util';
import { ColorType } from '../../types/Colors'; import { ConversationType } from '../../state/ducks/conversations';
import { assert } from '../../util/assert'; import { assert } from '../../util/assert';
export type Contact = { export type Contact = Pick<
ConversationType,
| 'acceptedMessageRequest'
| 'avatarPath'
| 'color'
| 'isMe'
| 'name'
| 'phoneNumber'
| 'profileName'
| 'sharedGroupNames'
| 'title'
| 'unblurredAvatarPath'
> & {
status: MessageStatusType | null; status: MessageStatusType | null;
acceptedMessageRequest?: boolean;
title: string;
phoneNumber?: string;
name?: string;
profileName?: string;
avatarPath?: string;
color?: ColorType;
isOutgoingKeyError: boolean; isOutgoingKeyError: boolean;
sharedGroupNames?: Array<string>;
isUnidentifiedDelivery: boolean; isUnidentifiedDelivery: boolean;
unblurredAvatarPath?: string; unblurredAvatarPath?: string;
@ -95,6 +99,7 @@ export class MessageDetail extends React.Component<Props> {
acceptedMessageRequest, acceptedMessageRequest,
avatarPath, avatarPath,
color, color,
isMe,
name, name,
phoneNumber, phoneNumber,
profileName, profileName,
@ -110,6 +115,7 @@ export class MessageDetail extends React.Component<Props> {
color={color} color={color}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={isMe}
name={name} name={name}
phoneNumber={phoneNumber} phoneNumber={phoneNumber}
profileName={profileName} profileName={profileName}

View file

@ -1,10 +1,11 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
import { storiesOf } from '@storybook/react'; import { storiesOf } from '@storybook/react';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { ProfileChangeNotification } from './ProfileChangeNotification'; import { ProfileChangeNotification } from './ProfileChangeNotification';
@ -16,14 +17,12 @@ storiesOf('Components/Conversation/ProfileChangeNotification', module)
return ( return (
<ProfileChangeNotification <ProfileChangeNotification
i18n={i18n} i18n={i18n}
changedContact={{ changedContact={getDefaultConversation({
id: 'some-guid', id: 'some-guid',
type: 'direct', type: 'direct',
title: 'Mr. Fire 🔥', title: 'Mr. Fire 🔥',
name: 'Mr. Fire 🔥', name: 'Mr. Fire 🔥',
lastUpdated: Date.now(), })}
markedUnread: false,
}}
change={{ change={{
type: 'name', type: 'name',
oldName: 'Mr. Fire 🔥 Old', oldName: 'Mr. Fire 🔥 Old',
@ -36,13 +35,11 @@ storiesOf('Components/Conversation/ProfileChangeNotification', module)
return ( return (
<ProfileChangeNotification <ProfileChangeNotification
i18n={i18n} i18n={i18n}
changedContact={{ changedContact={getDefaultConversation({
id: 'some-guid', id: 'some-guid',
type: 'direct', type: 'direct',
title: 'Mr. Fire 🔥', title: 'Mr. Fire 🔥',
lastUpdated: Date.now(), })}
markedUnread: false,
}}
change={{ change={{
type: 'name', type: 'name',
oldName: 'Mr. Fire 🔥 Old', oldName: 'Mr. Fire 🔥 Old',

View file

@ -21,16 +21,17 @@ import {
import { Props, Quote } from './Quote'; import { Props, Quote } from './Quote';
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
const story = storiesOf('Components/Conversation/Quote', module); const story = storiesOf('Components/Conversation/Quote', module);
const defaultMessageProps: MessagesProps = { const defaultMessageProps: MessagesProps = {
author: { author: getDefaultConversation({
id: 'some-id', id: 'some-id',
title: 'Person X', title: 'Person X',
}, }),
canReply: true, canReply: true,
canDeleteForEveryone: true, canDeleteForEveryone: true,
canDownload: true, canDownload: true,

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -9,6 +9,7 @@ import { storiesOf } from '@storybook/react';
import { Props, ReactionViewer } from './ReactionViewer'; import { Props, ReactionViewer } from './ReactionViewer';
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
@ -28,94 +29,94 @@ story.add('All Reactions', () => {
{ {
emoji: '❤️', emoji: '❤️',
timestamp: 1, timestamp: 1,
from: { from: getDefaultConversation({
id: '+14155552671', id: '+14155552671',
phoneNumber: '+14155552671', phoneNumber: '+14155552671',
profileName: 'Ameila Briggs', profileName: 'Ameila Briggs',
title: 'Amelia', title: 'Amelia',
}, }),
}, },
{ {
emoji: '❤️', emoji: '❤️',
timestamp: 2, timestamp: 2,
from: { from: getDefaultConversation({
id: '+14155552672', id: '+14155552672',
name: 'Adam Burrel', name: 'Adam Burrel',
title: 'Adam', title: 'Adam',
}, }),
}, },
{ {
emoji: '❤️', emoji: '❤️',
timestamp: 3, timestamp: 3,
from: { from: getDefaultConversation({
id: '+14155552673', id: '+14155552673',
name: 'Rick Owens', name: 'Rick Owens',
title: 'Rick', title: 'Rick',
}, }),
}, },
{ {
emoji: '❤️', emoji: '❤️',
timestamp: 4, timestamp: 4,
from: { from: getDefaultConversation({
id: '+14155552674', id: '+14155552674',
name: 'Bojack Horseman', name: 'Bojack Horseman',
title: 'Bojack', title: 'Bojack',
}, }),
}, },
{ {
emoji: '👍', emoji: '👍',
timestamp: 9, timestamp: 9,
from: { from: getDefaultConversation({
id: '+14155552678', id: '+14155552678',
phoneNumber: '+14155552678', phoneNumber: '+14155552678',
profileName: 'Adam Burrel', profileName: 'Adam Burrel',
title: 'Adam', title: 'Adam',
}, }),
}, },
{ {
emoji: '👎', emoji: '👎',
timestamp: 10, timestamp: 10,
from: { from: getDefaultConversation({
id: '+14155552673', id: '+14155552673',
name: 'Rick Owens', name: 'Rick Owens',
title: 'Rick', title: 'Rick',
}, }),
}, },
{ {
emoji: '😂', emoji: '😂',
timestamp: 11, timestamp: 11,
from: { from: getDefaultConversation({
id: '+14155552674', id: '+14155552674',
name: 'Bojack Horseman', name: 'Bojack Horseman',
title: 'Bojack', title: 'Bojack',
}, }),
}, },
{ {
emoji: '😮', emoji: '😮',
timestamp: 12, timestamp: 12,
from: { from: getDefaultConversation({
id: '+14155552675', id: '+14155552675',
name: 'Cayce Pollard', name: 'Cayce Pollard',
title: 'Cayce', title: 'Cayce',
}, }),
}, },
{ {
emoji: '😢', emoji: '😢',
timestamp: 13, timestamp: 13,
from: { from: getDefaultConversation({
id: '+14155552676', id: '+14155552676',
name: 'Foo McBarrington', name: 'Foo McBarrington',
title: 'Foo', title: 'Foo',
}, }),
}, },
{ {
emoji: '😡', emoji: '😡',
timestamp: 14, timestamp: 14,
from: { from: getDefaultConversation({
id: '+14155552676', id: '+14155552676',
name: 'Foo McBarrington', name: 'Foo McBarrington',
title: 'Foo', title: 'Foo',
}, }),
}, },
], ],
}); });
@ -128,22 +129,22 @@ story.add('Picked Reaction', () => {
reactions: [ reactions: [
{ {
emoji: '❤️', emoji: '❤️',
from: { from: getDefaultConversation({
id: '+14155552671', id: '+14155552671',
name: 'Amelia Briggs', name: 'Amelia Briggs',
isMe: true, isMe: true,
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
{ {
emoji: '👍', emoji: '👍',
from: { from: getDefaultConversation({
id: '+14155552671', id: '+14155552671',
phoneNumber: '+14155552671', phoneNumber: '+14155552671',
profileName: 'Joel Ferrari', profileName: 'Joel Ferrari',
title: 'Joel', title: 'Joel',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
], ],
@ -157,22 +158,22 @@ story.add('Picked Missing Reaction', () => {
reactions: [ reactions: [
{ {
emoji: '❤️', emoji: '❤️',
from: { from: getDefaultConversation({
id: '+14155552671', id: '+14155552671',
name: 'Amelia Briggs', name: 'Amelia Briggs',
isMe: true, isMe: true,
title: 'Amelia', title: 'Amelia',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
{ {
emoji: '👍', emoji: '👍',
from: { from: getDefaultConversation({
id: '+14155552671', id: '+14155552671',
phoneNumber: '+14155552671', phoneNumber: '+14155552671',
profileName: 'Joel Ferrari', profileName: 'Joel Ferrari',
title: 'Joel', title: 'Joel',
}, }),
timestamp: Date.now(), timestamp: Date.now(),
}, },
], ],
@ -196,11 +197,11 @@ const createReaction = (
timestamp = Date.now() timestamp = Date.now()
) => ({ ) => ({
emoji, emoji,
from: { from: getDefaultConversation({
id: '+14155552671', id: '+14155552671',
name, name,
title: name, title: name,
}, }),
timestamp, timestamp,
}); });

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -8,22 +8,25 @@ import { ContactName } from './ContactName';
import { Avatar, Props as AvatarProps } from '../Avatar'; import { Avatar, Props as AvatarProps } from '../Avatar';
import { Emoji } from '../emoji/Emoji'; import { Emoji } from '../emoji/Emoji';
import { useRestoreFocus } from '../../util/hooks'; import { useRestoreFocus } from '../../util/hooks';
import { ColorType } from '../../types/Colors'; import { ConversationType } from '../../state/ducks/conversations';
import { emojiToData, EmojiData } from '../emoji/lib'; import { emojiToData, EmojiData } from '../emoji/lib';
export type Reaction = { export type Reaction = {
emoji: string; emoji: string;
timestamp: number; timestamp: number;
from: { from: Pick<
id: string; ConversationType,
color?: ColorType; | 'acceptedMessageRequest'
avatarPath?: string; | 'avatarPath'
name?: string; | 'color'
profileName?: string; | 'id'
title: string; | 'isMe'
isMe?: boolean; | 'name'
phoneNumber?: string; | 'phoneNumber'
}; | 'profileName'
| 'sharedGroupNames'
| 'title'
>;
}; };
export type OwnProps = { export type OwnProps = {
@ -212,9 +215,12 @@ export const ReactionViewer = React.forwardRef<HTMLDivElement, Props>(
> >
<div className="module-reaction-viewer__body__row__avatar"> <div className="module-reaction-viewer__body__row__avatar">
<Avatar <Avatar
acceptedMessageRequest={from.acceptedMessageRequest}
avatarPath={from.avatarPath} avatarPath={from.avatarPath}
conversationType="direct" conversationType="direct"
sharedGroupNames={from.sharedGroupNames}
size={32} size={32}
isMe={from.isMe}
color={from.color} color={from.color}
name={from.name} name={from.name}
profileName={from.profileName} profileName={from.profileName}

View file

@ -318,7 +318,9 @@ const getPhoneNumber = () => text('phoneNumber', '+1 (808) 555-1234');
const renderHeroRow = () => ( const renderHeroRow = () => (
<ConversationHero <ConversationHero
about={getAbout()} about={getAbout()}
acceptedMessageRequest
i18n={i18n} i18n={i18n}
isMe={false}
title={getTitle()} title={getTitle()}
avatarPath={getAvatarPath()} avatarPath={getAvatarPath()}
name={getName()} name={getName()}
@ -333,11 +335,14 @@ const renderHeroRow = () => (
const renderLoadingRow = () => <TimelineLoadingRow state="loading" />; const renderLoadingRow = () => <TimelineLoadingRow state="loading" />;
const renderTypingBubble = () => ( const renderTypingBubble = () => (
<TypingBubble <TypingBubble
acceptedMessageRequest
color="red" color="red"
conversationType="direct" conversationType="direct"
phoneNumber="+18005552222" phoneNumber="+18005552222"
i18n={i18n} i18n={i18n}
isMe={false}
title="title" title="title"
sharedGroupNames={[]}
/> />
); );
@ -456,16 +461,14 @@ story.add('Typing Indicator', () => {
story.add('With invited contacts for a newly-created group', () => { story.add('With invited contacts for a newly-created group', () => {
const props = createProps({ const props = createProps({
invitedContactsForNewlyCreatedGroup: [ invitedContactsForNewlyCreatedGroup: [
{ getDefaultConversation({
id: 'abc123', id: 'abc123',
title: 'John Bon Bon Jovi', title: 'John Bon Bon Jovi',
type: 'direct', }),
}, getDefaultConversation({
{
id: 'def456', id: 'def456',
title: 'Bon John Bon Jovi', title: 'Bon John Bon Jovi',
type: 'direct', }),
},
], ],
}); });

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -15,6 +15,8 @@ const i18n = setupI18n('en', enMessages);
const story = storiesOf('Components/Conversation/TypingBubble', module); const story = storiesOf('Components/Conversation/TypingBubble', module);
const createProps = (overrideProps: Partial<Props> = {}): Props => ({ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
acceptedMessageRequest: true,
isMe: false,
i18n, i18n,
color: select( color: select(
'color', 'color',
@ -29,6 +31,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
{ group: 'group', direct: 'direct' }, { group: 'group', direct: 'direct' },
overrideProps.conversationType || 'direct' overrideProps.conversationType || 'direct'
), ),
sharedGroupNames: [],
}); });
story.add('Direct', () => { story.add('Direct', () => {

View file

@ -1,4 +1,4 @@
// Copyright 2018-2020 Signal Messenger, LLC // Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import React from 'react'; import React from 'react';
@ -8,15 +8,20 @@ import { TypingAnimation } from './TypingAnimation';
import { Avatar } from '../Avatar'; import { Avatar } from '../Avatar';
import { LocalizerType } from '../../types/Util'; import { LocalizerType } from '../../types/Util';
import { ColorType } from '../../types/Colors'; import { ConversationType } from '../../state/ducks/conversations';
export type Props = { export type Props = Pick<
avatarPath?: string; ConversationType,
color: ColorType; | 'acceptedMessageRequest'
name?: string; | 'avatarPath'
phoneNumber?: string; | 'color'
profileName?: string; | 'isMe'
title: string; | 'name'
| 'phoneNumber'
| 'profileName'
| 'sharedGroupNames'
| 'title'
> & {
conversationType: 'group' | 'direct'; conversationType: 'group' | 'direct';
i18n: LocalizerType; i18n: LocalizerType;
}; };
@ -24,14 +29,17 @@ export type Props = {
export class TypingBubble extends React.PureComponent<Props> { export class TypingBubble extends React.PureComponent<Props> {
public renderAvatar(): JSX.Element | null { public renderAvatar(): JSX.Element | null {
const { const {
acceptedMessageRequest,
avatarPath, avatarPath,
color, color,
conversationType,
i18n,
isMe,
name, name,
phoneNumber, phoneNumber,
profileName, profileName,
sharedGroupNames,
title, title,
conversationType,
i18n,
} = this.props; } = this.props;
if (conversationType !== 'group') { if (conversationType !== 'group') {
@ -42,14 +50,17 @@ export class TypingBubble extends React.PureComponent<Props> {
<div className="module-message__author-avatar-container"> <div className="module-message__author-avatar-container">
<div className="module-message__author-avatar"> <div className="module-message__author-avatar">
<Avatar <Avatar
acceptedMessageRequest={acceptedMessageRequest}
avatarPath={avatarPath} avatarPath={avatarPath}
color={color} color={color}
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe={isMe}
name={name} name={name}
phoneNumber={phoneNumber} phoneNumber={phoneNumber}
profileName={profileName} profileName={profileName}
title={title} title={title}
sharedGroupNames={sharedGroupNames}
size={28} size={28}
/> />
</div> </div>

View file

@ -1,10 +1,10 @@
// Copyright 2019-2020 Signal Messenger, LLC // Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { Avatar } from '../Avatar'; import { Avatar, AvatarBlur } from '../Avatar';
import { Spinner } from '../Spinner'; import { Spinner } from '../Spinner';
import { LocalizerType } from '../../types/Util'; import { LocalizerType } from '../../types/Util';
@ -45,11 +45,15 @@ export function renderAvatar({
return ( return (
<Avatar <Avatar
acceptedMessageRequest={false}
avatarPath={avatarPath} avatarPath={avatarPath}
blur={AvatarBlur.NoBlur}
color="grey" color="grey"
conversationType="direct" conversationType="direct"
i18n={i18n} i18n={i18n}
isMe
title={title} title={title}
sharedGroupNames={[]}
size={size} size={size}
/> />
); );

View file

@ -156,10 +156,12 @@ export const ChooseGroupMembersModal: FunctionComponent<PropsType> = ({
color={contact.color} color={contact.color}
firstName={contact.firstName} firstName={contact.firstName}
i18n={i18n} i18n={i18n}
isMe={contact.isMe}
id={contact.id} id={contact.id}
name={contact.name} name={contact.name}
phoneNumber={contact.phoneNumber} phoneNumber={contact.phoneNumber}
profileName={contact.profileName} profileName={contact.profileName}
sharedGroupNames={contact.sharedGroupNames}
title={contact.title} title={contact.title}
onClickRemove={() => { onClickRemove={() => {
removeSelectedContact(contact.id); removeSelectedContact(contact.id);

View file

@ -20,13 +20,13 @@ const story = storiesOf(
module module
); );
const conversation: ConversationType = { const conversation: ConversationType = getDefaultConversation({
id: '', id: '',
lastUpdated: 0, lastUpdated: 0,
markedUnread: false,
title: 'Some Conversation', title: 'Some Conversation',
type: 'group', type: 'group',
}; sharedGroupNames: [],
});
const createProps = (hasGroupLink = false): Props => ({ const createProps = (hasGroupLink = false): Props => ({
addMembers: async () => { addMembers: async () => {

View file

@ -7,6 +7,7 @@ import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { number, text } from '@storybook/addon-knobs'; import { number, text } from '@storybook/addon-knobs';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
import { setup as setupI18n } from '../../../../js/modules/i18n'; import { setup as setupI18n } from '../../../../js/modules/i18n';
import enMessages from '../../../../_locales/en/messages.json'; import enMessages from '../../../../_locales/en/messages.json';
import { ConversationType } from '../../../state/ducks/conversations'; import { ConversationType } from '../../../state/ducks/conversations';
@ -20,14 +21,14 @@ const story = storiesOf(
module module
); );
const createConversation = (): ConversationType => ({ const createConversation = (): ConversationType =>
id: '', getDefaultConversation({
markedUnread: false, id: '',
type: 'group', type: 'group',
lastUpdated: 0, lastUpdated: 0,
title: text('conversation title', 'Some Conversation'), title: text('conversation title', 'Some Conversation'),
memberships: new Array(number('conversation members length', 0)), memberships: new Array(number('conversation members length', 0)),
}); });
const createProps = (overrideProps: Partial<Props> = {}): Props => ({ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
conversation: createConversation(), conversation: createConversation(),

View file

@ -32,6 +32,7 @@ export const ConversationDetailsHeader: React.ComponentType<Props> = ({
i18n={i18n} i18n={i18n}
size={80} size={80}
{...conversation} {...conversation}
sharedGroupNames={[]}
/> />
<div> <div>
<div className={bem('title')}>{conversation.title}</div> <div className={bem('title')}>{conversation.title}</div>

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -35,20 +35,20 @@ function getConversation(
groupLink?: string, groupLink?: string,
accessControlAddFromInviteLink?: number accessControlAddFromInviteLink?: number
): ConversationType { ): ConversationType {
return { return getDefaultConversation({
id: '', id: '',
lastUpdated: 0, lastUpdated: 0,
markedUnread: false,
memberships: Array(32).fill({ member: getDefaultConversation({}) }), memberships: Array(32).fill({ member: getDefaultConversation({}) }),
pendingMemberships: Array(16).fill({ member: getDefaultConversation({}) }), pendingMemberships: Array(16).fill({ member: getDefaultConversation({}) }),
title: 'Some Conversation', title: 'Some Conversation',
type: 'group', type: 'group',
sharedGroupNames: [],
groupLink, groupLink,
accessControlAddFromInviteLink: accessControlAddFromInviteLink:
accessControlAddFromInviteLink !== undefined accessControlAddFromInviteLink !== undefined
? accessControlAddFromInviteLink ? accessControlAddFromInviteLink
: AccessEnum.UNSATISFIABLE, : AccessEnum.UNSATISFIABLE,
}; });
} }
const createProps = ( const createProps = (

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react'; import * as React from 'react';
@ -19,15 +19,15 @@ const story = storiesOf(
module module
); );
const conversation: ConversationType = { const conversation: ConversationType = getDefaultConversation({
id: '', id: '',
lastUpdated: 0, lastUpdated: 0,
markedUnread: false,
memberships: Array(32).fill({ member: getDefaultConversation({}) }), memberships: Array(32).fill({ member: getDefaultConversation({}) }),
pendingMemberships: Array(16).fill({ member: getDefaultConversation({}) }), pendingMemberships: Array(16).fill({ member: getDefaultConversation({}) }),
title: 'Some Conversation', title: 'Some Conversation',
type: 'group', type: 'group',
}; sharedGroupNames: [],
});
class AccessEnum { class AccessEnum {
static ANY = 0; static ANY = 0;

View file

@ -27,13 +27,16 @@ const sortedGroupMembers = Array.from(Array(32)).map((_, i) =>
); );
const conversation: ConversationType = { const conversation: ConversationType = {
acceptedMessageRequest: true,
areWeAdmin: true, areWeAdmin: true,
id: '', id: '',
lastUpdated: 0, lastUpdated: 0,
markedUnread: false, markedUnread: false,
isMe: false,
sortedGroupMembers, sortedGroupMembers,
title: 'Some Conversation', title: 'Some Conversation',
type: 'group', type: 'group',
sharedGroupNames: [],
}; };
const createProps = (): PropsType => ({ const createProps = (): PropsType => ({

View file

@ -124,9 +124,10 @@ export const BaseConversationListItem: FunctionComponent<PropsType> = React.memo
acceptedMessageRequest={acceptedMessageRequest} acceptedMessageRequest={acceptedMessageRequest}
avatarPath={avatarPath} avatarPath={avatarPath}
color={color} color={color}
noteToSelf={isAvatarNoteToSelf}
conversationType={conversationType} conversationType={conversationType}
noteToSelf={isAvatarNoteToSelf}
i18n={i18n} i18n={i18n}
isMe={isMe}
name={name} name={name}
phoneNumber={phoneNumber} phoneNumber={phoneNumber}
profileName={profileName} profileName={profileName}

View file

@ -18,7 +18,7 @@ import { ContactName } from '../conversation/ContactName';
import { TypingAnimation } from '../conversation/TypingAnimation'; import { TypingAnimation } from '../conversation/TypingAnimation';
import { LocalizerType } from '../../types/Util'; import { LocalizerType } from '../../types/Util';
import { ColorType } from '../../types/Colors'; import { ConversationType } from '../../state/ducks/conversations';
const MESSAGE_STATUS_ICON_CLASS_NAME = `${MESSAGE_TEXT_CLASS_NAME}__status-icon`; const MESSAGE_STATUS_ICON_CLASS_NAME = `${MESSAGE_TEXT_CLASS_NAME}__status-icon`;
@ -34,37 +34,31 @@ export const MessageStatuses = [
export type MessageStatusType = typeof MessageStatuses[number]; export type MessageStatusType = typeof MessageStatuses[number];
export type PropsData = { export type PropsData = Pick<
id: string; ConversationType,
phoneNumber?: string; | 'acceptedMessageRequest'
color?: ColorType; | 'avatarPath'
profileName?: string; | 'color'
title: string; | 'draftPreview'
name?: string; | 'id'
type: 'group' | 'direct'; | 'isMe'
avatarPath?: string; | 'isPinned'
isMe?: boolean; | 'isSelected'
muteExpiresAt?: number; | 'lastMessage'
sharedGroupNames?: Array<string>; | 'lastUpdated'
unblurredAvatarPath?: string; | 'markedUnread'
| 'muteExpiresAt'
lastUpdated?: number; | 'name'
unreadCount?: number; | 'phoneNumber'
markedUnread?: boolean; | 'profileName'
isSelected?: boolean; | 'sharedGroupNames'
| 'shouldShowDraft'
acceptedMessageRequest?: boolean; | 'title'
draftPreview?: string; | 'type'
shouldShowDraft?: boolean; | 'typingContact'
| 'unblurredAvatarPath'
typingContact?: unknown; | 'unreadCount'
lastMessage?: { >;
status: MessageStatusType;
text: string;
deletedForEveryone?: boolean;
};
isPinned?: boolean;
};
type PropsHousekeeping = { type PropsHousekeeping = {
i18n: LocalizerType; i18n: LocalizerType;

View file

@ -18,12 +18,15 @@ export const CreateNewGroupButton: FunctionComponent<PropsType> = React.memo(
return ( return (
<BaseConversationListItem <BaseConversationListItem
acceptedMessageRequest={false}
color="grey" color="grey"
conversationType="group" conversationType="group"
headerName={title} headerName={title}
i18n={i18n} i18n={i18n}
isMe={false}
isSelected={false} isSelected={false}
onClick={onClick} onClick={onClick}
sharedGroupNames={[]}
style={style} style={style}
title={title} title={title}
/> />

View file

@ -9,6 +9,7 @@ import { boolean, text, withKnobs } from '@storybook/addon-knobs';
import { setup as setupI18n } from '../../../js/modules/i18n'; import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json'; import enMessages from '../../../_locales/en/messages.json';
import { MessageSearchResult, PropsType } from './MessageSearchResult'; import { MessageSearchResult, PropsType } from './MessageSearchResult';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
const story = storiesOf('Components/MessageSearchResult', module); const story = storiesOf('Components/MessageSearchResult', module);
@ -17,22 +18,23 @@ const story = storiesOf('Components/MessageSearchResult', module);
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
story.addDecorator((withKnobs as any)({ escapeHTML: false })); story.addDecorator((withKnobs as any)({ escapeHTML: false }));
const someone = { const someone = getDefaultConversation({
title: 'Some Person', title: 'Some Person',
name: 'Some Person', name: 'Some Person',
phoneNumber: '(202) 555-0011', phoneNumber: '(202) 555-0011',
}; });
const me = { const me = getDefaultConversation({
title: 'Me', title: 'Me',
name: 'Me', name: 'Me',
isMe: true, isMe: true,
}; });
const group = { const group = getDefaultConversation({
title: 'Group Chat', title: 'Group Chat',
name: 'Group Chat', name: 'Group Chat',
}; type: 'group',
});
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
i18n, i18n,

View file

@ -32,14 +32,17 @@ export const StartNewConversation: FunctionComponent<Props> = React.memo(
return ( return (
<BaseConversationListItem <BaseConversationListItem
acceptedMessageRequest={false}
color="grey" color="grey"
conversationType="direct" conversationType="direct"
headerName={phoneNumber} headerName={phoneNumber}
i18n={i18n} i18n={i18n}
isMe={false}
isSelected={false} isSelected={false}
messageText={messageText} messageText={messageText}
onClick={onClick} onClick={onClick}
phoneNumber={phoneNumber} phoneNumber={phoneNumber}
sharedGroupNames={[]}
style={style} style={style}
title={phoneNumber} title={phoneNumber}
/> />

View file

@ -169,14 +169,17 @@ export class LeftPaneChooseGroupMembersHelper extends LeftPaneHelper<LeftPaneCho
{this.selectedContacts.map(contact => ( {this.selectedContacts.map(contact => (
<ContactPill <ContactPill
key={contact.id} key={contact.id}
acceptedMessageRequest={contact.acceptedMessageRequest}
avatarPath={contact.avatarPath} avatarPath={contact.avatarPath}
color={contact.color} color={contact.color}
firstName={contact.firstName} firstName={contact.firstName}
i18n={i18n} i18n={i18n}
id={contact.id} id={contact.id}
isMe={contact.isMe}
name={contact.name} name={contact.name}
phoneNumber={contact.phoneNumber} phoneNumber={contact.phoneNumber}
profileName={contact.profileName} profileName={contact.profileName}
sharedGroupNames={contact.sharedGroupNames}
title={contact.title} title={contact.title}
onClickRemove={removeSelectedContact} onClickRemove={removeSelectedContact}
/> />

View file

@ -18,10 +18,7 @@ import {
GroupV2InfoType, GroupV2InfoType,
SendOptionsType, SendOptionsType,
} from '../textsecure/SendMessage'; } from '../textsecure/SendMessage';
import { import { ConversationType } from '../state/ducks/conversations';
ConversationType,
ConversationTypeType,
} from '../state/ducks/conversations';
import { ColorType } from '../types/Colors'; import { ColorType } from '../types/Colors';
import { MessageModel } from './messages'; import { MessageModel } from './messages';
import { isMuted } from '../util/isMuted'; import { isMuted } from '../util/isMuted';
@ -1386,7 +1383,6 @@ export class ConversationModel extends window.Backbone
profileSharing: this.get('profileSharing'), profileSharing: this.get('profileSharing'),
publicParams: this.get('publicParams'), publicParams: this.get('publicParams'),
secretParams: this.get('secretParams'), secretParams: this.get('secretParams'),
sharedGroupNames: this.get('sharedGroupNames'),
shouldShowDraft, shouldShowDraft,
sortedGroupMembers, sortedGroupMembers,
timestamp, timestamp,
@ -1394,8 +1390,16 @@ export class ConversationModel extends window.Backbone
searchableTitle: this.isMe() searchableTitle: this.isMe()
? window.i18n('noteToSelf') ? window.i18n('noteToSelf')
: this.getTitle(), : this.getTitle(),
type: (this.isPrivate() ? 'direct' : 'group') as ConversationTypeType,
unreadCount: this.get('unreadCount')! || 0, unreadCount: this.get('unreadCount')! || 0,
...(this.isPrivate()
? {
type: 'direct' as const,
sharedGroupNames: this.get('sharedGroupNames') || [],
}
: {
type: 'group' as const,
sharedGroupNames: [],
}),
}; };
if (typingContact) { if (typingContact) {

View file

@ -63,7 +63,16 @@ type PropsForMessageDetail = Pick<
type PropsForMessage = Omit<PropsData, 'interactionMode'>; type PropsForMessage = Omit<PropsData, 'interactionMode'>;
type FormattedContact = Partial<ConversationType> & type FormattedContact = Partial<ConversationType> &
Pick<ConversationType, 'title' | 'id' | 'type'>; Pick<
ConversationType,
| 'acceptedMessageRequest'
| 'id'
| 'isMe'
| 'sharedGroupNames'
| 'title'
| 'type'
| 'unblurredAvatarPath'
>;
type PropsForUnsupportedMessage = { type PropsForUnsupportedMessage = {
canProcessNow: boolean; canProcessNow: boolean;
@ -155,10 +164,13 @@ const { getTextWithMentions, GoogleChrome } = window.Signal.Util;
const { addStickerPackReference, getMessageBySender } = window.Signal.Data; const { addStickerPackReference, getMessageBySender } = window.Signal.Data;
const { bytesFromString } = window.Signal.Crypto; const { bytesFromString } = window.Signal.Crypto;
const PLACEHOLDER_CONTACT: Pick<ConversationType, 'title' | 'type' | 'id'> = { const PLACEHOLDER_CONTACT: FormattedContact = {
acceptedMessageRequest: false,
id: 'placeholder-contact', id: 'placeholder-contact',
type: 'direct', isMe: false,
sharedGroupNames: [],
title: window.i18n('unknownContact'), title: window.i18n('unknownContact'),
type: 'direct',
}; };
const THREE_HOURS = 3 * 60 * 60 * 1000; const THREE_HOURS = 3 * 60 * 60 * 1000;
@ -1003,10 +1015,13 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
}); });
return { return {
acceptedMessageRequest: false,
id: 'phone-only', id: 'phone-only',
type: 'direct', isMe: false,
title: phoneNumber,
phoneNumber, phoneNumber,
sharedGroupNames: [],
title: phoneNumber,
type: 'direct',
}; };
} }

View file

@ -272,11 +272,15 @@ export class MentionCompletion {
)} )}
> >
<Avatar <Avatar
acceptedMessageRequest={member.acceptedMessageRequest}
avatarPath={member.avatarPath} avatarPath={member.avatarPath}
conversationType="direct" conversationType="direct"
i18n={this.options.i18n} i18n={this.options.i18n}
isMe={member.isMe}
sharedGroupNames={member.sharedGroupNames}
size={28} size={28}
title={member.title} title={member.title}
unblurredAvatarPath={member.unblurredAvatarPath}
/> />
<div className="module-composition-input__suggestions__title"> <div className="module-composition-input__suggestions__title">
{member.title} {member.title}

View file

@ -106,7 +106,7 @@ export type ConversationType = {
}>; }>;
muteExpiresAt?: number; muteExpiresAt?: number;
type: ConversationTypeType; type: ConversationTypeType;
isMe?: boolean; isMe: boolean;
lastUpdated?: number; lastUpdated?: number;
// This is used by the CompositionInput for @mentions // This is used by the CompositionInput for @mentions
sortedGroupMembers?: Array<ConversationType>; sortedGroupMembers?: Array<ConversationType>;
@ -129,12 +129,12 @@ export type ConversationType = {
draftBodyRanges?: Array<BodyRangeType>; draftBodyRanges?: Array<BodyRangeType>;
draftPreview?: string; draftPreview?: string;
sharedGroupNames?: Array<string>; sharedGroupNames: Array<string>;
groupVersion?: 1 | 2; groupVersion?: 1 | 2;
groupId?: string; groupId?: string;
groupLink?: string; groupLink?: string;
messageRequestsEnabled?: boolean; messageRequestsEnabled?: boolean;
acceptedMessageRequest?: boolean; acceptedMessageRequest: boolean;
secretParams?: string; secretParams?: string;
publicParams?: string; publicParams?: string;
}; };

View file

@ -45,9 +45,12 @@ export const getPlaceholderContact = (): ConversationType => {
} }
placeholderContact = { placeholderContact = {
acceptedMessageRequest: false,
id: 'placeholder-contact', id: 'placeholder-contact',
type: 'direct', type: 'direct',
title: window.i18n('unknownContact'), title: window.i18n('unknownContact'),
isMe: false,
sharedGroupNames: [],
}; };
return placeholderContact; return placeholderContact;
}; };

View file

@ -321,12 +321,15 @@ export function getDefaultConversation(
const lastName = getLastName(); const lastName = getLastName();
return { return {
id: generateUuid(), acceptedMessageRequest: true,
isGroupV2Capable: true,
lastUpdated: Date.now(),
markedUnread: Boolean(overrideProps.markedUnread),
e164: '+1300555000', e164: '+1300555000',
firstName, firstName,
id: generateUuid(),
isGroupV2Capable: true,
isMe: false,
lastUpdated: Date.now(),
markedUnread: Boolean(overrideProps.markedUnread),
sharedGroupNames: [],
title: `${firstName} ${lastName}`, title: `${firstName} ${lastName}`,
type: 'direct' as const, type: 'direct' as const,
uuid: generateUuid(), uuid: generateUuid(),

View file

@ -42,19 +42,19 @@ import { noopAction } from '../../../state/ducks/noop';
import { StateType, reducer as rootReducer } from '../../../state/reducer'; import { StateType, reducer as rootReducer } from '../../../state/reducer';
import { setup as setupI18n } from '../../../../js/modules/i18n'; import { setup as setupI18n } from '../../../../js/modules/i18n';
import enMessages from '../../../../_locales/en/messages.json'; import enMessages from '../../../../_locales/en/messages.json';
import { getDefaultConversation } from '../../helpers/getDefaultConversation';
describe('both/state/selectors/conversations', () => { describe('both/state/selectors/conversations', () => {
const getEmptyRootState = (): StateType => { const getEmptyRootState = (): StateType => {
return rootReducer(undefined, noopAction()); return rootReducer(undefined, noopAction());
}; };
function getDefaultConversation(id: string): ConversationType { function makeConversation(id: string): ConversationType {
return { return getDefaultConversation({
id, id,
type: 'direct',
searchableTitle: `${id} title`, searchableTitle: `${id} title`,
title: `${id} title`, title: `${id} title`,
}; });
} }
const i18n = setupI18n('en', enMessages); const i18n = setupI18n('en', enMessages);
@ -64,7 +64,7 @@ describe('both/state/selectors/conversations', () => {
...getEmptyRootState(), ...getEmptyRootState(),
conversations: { conversations: {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { abc123: getDefaultConversation('abc123') }, conversationLookup: { abc123: makeConversation('abc123') },
}, },
}; };
@ -104,8 +104,8 @@ describe('both/state/selectors/conversations', () => {
it('returns conversation by e164 first', () => { it('returns conversation by e164 first', () => {
const id = 'id'; const id = 'id';
const conversation = getDefaultConversation(id); const conversation = makeConversation(id);
const wrongConversation = getDefaultConversation('wrong'); const wrongConversation = makeConversation('wrong');
const state = { const state = {
...getEmptyRootState(), ...getEmptyRootState(),
@ -135,8 +135,8 @@ describe('both/state/selectors/conversations', () => {
it('returns conversation by uuid', () => { it('returns conversation by uuid', () => {
const id = 'id'; const id = 'id';
const conversation = getDefaultConversation(id); const conversation = makeConversation(id);
const wrongConversation = getDefaultConversation('wrong'); const wrongConversation = makeConversation('wrong');
const state = { const state = {
...getEmptyRootState(), ...getEmptyRootState(),
@ -163,8 +163,8 @@ describe('both/state/selectors/conversations', () => {
it('returns conversation by groupId', () => { it('returns conversation by groupId', () => {
const id = 'id'; const id = 'id';
const conversation = getDefaultConversation(id); const conversation = makeConversation(id);
const wrongConversation = getDefaultConversation('wrong'); const wrongConversation = makeConversation('wrong');
const state = { const state = {
...getEmptyRootState(), ...getEmptyRootState(),
@ -188,7 +188,7 @@ describe('both/state/selectors/conversations', () => {
it('returns conversation by conversationId', () => { it('returns conversation by conversationId', () => {
const id = 'id'; const id = 'id';
const conversation = getDefaultConversation(id); const conversation = makeConversation(id);
const state = { const state = {
...getEmptyRootState(), ...getEmptyRootState(),
@ -212,7 +212,7 @@ describe('both/state/selectors/conversations', () => {
it('does proper caching of result', () => { it('does proper caching of result', () => {
const id = 'id'; const id = 'id';
const conversation = getDefaultConversation(id); const conversation = makeConversation(id);
const state = { const state = {
...getEmptyRootState(), ...getEmptyRootState(),
@ -248,7 +248,7 @@ describe('both/state/selectors/conversations', () => {
conversations: { conversations: {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
[id]: getDefaultConversation('third'), [id]: makeConversation('third'),
}, },
}, },
}; };
@ -273,8 +273,8 @@ describe('both/state/selectors/conversations', () => {
conversations: { conversations: {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
abc: getDefaultConversation('abc'), abc: makeConversation('abc'),
def: getDefaultConversation('def'), def: makeConversation('def'),
}, },
invitedConversationIdsForNewlyCreatedGroup: ['def', 'abc'], invitedConversationIdsForNewlyCreatedGroup: ['def', 'abc'],
}, },
@ -487,7 +487,7 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'our-conversation-id': { 'our-conversation-id': {
...getDefaultConversation('our-conversation-id'), ...makeConversation('our-conversation-id'),
isMe: true, isMe: true,
profileName: 'My own name', profileName: 'My own name',
}, },
@ -505,44 +505,44 @@ describe('both/state/selectors/conversations', () => {
const result = getRootState(); const result = getRootState();
Object.assign(result.conversations.conversationLookup, { Object.assign(result.conversations.conversationLookup, {
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
type: 'direct', type: 'direct',
profileName: 'A', profileName: 'A',
title: 'A', title: 'A',
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
type: 'group', type: 'group',
isGroupV1AndDisabled: true, isGroupV1AndDisabled: true,
name: '2', name: '2',
title: 'Should Be Dropped (GV1)', title: 'Should Be Dropped (GV1)',
}, },
'convo-3': { 'convo-3': {
...getDefaultConversation('convo-3'), ...makeConversation('convo-3'),
type: 'group', type: 'group',
name: 'B', name: 'B',
title: 'B', title: 'B',
}, },
'convo-4': { 'convo-4': {
...getDefaultConversation('convo-4'), ...makeConversation('convo-4'),
isBlocked: true, isBlocked: true,
name: '4', name: '4',
title: 'Should Be Dropped (blocked)', title: 'Should Be Dropped (blocked)',
}, },
'convo-5': { 'convo-5': {
...getDefaultConversation('convo-5'), ...makeConversation('convo-5'),
discoveredUnregisteredAt: new Date(1999, 3, 20).getTime(), discoveredUnregisteredAt: new Date(1999, 3, 20).getTime(),
name: 'C', name: 'C',
title: 'C', title: 'C',
}, },
'convo-6': { 'convo-6': {
...getDefaultConversation('convo-6'), ...makeConversation('convo-6'),
profileSharing: true, profileSharing: true,
name: 'Should Be Droped (no title)', name: 'Should Be Droped (no title)',
title: null, title: null,
}, },
'convo-7': { 'convo-7': {
...getDefaultConversation('convo-7'), ...makeConversation('convo-7'),
discoveredUnregisteredAt: Date.now(), discoveredUnregisteredAt: Date.now(),
name: '7', name: '7',
title: 'Should Be Dropped (unregistered)', title: 'Should Be Dropped (unregistered)',
@ -574,7 +574,7 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'our-conversation-id': { 'our-conversation-id': {
...getDefaultConversation('our-conversation-id'), ...makeConversation('our-conversation-id'),
isMe: true, isMe: true,
}, },
}, },
@ -594,17 +594,18 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'convo-0': { 'convo-0': {
...getDefaultConversation('convo-0'), ...makeConversation('convo-0'),
isMe: true, isMe: true,
profileSharing: false, profileSharing: false,
}, },
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
type: 'group' as const, type: 'group' as const,
name: 'Friends!', name: 'Friends!',
sharedGroupNames: [],
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
name: 'Alice', name: 'Alice',
}, },
}, },
@ -623,17 +624,17 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'convo-0': { 'convo-0': {
...getDefaultConversation('convo-0'), ...makeConversation('convo-0'),
name: 'Ex', name: 'Ex',
isBlocked: true, isBlocked: true,
}, },
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
name: 'Bob', name: 'Bob',
discoveredUnregisteredAt: Date.now(), discoveredUnregisteredAt: Date.now(),
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
name: 'Charlie', name: 'Charlie',
}, },
}, },
@ -656,7 +657,7 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'our-conversation-id': { 'our-conversation-id': {
...getDefaultConversation('our-conversation-id'), ...makeConversation('our-conversation-id'),
isMe: true, isMe: true,
}, },
}, },
@ -676,17 +677,18 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'convo-0': { 'convo-0': {
...getDefaultConversation('convo-0'), ...makeConversation('convo-0'),
isMe: true, isMe: true,
name: 'Me!', name: 'Me!',
}, },
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
type: 'group' as const, type: 'group' as const,
name: 'Friends!', name: 'Friends!',
sharedGroupNames: [],
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
name: 'Alice', name: 'Alice',
}, },
}, },
@ -705,17 +707,17 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'convo-0': { 'convo-0': {
...getDefaultConversation('convo-0'), ...makeConversation('convo-0'),
name: 'Ex', name: 'Ex',
isBlocked: true, isBlocked: true,
}, },
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
name: 'Bob', name: 'Bob',
discoveredUnregisteredAt: Date.now(), discoveredUnregisteredAt: Date.now(),
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
name: 'Charlie', name: 'Charlie',
}, },
}, },
@ -738,7 +740,7 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'our-conversation-id': { 'our-conversation-id': {
...getDefaultConversation('our-conversation-id'), ...makeConversation('our-conversation-id'),
isMe: true, isMe: true,
}, },
}, },
@ -758,18 +760,20 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'convo-0': { 'convo-0': {
...getDefaultConversation('convo-0'), ...makeConversation('convo-0'),
isMe: true, isMe: true,
name: 'Me!', name: 'Me!',
}, },
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
type: 'group' as const, type: 'group' as const,
name: 'Friends!', name: 'Friends!',
sharedGroupNames: [],
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
type: 'group' as const, type: 'group' as const,
sharedGroupNames: [],
}, },
}, },
}, },
@ -787,19 +791,22 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'convo-0': { 'convo-0': {
...getDefaultConversation('convo-0'), ...makeConversation('convo-0'),
type: 'group' as const, type: 'group' as const,
name: 'Family!', name: 'Family!',
isBlocked: true, isBlocked: true,
sharedGroupNames: [],
}, },
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
type: 'group' as const, type: 'group' as const,
name: 'Friends!', name: 'Friends!',
sharedGroupNames: [],
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
type: 'group' as const, type: 'group' as const,
sharedGroupNames: [],
}, },
}, },
}, },
@ -821,7 +828,7 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'our-conversation-id': { 'our-conversation-id': {
...getDefaultConversation('our-conversation-id'), ...makeConversation('our-conversation-id'),
name: 'Me, Myself, and I', name: 'Me, Myself, and I',
title: 'Me, Myself, and I', title: 'Me, Myself, and I',
searchableTitle: 'Note to Self', searchableTitle: 'Note to Self',
@ -845,38 +852,38 @@ describe('both/state/selectors/conversations', () => {
const result = getRootState(searchTerm); const result = getRootState(searchTerm);
Object.assign(result.conversations.conversationLookup, { Object.assign(result.conversations.conversationLookup, {
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
name: 'In System Contacts', name: 'In System Contacts',
title: 'A. Sorted First', title: 'A. Sorted First',
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
title: 'Should Be Dropped (no name, no profile sharing)', title: 'Should Be Dropped (no name, no profile sharing)',
}, },
'convo-3': { 'convo-3': {
...getDefaultConversation('convo-3'), ...makeConversation('convo-3'),
type: 'group', type: 'group',
title: 'Should Be Dropped (group)', title: 'Should Be Dropped (group)',
}, },
'convo-4': { 'convo-4': {
...getDefaultConversation('convo-4'), ...makeConversation('convo-4'),
isBlocked: true, isBlocked: true,
title: 'Should Be Dropped (blocked)', title: 'Should Be Dropped (blocked)',
}, },
'convo-5': { 'convo-5': {
...getDefaultConversation('convo-5'), ...makeConversation('convo-5'),
discoveredUnregisteredAt: new Date(1999, 3, 20).getTime(), discoveredUnregisteredAt: new Date(1999, 3, 20).getTime(),
name: 'In System Contacts (and unregistered too long ago)', name: 'In System Contacts (and unregistered too long ago)',
title: 'B. Sorted Second', title: 'B. Sorted Second',
}, },
'convo-6': { 'convo-6': {
...getDefaultConversation('convo-6'), ...makeConversation('convo-6'),
profileSharing: true, profileSharing: true,
profileName: 'C. Has Profile Sharing', profileName: 'C. Has Profile Sharing',
title: 'C. Has Profile Sharing', title: 'C. Has Profile Sharing',
}, },
'convo-7': { 'convo-7': {
...getDefaultConversation('convo-7'), ...makeConversation('convo-7'),
discoveredUnregisteredAt: Date.now(), discoveredUnregisteredAt: Date.now(),
title: 'Should Be Dropped (unregistered)', title: 'Should Be Dropped (unregistered)',
}, },
@ -939,47 +946,52 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'our-conversation-id': { 'our-conversation-id': {
...getDefaultConversation('our-conversation-id'), ...makeConversation('our-conversation-id'),
isMe: true, isMe: true,
}, },
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
name: 'In System Contacts', name: 'In System Contacts',
title: 'Should be dropped (contact)', title: 'Should be dropped (contact)',
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
title: 'Should be dropped (contact)', title: 'Should be dropped (contact)',
}, },
'convo-3': { 'convo-3': {
...getDefaultConversation('convo-3'), ...makeConversation('convo-3'),
type: 'group', type: 'group',
name: 'Hello World', name: 'Hello World',
title: 'Hello World', title: 'Hello World',
sharedGroupNames: [],
}, },
'convo-4': { 'convo-4': {
...getDefaultConversation('convo-4'), ...makeConversation('convo-4'),
type: 'group', type: 'group',
isBlocked: true, isBlocked: true,
title: 'Should be dropped (blocked)', title: 'Should be dropped (blocked)',
sharedGroupNames: [],
}, },
'convo-5': { 'convo-5': {
...getDefaultConversation('convo-5'), ...makeConversation('convo-5'),
type: 'group', type: 'group',
title: 'Unknown Group', title: 'Unknown Group',
sharedGroupNames: [],
}, },
'convo-6': { 'convo-6': {
...getDefaultConversation('convo-6'), ...makeConversation('convo-6'),
type: 'group', type: 'group',
name: 'Signal', name: 'Signal',
title: 'Signal', title: 'Signal',
sharedGroupNames: [],
}, },
'convo-7': { 'convo-7': {
...getDefaultConversation('convo-7'), ...makeConversation('convo-7'),
profileSharing: false, profileSharing: false,
type: 'group', type: 'group',
name: 'Signal Fake', name: 'Signal Fake',
title: 'Signal Fake', title: 'Signal Fake',
sharedGroupNames: [],
}, },
}, },
composer: { composer: {
@ -1021,37 +1033,38 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'our-conversation-id': { 'our-conversation-id': {
...getDefaultConversation('our-conversation-id'), ...makeConversation('our-conversation-id'),
isMe: true, isMe: true,
}, },
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
name: 'In System Contacts', name: 'In System Contacts',
title: 'A. Sorted First', title: 'A. Sorted First',
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
title: 'Should be dropped (has no name)', title: 'Should be dropped (has no name)',
}, },
'convo-3': { 'convo-3': {
...getDefaultConversation('convo-3'), ...makeConversation('convo-3'),
type: 'group', type: 'group',
title: 'Should Be Dropped (group)', title: 'Should Be Dropped (group)',
sharedGroupNames: [],
}, },
'convo-4': { 'convo-4': {
...getDefaultConversation('convo-4'), ...makeConversation('convo-4'),
isBlocked: true, isBlocked: true,
name: 'My Name', name: 'My Name',
title: 'Should Be Dropped (blocked)', title: 'Should Be Dropped (blocked)',
}, },
'convo-5': { 'convo-5': {
...getDefaultConversation('convo-5'), ...makeConversation('convo-5'),
discoveredUnregisteredAt: new Date(1999, 3, 20).getTime(), discoveredUnregisteredAt: new Date(1999, 3, 20).getTime(),
name: 'In System Contacts (and unregistered too long ago)', name: 'In System Contacts (and unregistered too long ago)',
title: 'C. Sorted Third', title: 'C. Sorted Third',
}, },
'convo-6': { 'convo-6': {
...getDefaultConversation('convo-6'), ...makeConversation('convo-6'),
discoveredUnregisteredAt: Date.now(), discoveredUnregisteredAt: Date.now(),
name: 'My Name', name: 'My Name',
title: 'Should Be Dropped (unregistered)', title: 'Should Be Dropped (unregistered)',
@ -1133,7 +1146,7 @@ describe('both/state/selectors/conversations', () => {
}); });
it('returns the marked contact', () => { it('returns the marked contact', () => {
const conversation = getDefaultConversation('abc123'); const conversation = makeConversation('abc123');
assert.deepEqual( assert.deepEqual(
getCantAddContactForModal({ getCantAddContactForModal({
@ -1179,7 +1192,7 @@ describe('both/state/selectors/conversations', () => {
describe('#_getLeftPaneLists', () => { describe('#_getLeftPaneLists', () => {
it('sorts conversations based on timestamp then by intl-friendly title', () => { it('sorts conversations based on timestamp then by intl-friendly title', () => {
const data: ConversationLookupType = { const data: ConversationLookupType = {
id1: { id1: getDefaultConversation({
id: 'id1', id: 'id1',
e164: '+18005551111', e164: '+18005551111',
activeAt: Date.now(), activeAt: Date.now(),
@ -1203,8 +1216,8 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
id2: { id2: getDefaultConversation({
id: 'id2', id: 'id2',
e164: '+18005551111', e164: '+18005551111',
activeAt: Date.now(), activeAt: Date.now(),
@ -1228,8 +1241,8 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
id3: { id3: getDefaultConversation({
id: 'id3', id: 'id3',
e164: '+18005551111', e164: '+18005551111',
activeAt: Date.now(), activeAt: Date.now(),
@ -1253,8 +1266,8 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
id4: { id4: getDefaultConversation({
id: 'id4', id: 'id4',
e164: '+18005551111', e164: '+18005551111',
activeAt: Date.now(), activeAt: Date.now(),
@ -1278,8 +1291,8 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
id5: { id5: getDefaultConversation({
id: 'id5', id: 'id5',
e164: '+18005551111', e164: '+18005551111',
activeAt: Date.now(), activeAt: Date.now(),
@ -1303,7 +1316,7 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
}; };
const comparator = _getConversationComparator(); const comparator = _getConversationComparator();
const { const {
@ -1327,7 +1340,7 @@ describe('both/state/selectors/conversations', () => {
describe('given pinned conversations', () => { describe('given pinned conversations', () => {
it('sorts pinned conversations based on order in storage', () => { it('sorts pinned conversations based on order in storage', () => {
const data: ConversationLookupType = { const data: ConversationLookupType = {
pin2: { pin2: getDefaultConversation({
id: 'pin2', id: 'pin2',
e164: '+18005551111', e164: '+18005551111',
activeAt: Date.now(), activeAt: Date.now(),
@ -1352,8 +1365,8 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
pin3: { pin3: getDefaultConversation({
id: 'pin3', id: 'pin3',
e164: '+18005551111', e164: '+18005551111',
activeAt: Date.now(), activeAt: Date.now(),
@ -1378,8 +1391,8 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
pin1: { pin1: getDefaultConversation({
id: 'pin1', id: 'pin1',
e164: '+18005551111', e164: '+18005551111',
activeAt: Date.now(), activeAt: Date.now(),
@ -1404,7 +1417,7 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
}; };
const pinnedConversationIds = ['pin1', 'pin2', 'pin3']; const pinnedConversationIds = ['pin1', 'pin2', 'pin3'];
@ -1431,7 +1444,7 @@ describe('both/state/selectors/conversations', () => {
it('includes archived and pinned conversations with no active_at', () => { it('includes archived and pinned conversations with no active_at', () => {
const data: ConversationLookupType = { const data: ConversationLookupType = {
pin2: { pin2: getDefaultConversation({
id: 'pin2', id: 'pin2',
e164: '+18005551111', e164: '+18005551111',
name: 'Pin Two', name: 'Pin Two',
@ -1455,8 +1468,8 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
pin3: { pin3: getDefaultConversation({
id: 'pin3', id: 'pin3',
e164: '+18005551111', e164: '+18005551111',
name: 'Pin Three', name: 'Pin Three',
@ -1480,8 +1493,8 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
pin1: { pin1: getDefaultConversation({
id: 'pin1', id: 'pin1',
e164: '+18005551111', e164: '+18005551111',
name: 'Pin One', name: 'Pin One',
@ -1505,8 +1518,8 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
pin4: { pin4: getDefaultConversation({
id: 'pin1', id: 'pin1',
e164: '+18005551111', e164: '+18005551111',
name: 'Pin Four', name: 'Pin Four',
@ -1531,8 +1544,8 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
pin5: { pin5: getDefaultConversation({
id: 'pin1', id: 'pin1',
e164: '+18005551111', e164: '+18005551111',
name: 'Pin Five', name: 'Pin Five',
@ -1556,7 +1569,7 @@ describe('both/state/selectors/conversations', () => {
}, },
acceptedMessageRequest: true, acceptedMessageRequest: true,
}, }),
}; };
const pinnedConversationIds = ['pin1', 'pin2', 'pin3']; const pinnedConversationIds = ['pin1', 'pin2', 'pin3'];
@ -1713,11 +1726,11 @@ describe('both/state/selectors/conversations', () => {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'convo-1': { 'convo-1': {
...getDefaultConversation('convo-1'), ...makeConversation('convo-1'),
title: 'Person One', title: 'Person One',
}, },
'convo-2': { 'convo-2': {
...getDefaultConversation('convo-2'), ...makeConversation('convo-2'),
title: 'Person Two', title: 'Person Two',
}, },
}, },
@ -1749,9 +1762,9 @@ describe('both/state/selectors/conversations', () => {
conversations: { conversations: {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
abc: { ...getDefaultConversation('abc'), title: 'Janet' }, abc: { ...makeConversation('abc'), title: 'Janet' },
def: { ...getDefaultConversation('def'), title: 'Janet' }, def: { ...makeConversation('def'), title: 'Janet' },
geh: { ...getDefaultConversation('geh'), title: 'Rick' }, geh: { ...makeConversation('geh'), title: 'Rick' },
}, },
}, },
}; };
@ -1778,7 +1791,7 @@ describe('both/state/selectors/conversations', () => {
conversations: { conversations: {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
abc123: getDefaultConversation('abc123'), abc123: makeConversation('abc123'),
}, },
}, },
}; };
@ -1791,7 +1804,7 @@ describe('both/state/selectors/conversations', () => {
conversations: { conversations: {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
abc123: getDefaultConversation('abc123'), abc123: makeConversation('abc123'),
}, },
selectedConversationId: 'abc123', selectedConversationId: 'abc123',
}, },
@ -1807,28 +1820,26 @@ describe('both/state/selectors/conversations', () => {
conversations: { conversations: {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
abc123: getDefaultConversation('abc123'), abc123: makeConversation('abc123'),
}, },
}, },
}; };
assert.isUndefined(getSelectedConversation(state)); assert.isUndefined(getSelectedConversation(state));
}); });
it('returns the selected conversation ID', () => { it('returns the selected conversation', () => {
const conversation = makeConversation('abc123');
const state = { const state = {
...getEmptyRootState(), ...getEmptyRootState(),
conversations: { conversations: {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
abc123: getDefaultConversation('abc123'), abc123: conversation,
}, },
selectedConversationId: 'abc123', selectedConversationId: 'abc123',
}, },
}; };
assert.deepEqual( assert.strictEqual(getSelectedConversation(state), conversation);
getSelectedConversation(state),
getDefaultConversation('abc123')
);
}); });
}); });
}); });

View file

@ -19,6 +19,7 @@ import {
getSearchResults, getSearchResults,
} from '../../../state/selectors/search'; } from '../../../state/selectors/search';
import { makeLookup } from '../../../util/makeLookup'; import { makeLookup } from '../../../util/makeLookup';
import { getDefaultConversation } from '../../helpers/getDefaultConversation';
import { StateType, reducer as rootReducer } from '../../../state/reducer'; import { StateType, reducer as rootReducer } from '../../../state/reducer';
@ -50,14 +51,6 @@ describe('both/state/selectors/search', () => {
}; };
} }
function getDefaultConversation(id: string): ConversationType {
return {
id,
type: 'direct',
title: `${id} title`,
};
}
describe('#getMessageSearchResultSelector', () => { describe('#getMessageSearchResultSelector', () => {
it('returns undefined if message not found in lookup', () => { it('returns undefined if message not found in lookup', () => {
const state = getEmptyRootState(); const state = getEmptyRootState();
@ -97,8 +90,8 @@ describe('both/state/selectors/search', () => {
const fromId = 'from-id'; const fromId = 'from-id';
const toId = 'to-id'; const toId = 'to-id';
const from = getDefaultConversation(fromId); const from = getDefaultConversation({ id: fromId });
const to = getDefaultConversation(toId); const to = getDefaultConversation({ id: toId });
const state = { const state = {
...getEmptyRootState(), ...getEmptyRootState(),
@ -151,8 +144,8 @@ describe('both/state/selectors/search', () => {
const toId = fromId; const toId = fromId;
const myId = 'my-id'; const myId = 'my-id';
const from = getDefaultConversation(fromId); const from = getDefaultConversation({ id: fromId });
const meAsRecipient = getDefaultConversation(myId); const meAsRecipient = getDefaultConversation({ id: myId });
const state = { const state = {
...getEmptyRootState(), ...getEmptyRootState(),
@ -195,8 +188,8 @@ describe('both/state/selectors/search', () => {
const fromId = 'from-id'; const fromId = 'from-id';
const toId = 'to-id'; const toId = 'to-id';
const from = getDefaultConversation(fromId); const from = getDefaultConversation({ id: fromId });
const to = getDefaultConversation(toId); const to = getDefaultConversation({ id: toId });
const state = { const state = {
...getEmptyRootState(), ...getEmptyRootState(),
@ -302,13 +295,13 @@ describe('both/state/selectors/search', () => {
it('returns loaded search results', () => { it('returns loaded search results', () => {
const conversations: Array<ConversationType> = [ const conversations: Array<ConversationType> = [
getDefaultConversation('1'), getDefaultConversation({ id: '1' }),
getDefaultConversation('2'), getDefaultConversation({ id: '2' }),
]; ];
const contacts: Array<ConversationType> = [ const contacts: Array<ConversationType> = [
getDefaultConversation('3'), getDefaultConversation({ id: '3' }),
getDefaultConversation('4'), getDefaultConversation({ id: '4' }),
getDefaultConversation('5'), getDefaultConversation({ id: '5' }),
]; ];
const messages: Array<MessageSearchResultType> = [ const messages: Array<MessageSearchResultType> = [
getDefaultSearchMessage('a'), getDefaultSearchMessage('a'),

View file

@ -84,13 +84,6 @@ describe('shouldBlurAvatar', () => {
}); });
it('returns true if the stars align (i.e., not everything above)', () => { it('returns true if the stars align (i.e., not everything above)', () => {
assert.isTrue(
shouldBlurAvatar({
avatarPath: '/path/to/avatar.jpg',
acceptedMessageRequest: false,
isMe: false,
})
);
assert.isTrue( assert.isTrue(
shouldBlurAvatar({ shouldBlurAvatar({
avatarPath: '/path/to/avatar.jpg', avatarPath: '/path/to/avatar.jpg',

View file

@ -13,8 +13,9 @@ import {
} from '../../../quill/mentions/completion'; } from '../../../quill/mentions/completion';
import { ConversationType } from '../../../state/ducks/conversations'; import { ConversationType } from '../../../state/ducks/conversations';
import { MemberRepository } from '../../../quill/memberRepository'; import { MemberRepository } from '../../../quill/memberRepository';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
const me: ConversationType = { const me: ConversationType = getDefaultConversation({
id: '666777', id: '666777',
uuid: 'pqrstuv', uuid: 'pqrstuv',
title: 'Fred Savage', title: 'Fred Savage',
@ -24,10 +25,11 @@ const me: ConversationType = {
lastUpdated: Date.now(), lastUpdated: Date.now(),
markedUnread: false, markedUnread: false,
areWeAdmin: false, areWeAdmin: false,
}; isMe: true,
});
const members: Array<ConversationType> = [ const members: Array<ConversationType> = [
{ getDefaultConversation({
id: '555444', id: '555444',
uuid: 'abcdefg', uuid: 'abcdefg',
title: 'Mahershala Ali', title: 'Mahershala Ali',
@ -37,8 +39,8 @@ const members: Array<ConversationType> = [
lastUpdated: Date.now(), lastUpdated: Date.now(),
markedUnread: false, markedUnread: false,
areWeAdmin: false, areWeAdmin: false,
}, }),
{ getDefaultConversation({
id: '333222', id: '333222',
uuid: 'hijklmno', uuid: 'hijklmno',
title: 'Shia LaBeouf', title: 'Shia LaBeouf',
@ -48,7 +50,7 @@ const members: Array<ConversationType> = [
lastUpdated: Date.now(), lastUpdated: Date.now(),
markedUnread: false, markedUnread: false,
areWeAdmin: false, areWeAdmin: false,
}, }),
me, me,
]; ];

View file

@ -25,6 +25,7 @@ import {
} from '../../../state/ducks/conversations'; } from '../../../state/ducks/conversations';
import { CallMode } from '../../../types/Calling'; import { CallMode } from '../../../types/Calling';
import * as groups from '../../../groups'; import * as groups from '../../../groups';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
const { const {
cantAddContactToGroup, cantAddContactToGroup,
@ -72,31 +73,7 @@ describe('both/state/ducks/conversations', () => {
describe('helpers', () => { describe('helpers', () => {
describe('getConversationCallMode', () => { describe('getConversationCallMode', () => {
const fakeConversation: ConversationType = { const fakeConversation: ConversationType = getDefaultConversation();
id: 'id1',
e164: '+18005551111',
activeAt: Date.now(),
name: 'No timestamp',
timestamp: 0,
inboxPosition: 0,
phoneNumber: 'notused',
isArchived: false,
markedUnread: false,
type: 'direct',
isMe: false,
lastUpdated: Date.now(),
title: 'No timestamp',
unreadCount: 1,
isSelected: false,
typingContact: {
name: 'Someone There',
color: 'blue',
phoneNumber: '+18005551111',
},
acceptedMessageRequest: true,
};
it("returns CallMode.None if you've left the conversation", () => { it("returns CallMode.None if you've left the conversation", () => {
assert.strictEqual( assert.strictEqual(
@ -144,6 +121,7 @@ describe('both/state/ducks/conversations', () => {
...fakeConversation, ...fakeConversation,
type: 'group', type: 'group',
groupVersion: 1, groupVersion: 1,
sharedGroupNames: [],
}), }),
CallMode.None CallMode.None
); );
@ -152,6 +130,7 @@ describe('both/state/ducks/conversations', () => {
getConversationCallMode({ getConversationCallMode({
...fakeConversation, ...fakeConversation,
type: 'group', type: 'group',
sharedGroupNames: [],
}), }),
CallMode.None CallMode.None
); );
@ -170,6 +149,7 @@ describe('both/state/ducks/conversations', () => {
...fakeConversation, ...fakeConversation,
type: 'group', type: 'group',
groupVersion: 2, groupVersion: 2,
sharedGroupNames: [],
}), }),
CallMode.Group CallMode.Group
); );
@ -177,14 +157,6 @@ describe('both/state/ducks/conversations', () => {
}); });
describe('updateConversationLookups', () => { describe('updateConversationLookups', () => {
function getDefaultConversation(id: string): ConversationType {
return {
id,
type: 'direct',
title: `${id} title`,
};
}
it('does not change lookups if no conversations provided', () => { it('does not change lookups if no conversations provided', () => {
const state = getEmptyState(); const state = getEmptyState();
const result = updateConversationLookups(undefined, undefined, state); const result = updateConversationLookups(undefined, undefined, state);
@ -204,24 +176,26 @@ describe('both/state/ducks/conversations', () => {
}); });
it('adds and removes e164-only contact', () => { it('adds and removes e164-only contact', () => {
const removed = { const removed = getDefaultConversation({
...getDefaultConversation('id-removed'), id: 'id-removed',
e164: 'e164-removed', e164: 'e164-removed',
}; uuid: undefined,
});
const state = { const state = {
...getEmptyState(), ...getEmptyState(),
conversationsByE164: { conversationsByE164: {
[removed.e164]: removed, 'e164-removed': removed,
}, },
}; };
const added = { const added = getDefaultConversation({
...getDefaultConversation('id-added'), id: 'id-added',
e164: 'e164-added', e164: 'e164-added',
}; uuid: undefined,
});
const expected = { const expected = {
[added.e164]: added, 'e164-added': added,
}; };
const actual = updateConversationLookups(added, removed, state); const actual = updateConversationLookups(added, removed, state);
@ -238,24 +212,26 @@ describe('both/state/ducks/conversations', () => {
}); });
it('adds and removes uuid-only contact', () => { it('adds and removes uuid-only contact', () => {
const removed = { const removed = getDefaultConversation({
...getDefaultConversation('id-removed'), id: 'id-removed',
uuid: 'uuid-removed', uuid: 'uuid-removed',
}; e164: undefined,
});
const state = { const state = {
...getEmptyState(), ...getEmptyState(),
conversationsByuuid: { conversationsByuuid: {
[removed.uuid]: removed, 'uuid-removed': removed,
}, },
}; };
const added = { const added = getDefaultConversation({
...getDefaultConversation('id-added'), id: 'id-added',
uuid: 'uuid-added', uuid: 'uuid-added',
}; e164: undefined,
});
const expected = { const expected = {
[added.uuid]: added, 'uuid-added': added,
}; };
const actual = updateConversationLookups(added, removed, state); const actual = updateConversationLookups(added, removed, state);
@ -272,24 +248,28 @@ describe('both/state/ducks/conversations', () => {
}); });
it('adds and removes groupId-only contact', () => { it('adds and removes groupId-only contact', () => {
const removed = { const removed = getDefaultConversation({
...getDefaultConversation('id-removed'), id: 'id-removed',
groupId: 'groupId-removed', groupId: 'groupId-removed',
}; e164: undefined,
uuid: undefined,
});
const state = { const state = {
...getEmptyState(), ...getEmptyState(),
conversationsBygroupId: { conversationsBygroupId: {
[removed.groupId]: removed, 'groupId-removed': removed,
}, },
}; };
const added = { const added = getDefaultConversation({
...getDefaultConversation('id-added'), id: 'id-added',
groupId: 'groupId-added', groupId: 'groupId-added',
}; e164: undefined,
uuid: undefined,
});
const expected = { const expected = {
[added.groupId]: added, 'groupId-added': added,
}; };
const actual = updateConversationLookups(added, removed, state); const actual = updateConversationLookups(added, removed, state);
@ -420,14 +400,13 @@ describe('both/state/ducks/conversations', () => {
}); });
it('shows the inbox if the conversation is not archived', () => { it('shows the inbox if the conversation is not archived', () => {
const conversation = getDefaultConversation({
id: 'fake-conversation-id',
});
const state = { const state = {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'fake-conversation-id': { [conversation.id]: conversation,
id: 'fake-conversation-id',
type: 'direct' as const,
title: 'Foo Bar',
},
}, },
}; };
const result = reducer(state, action); const result = reducer(state, action);
@ -437,15 +416,14 @@ describe('both/state/ducks/conversations', () => {
}); });
it('shows the archive if the conversation is archived', () => { it('shows the archive if the conversation is archived', () => {
const conversation = getDefaultConversation({
id: 'fake-conversation-id',
isArchived: true,
});
const state = { const state = {
...getEmptyState(), ...getEmptyState(),
conversationLookup: { conversationLookup: {
'fake-conversation-id': { [conversation.id]: conversation,
id: 'fake-conversation-id',
type: 'group' as const,
title: 'Baz Qux',
isArchived: true,
},
}, },
}; };
const result = reducer(state, action); const result = reducer(state, action);

View file

@ -6,16 +6,11 @@ import * as sinon from 'sinon';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { RowType } from '../../../components/ConversationList'; import { RowType } from '../../../components/ConversationList';
import { FindDirection } from '../../../components/leftPane/LeftPaneHelper'; import { FindDirection } from '../../../components/leftPane/LeftPaneHelper';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
import { LeftPaneArchiveHelper } from '../../../components/leftPane/LeftPaneArchiveHelper'; import { LeftPaneArchiveHelper } from '../../../components/leftPane/LeftPaneArchiveHelper';
describe('LeftPaneArchiveHelper', () => { describe('LeftPaneArchiveHelper', () => {
const fakeConversation = () => ({
id: uuid(),
title: uuid(),
type: 'direct' as const,
});
describe('getBackAction', () => { describe('getBackAction', () => {
it('returns the "show inbox" action', () => { it('returns the "show inbox" action', () => {
const showInbox = sinon.fake(); const showInbox = sinon.fake();
@ -33,7 +28,10 @@ describe('LeftPaneArchiveHelper', () => {
); );
assert.strictEqual( assert.strictEqual(
new LeftPaneArchiveHelper({ new LeftPaneArchiveHelper({
archivedConversations: [fakeConversation(), fakeConversation()], archivedConversations: [
getDefaultConversation(),
getDefaultConversation(),
],
}).getRowCount(), }).getRowCount(),
2 2
); );
@ -43,7 +41,10 @@ describe('LeftPaneArchiveHelper', () => {
describe('getRowIndexToScrollTo', () => { describe('getRowIndexToScrollTo', () => {
it('returns undefined if no conversation is selected', () => { it('returns undefined if no conversation is selected', () => {
const helper = new LeftPaneArchiveHelper({ const helper = new LeftPaneArchiveHelper({
archivedConversations: [fakeConversation(), fakeConversation()], archivedConversations: [
getDefaultConversation(),
getDefaultConversation(),
],
}); });
assert.isUndefined(helper.getRowIndexToScrollTo(undefined)); assert.isUndefined(helper.getRowIndexToScrollTo(undefined));
@ -51,14 +52,20 @@ describe('LeftPaneArchiveHelper', () => {
it('returns undefined if the selected conversation is not pinned or non-pinned', () => { it('returns undefined if the selected conversation is not pinned or non-pinned', () => {
const helper = new LeftPaneArchiveHelper({ const helper = new LeftPaneArchiveHelper({
archivedConversations: [fakeConversation(), fakeConversation()], archivedConversations: [
getDefaultConversation(),
getDefaultConversation(),
],
}); });
assert.isUndefined(helper.getRowIndexToScrollTo(uuid())); assert.isUndefined(helper.getRowIndexToScrollTo(uuid()));
}); });
it("returns the archived conversation's index", () => { it("returns the archived conversation's index", () => {
const archivedConversations = [fakeConversation(), fakeConversation()]; const archivedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneArchiveHelper({ archivedConversations }); const helper = new LeftPaneArchiveHelper({ archivedConversations });
assert.strictEqual( assert.strictEqual(
@ -74,7 +81,10 @@ describe('LeftPaneArchiveHelper', () => {
describe('getRow', () => { describe('getRow', () => {
it('returns each conversation as a row', () => { it('returns each conversation as a row', () => {
const archivedConversations = [fakeConversation(), fakeConversation()]; const archivedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneArchiveHelper({ archivedConversations }); const helper = new LeftPaneArchiveHelper({ archivedConversations });
assert.deepEqual(helper.getRow(0), { assert.deepEqual(helper.getRow(0), {
@ -90,7 +100,10 @@ describe('LeftPaneArchiveHelper', () => {
describe('getConversationAndMessageAtIndex', () => { describe('getConversationAndMessageAtIndex', () => {
it('returns the conversation at the given index when it exists', () => { it('returns the conversation at the given index when it exists', () => {
const archivedConversations = [fakeConversation(), fakeConversation()]; const archivedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneArchiveHelper({ archivedConversations }); const helper = new LeftPaneArchiveHelper({ archivedConversations });
assert.strictEqual( assert.strictEqual(
@ -104,7 +117,10 @@ describe('LeftPaneArchiveHelper', () => {
}); });
it('when requesting an index out of bounds, returns the last conversation', () => { it('when requesting an index out of bounds, returns the last conversation', () => {
const archivedConversations = [fakeConversation(), fakeConversation()]; const archivedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneArchiveHelper({ archivedConversations }); const helper = new LeftPaneArchiveHelper({ archivedConversations });
assert.strictEqual( assert.strictEqual(
@ -135,7 +151,10 @@ describe('LeftPaneArchiveHelper', () => {
describe('getConversationAndMessageInDirection', () => { describe('getConversationAndMessageInDirection', () => {
it('returns the next conversation when searching downward', () => { it('returns the next conversation when searching downward', () => {
const archivedConversations = [fakeConversation(), fakeConversation()]; const archivedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneArchiveHelper({ archivedConversations }); const helper = new LeftPaneArchiveHelper({ archivedConversations });
assert.deepEqual( assert.deepEqual(
@ -154,17 +173,23 @@ describe('LeftPaneArchiveHelper', () => {
describe('shouldRecomputeRowHeights', () => { describe('shouldRecomputeRowHeights', () => {
it('always returns false because row heights are constant', () => { it('always returns false because row heights are constant', () => {
const helper = new LeftPaneArchiveHelper({ const helper = new LeftPaneArchiveHelper({
archivedConversations: [fakeConversation(), fakeConversation()], archivedConversations: [
getDefaultConversation(),
getDefaultConversation(),
],
}); });
assert.isFalse( assert.isFalse(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
archivedConversations: [fakeConversation()], archivedConversations: [getDefaultConversation()],
}) })
); );
assert.isFalse( assert.isFalse(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
archivedConversations: [fakeConversation(), fakeConversation()], archivedConversations: [
getDefaultConversation(),
getDefaultConversation(),
],
}) })
); );
}); });

View file

@ -4,10 +4,10 @@
import { assert } from 'chai'; import { assert } from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { times } from 'lodash'; import { times } from 'lodash';
import { v4 as uuid } from 'uuid';
import { RowType } from '../../../components/ConversationList'; import { RowType } from '../../../components/ConversationList';
import * as remoteConfig from '../../../RemoteConfig'; import * as remoteConfig from '../../../RemoteConfig';
import { ContactCheckboxDisabledReason } from '../../../components/conversationList/ContactCheckbox'; import { ContactCheckboxDisabledReason } from '../../../components/conversationList/ContactCheckbox';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
import { LeftPaneChooseGroupMembersHelper } from '../../../components/leftPane/LeftPaneChooseGroupMembersHelper'; import { LeftPaneChooseGroupMembersHelper } from '../../../components/leftPane/LeftPaneChooseGroupMembersHelper';
@ -21,13 +21,6 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
selectedContacts: [], selectedContacts: [],
}; };
const fakeContact = () => ({
id: uuid(),
isGroupV2Capable: true,
title: uuid(),
type: 'direct' as const,
});
let sinonSandbox: sinon.SinonSandbox; let sinonSandbox: sinon.SinonSandbox;
beforeEach(() => { beforeEach(() => {
@ -64,7 +57,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: '', searchTerm: '',
selectedContacts: [fakeContact()], selectedContacts: [getDefaultConversation()],
}).getRowCount(), }).getRowCount(),
0 0
); );
@ -73,7 +66,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: 'foo bar', searchTerm: 'foo bar',
selectedContacts: [fakeContact()], selectedContacts: [getDefaultConversation()],
}).getRowCount(), }).getRowCount(),
0 0
); );
@ -83,9 +76,12 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
assert.strictEqual( assert.strictEqual(
new LeftPaneChooseGroupMembersHelper({ new LeftPaneChooseGroupMembersHelper({
...defaults, ...defaults,
candidateContacts: [fakeContact(), fakeContact()], candidateContacts: [
getDefaultConversation(),
getDefaultConversation(),
],
searchTerm: '', searchTerm: '',
selectedContacts: [fakeContact()], selectedContacts: [getDefaultConversation()],
}).getRowCount(), }).getRowCount(),
4 4
); );
@ -99,7 +95,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: '', searchTerm: '',
selectedContacts: [fakeContact()], selectedContacts: [getDefaultConversation()],
}).getRow(0) }).getRow(0)
); );
assert.isUndefined( assert.isUndefined(
@ -107,7 +103,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: '', searchTerm: '',
selectedContacts: [fakeContact()], selectedContacts: [getDefaultConversation()],
}).getRow(99) }).getRow(99)
); );
assert.isUndefined( assert.isUndefined(
@ -115,13 +111,16 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
...defaults, ...defaults,
candidateContacts: [], candidateContacts: [],
searchTerm: 'foo bar', searchTerm: 'foo bar',
selectedContacts: [fakeContact()], selectedContacts: [getDefaultConversation()],
}).getRow(0) }).getRow(0)
); );
}); });
it('returns a header, then the contacts, then a blank space if there are contacts', () => { it('returns a header, then the contacts, then a blank space if there are contacts', () => {
const candidateContacts = [fakeContact(), fakeContact()]; const candidateContacts = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneChooseGroupMembersHelper({ const helper = new LeftPaneChooseGroupMembersHelper({
...defaults, ...defaults,
candidateContacts, candidateContacts,
@ -149,7 +148,7 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
}); });
it("disables non-selected contact checkboxes if you've selected the maximum number of contacts", () => { it("disables non-selected contact checkboxes if you've selected the maximum number of contacts", () => {
const candidateContacts = times(50, () => fakeContact()); const candidateContacts = times(50, () => getDefaultConversation());
const helper = new LeftPaneChooseGroupMembersHelper({ const helper = new LeftPaneChooseGroupMembersHelper({
...defaults, ...defaults,
candidateContacts, candidateContacts,
@ -173,9 +172,9 @@ describe('LeftPaneChooseGroupMembersHelper', () => {
it("disables contacts that aren't GV2-capable, unless they are already selected somehow", () => { it("disables contacts that aren't GV2-capable, unless they are already selected somehow", () => {
const candidateContacts = [ const candidateContacts = [
{ ...fakeContact(), isGroupV2Capable: false }, { ...getDefaultConversation(), isGroupV2Capable: false },
{ ...fakeContact(), isGroupV2Capable: undefined }, { ...getDefaultConversation(), isGroupV2Capable: undefined },
{ ...fakeContact(), isGroupV2Capable: false }, { ...getDefaultConversation(), isGroupV2Capable: false },
]; ];
const helper = new LeftPaneChooseGroupMembersHelper({ const helper = new LeftPaneChooseGroupMembersHelper({

View file

@ -3,20 +3,14 @@
import { assert } from 'chai'; import { assert } from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { v4 as uuid } from 'uuid';
import { RowType } from '../../../components/ConversationList'; import { RowType } from '../../../components/ConversationList';
import { FindDirection } from '../../../components/leftPane/LeftPaneHelper'; import { FindDirection } from '../../../components/leftPane/LeftPaneHelper';
import * as remoteConfig from '../../../RemoteConfig'; import * as remoteConfig from '../../../RemoteConfig';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
import { LeftPaneComposeHelper } from '../../../components/leftPane/LeftPaneComposeHelper'; import { LeftPaneComposeHelper } from '../../../components/leftPane/LeftPaneComposeHelper';
describe('LeftPaneComposeHelper', () => { describe('LeftPaneComposeHelper', () => {
const fakeConvo = () => ({
id: uuid(),
title: uuid(),
type: 'direct' as const,
});
let sinonSandbox: sinon.SinonSandbox; let sinonSandbox: sinon.SinonSandbox;
let remoteConfigStub: sinon.SinonStub; let remoteConfigStub: sinon.SinonStub;
@ -65,7 +59,7 @@ describe('LeftPaneComposeHelper', () => {
it('returns the number of contacts + 2 (for the "new group" button and header) if not searching', () => { it('returns the number of contacts + 2 (for the "new group" button and header) if not searching', () => {
assert.strictEqual( assert.strictEqual(
new LeftPaneComposeHelper({ new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
@ -77,8 +71,8 @@ describe('LeftPaneComposeHelper', () => {
it('returns the number of contacts + number of groups + 3 (for the "new group" button and the headers) if not searching', () => { it('returns the number of contacts + number of groups + 3 (for the "new group" button and the headers) if not searching', () => {
assert.strictEqual( assert.strictEqual(
new LeftPaneComposeHelper({ new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [fakeConvo(), fakeConvo()], composeGroups: [getDefaultConversation(), getDefaultConversation()],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
}).getRowCount(), }).getRowCount(),
@ -98,7 +92,7 @@ describe('LeftPaneComposeHelper', () => {
); );
assert.strictEqual( assert.strictEqual(
new LeftPaneComposeHelper({ new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
@ -107,8 +101,8 @@ describe('LeftPaneComposeHelper', () => {
); );
assert.strictEqual( assert.strictEqual(
new LeftPaneComposeHelper({ new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [fakeConvo()], composeGroups: [getDefaultConversation()],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
}).getRowCount(), }).getRowCount(),
@ -131,7 +125,7 @@ describe('LeftPaneComposeHelper', () => {
it('returns the number of contacts + 2 (for the "Start new conversation" button and header) if searching for a phone number', () => { it('returns the number of contacts + 2 (for the "Start new conversation" button and header) if searching for a phone number', () => {
assert.strictEqual( assert.strictEqual(
new LeftPaneComposeHelper({ new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '+16505551234', searchTerm: '+16505551234',
@ -157,7 +151,10 @@ describe('LeftPaneComposeHelper', () => {
}); });
it('returns a "new group" button, a header, and contacts if not searching', () => { it('returns a "new group" button, a header, and contacts if not searching', () => {
const composeContacts = [fakeConvo(), fakeConvo()]; const composeContacts = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneComposeHelper({ const helper = new LeftPaneComposeHelper({
composeContacts, composeContacts,
composeGroups: [], composeGroups: [],
@ -183,8 +180,14 @@ describe('LeftPaneComposeHelper', () => {
}); });
it('returns a "new group" button, a header, contacts, groups header, and groups -- if not searching', () => { it('returns a "new group" button, a header, contacts, groups header, and groups -- if not searching', () => {
const composeContacts = [fakeConvo(), fakeConvo()]; const composeContacts = [
const composeGroups = [fakeConvo(), fakeConvo()]; getDefaultConversation(),
getDefaultConversation(),
];
const composeGroups = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneComposeHelper({ const helper = new LeftPaneComposeHelper({
composeContacts, composeContacts,
composeGroups, composeGroups,
@ -266,7 +269,10 @@ describe('LeftPaneComposeHelper', () => {
}); });
it('returns one row per contact if searching', () => { it('returns one row per contact if searching', () => {
const composeContacts = [fakeConvo(), fakeConvo()]; const composeContacts = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneComposeHelper({ const helper = new LeftPaneComposeHelper({
composeContacts, composeContacts,
composeGroups: [], composeGroups: [],
@ -300,7 +306,10 @@ describe('LeftPaneComposeHelper', () => {
}); });
it('returns a "start new conversation" row, a header, and contacts if searching for a phone number', () => { it('returns a "start new conversation" row, a header, and contacts if searching for a phone number', () => {
const composeContacts = [fakeConvo(), fakeConvo()]; const composeContacts = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneComposeHelper({ const helper = new LeftPaneComposeHelper({
composeContacts, composeContacts,
composeGroups: [], composeGroups: [],
@ -330,7 +339,7 @@ describe('LeftPaneComposeHelper', () => {
describe('getConversationAndMessageAtIndex', () => { describe('getConversationAndMessageAtIndex', () => {
it('returns undefined because keyboard shortcuts are not supported', () => { it('returns undefined because keyboard shortcuts are not supported', () => {
const helper = new LeftPaneComposeHelper({ const helper = new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
@ -343,7 +352,7 @@ describe('LeftPaneComposeHelper', () => {
describe('getConversationAndMessageInDirection', () => { describe('getConversationAndMessageInDirection', () => {
it('returns undefined because keyboard shortcuts are not supported', () => { it('returns undefined because keyboard shortcuts are not supported', () => {
const helper = new LeftPaneComposeHelper({ const helper = new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
@ -362,7 +371,7 @@ describe('LeftPaneComposeHelper', () => {
describe('shouldRecomputeRowHeights', () => { describe('shouldRecomputeRowHeights', () => {
it('returns false if going from "no header" to "no header"', () => { it('returns false if going from "no header" to "no header"', () => {
const helper = new LeftPaneComposeHelper({ const helper = new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
@ -370,7 +379,7 @@ describe('LeftPaneComposeHelper', () => {
assert.isFalse( assert.isFalse(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
composeContacts: [fakeConvo()], composeContacts: [getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
@ -378,7 +387,11 @@ describe('LeftPaneComposeHelper', () => {
); );
assert.isFalse( assert.isFalse(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
composeContacts: [fakeConvo(), fakeConvo(), fakeConvo()], composeContacts: [
getDefaultConversation(),
getDefaultConversation(),
getDefaultConversation(),
],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'bing bong', searchTerm: 'bing bong',
@ -388,7 +401,7 @@ describe('LeftPaneComposeHelper', () => {
it('returns false if going from "has header" to "has header"', () => { it('returns false if going from "has header" to "has header"', () => {
const helper = new LeftPaneComposeHelper({ const helper = new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
@ -396,7 +409,7 @@ describe('LeftPaneComposeHelper', () => {
assert.isFalse( assert.isFalse(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
composeContacts: [fakeConvo()], composeContacts: [getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
@ -404,7 +417,7 @@ describe('LeftPaneComposeHelper', () => {
); );
assert.isFalse( assert.isFalse(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
composeContacts: [fakeConvo()], composeContacts: [getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '+16505559876', searchTerm: '+16505559876',
@ -414,7 +427,7 @@ describe('LeftPaneComposeHelper', () => {
it('returns true if going from "no header" to "has header"', () => { it('returns true if going from "no header" to "has header"', () => {
const helper = new LeftPaneComposeHelper({ const helper = new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
@ -422,7 +435,7 @@ describe('LeftPaneComposeHelper', () => {
assert.isTrue( assert.isTrue(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
@ -430,7 +443,7 @@ describe('LeftPaneComposeHelper', () => {
); );
assert.isTrue( assert.isTrue(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '+16505551234', searchTerm: '+16505551234',
@ -440,7 +453,7 @@ describe('LeftPaneComposeHelper', () => {
it('returns true if going from "has header" to "no header"', () => { it('returns true if going from "has header" to "no header"', () => {
const helper = new LeftPaneComposeHelper({ const helper = new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: '', searchTerm: '',
@ -448,7 +461,7 @@ describe('LeftPaneComposeHelper', () => {
assert.isTrue( assert.isTrue(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
@ -458,7 +471,7 @@ describe('LeftPaneComposeHelper', () => {
it('should be true if going from contact to group or vice versa', () => { it('should be true if going from contact to group or vice versa', () => {
const helperContacts = new LeftPaneComposeHelper({ const helperContacts = new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
@ -467,7 +480,7 @@ describe('LeftPaneComposeHelper', () => {
assert.isTrue( assert.isTrue(
helperContacts.shouldRecomputeRowHeights({ helperContacts.shouldRecomputeRowHeights({
composeContacts: [], composeContacts: [],
composeGroups: [fakeConvo(), fakeConvo()], composeGroups: [getDefaultConversation(), getDefaultConversation()],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
}) })
@ -475,14 +488,14 @@ describe('LeftPaneComposeHelper', () => {
const helperGroups = new LeftPaneComposeHelper({ const helperGroups = new LeftPaneComposeHelper({
composeContacts: [], composeContacts: [],
composeGroups: [fakeConvo(), fakeConvo()], composeGroups: [getDefaultConversation(), getDefaultConversation()],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
}); });
assert.isTrue( assert.isTrue(
helperGroups.shouldRecomputeRowHeights({ helperGroups.shouldRecomputeRowHeights({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [], composeGroups: [],
regionCode: 'US', regionCode: 'US',
searchTerm: 'foo bar', searchTerm: 'foo bar',
@ -492,16 +505,16 @@ describe('LeftPaneComposeHelper', () => {
it('should be true if the headers are in different row indices as before', () => { it('should be true if the headers are in different row indices as before', () => {
const helperContacts = new LeftPaneComposeHelper({ const helperContacts = new LeftPaneComposeHelper({
composeContacts: [fakeConvo(), fakeConvo()], composeContacts: [getDefaultConversation(), getDefaultConversation()],
composeGroups: [fakeConvo()], composeGroups: [getDefaultConversation()],
regionCode: 'US', regionCode: 'US',
searchTerm: 'soup', searchTerm: 'soup',
}); });
assert.isTrue( assert.isTrue(
helperContacts.shouldRecomputeRowHeights({ helperContacts.shouldRecomputeRowHeights({
composeContacts: [fakeConvo()], composeContacts: [getDefaultConversation()],
composeGroups: [fakeConvo(), fakeConvo()], composeGroups: [getDefaultConversation(), getDefaultConversation()],
regionCode: 'US', regionCode: 'US',
searchTerm: 'sandwich', searchTerm: 'sandwich',
}) })

View file

@ -3,19 +3,13 @@
import { assert } from 'chai'; import { assert } from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { v4 as uuid } from 'uuid';
import { RowType } from '../../../components/ConversationList'; import { RowType } from '../../../components/ConversationList';
import { FindDirection } from '../../../components/leftPane/LeftPaneHelper'; import { FindDirection } from '../../../components/leftPane/LeftPaneHelper';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
import { LeftPaneInboxHelper } from '../../../components/leftPane/LeftPaneInboxHelper'; import { LeftPaneInboxHelper } from '../../../components/leftPane/LeftPaneInboxHelper';
describe('LeftPaneInboxHelper', () => { describe('LeftPaneInboxHelper', () => {
const fakeConversation = () => ({
id: uuid(),
title: uuid(),
type: 'direct' as const,
});
describe('getBackAction', () => { describe('getBackAction', () => {
it("returns undefined; you can't go back from the main inbox", () => { it("returns undefined; you can't go back from the main inbox", () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
@ -49,7 +43,7 @@ describe('LeftPaneInboxHelper', () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [], conversations: [],
pinnedConversations: [], pinnedConversations: [],
archivedConversations: [fakeConversation()], archivedConversations: [getDefaultConversation()],
}); });
assert.strictEqual(helper.getRowCount(), 1); assert.strictEqual(helper.getRowCount(), 1);
@ -58,9 +52,9 @@ describe('LeftPaneInboxHelper', () => {
it("returns the number of non-pinned conversations if that's all there is", () => { it("returns the number of non-pinned conversations if that's all there is", () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [ conversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
], ],
pinnedConversations: [], pinnedConversations: [],
archivedConversations: [], archivedConversations: [],
@ -73,9 +67,9 @@ describe('LeftPaneInboxHelper', () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [], conversations: [],
pinnedConversations: [ pinnedConversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
], ],
archivedConversations: [], archivedConversations: [],
}); });
@ -86,11 +80,11 @@ describe('LeftPaneInboxHelper', () => {
it('adds 2 rows for each header if there are pinned and non-pinned conversations,', () => { it('adds 2 rows for each header if there are pinned and non-pinned conversations,', () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [ conversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
], ],
pinnedConversations: [fakeConversation()], pinnedConversations: [getDefaultConversation()],
archivedConversations: [], archivedConversations: [],
}); });
@ -100,12 +94,12 @@ describe('LeftPaneInboxHelper', () => {
it('adds 1 row for the archive button if there are any archived conversations', () => { it('adds 1 row for the archive button if there are any archived conversations', () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [ conversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
], ],
pinnedConversations: [], pinnedConversations: [],
archivedConversations: [fakeConversation()], archivedConversations: [getDefaultConversation()],
}); });
assert.strictEqual(helper.getRowCount(), 4); assert.strictEqual(helper.getRowCount(), 4);
@ -115,8 +109,8 @@ describe('LeftPaneInboxHelper', () => {
describe('getRowIndexToScrollTo', () => { describe('getRowIndexToScrollTo', () => {
it('returns undefined if no conversation is selected', () => { it('returns undefined if no conversation is selected', () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [fakeConversation(), fakeConversation()], conversations: [getDefaultConversation(), getDefaultConversation()],
pinnedConversations: [fakeConversation()], pinnedConversations: [getDefaultConversation()],
archivedConversations: [], archivedConversations: [],
}); });
@ -124,10 +118,10 @@ describe('LeftPaneInboxHelper', () => {
}); });
it('returns undefined if the selected conversation is not pinned or non-pinned', () => { it('returns undefined if the selected conversation is not pinned or non-pinned', () => {
const archivedConversations = [fakeConversation()]; const archivedConversations = [getDefaultConversation()];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [fakeConversation(), fakeConversation()], conversations: [getDefaultConversation(), getDefaultConversation()],
pinnedConversations: [fakeConversation()], pinnedConversations: [getDefaultConversation()],
archivedConversations, archivedConversations,
}); });
@ -137,7 +131,10 @@ describe('LeftPaneInboxHelper', () => {
}); });
it("returns the pinned conversation's index if there are only pinned conversations", () => { it("returns the pinned conversation's index if there are only pinned conversations", () => {
const pinnedConversations = [fakeConversation(), fakeConversation()]; const pinnedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [], conversations: [],
pinnedConversations, pinnedConversations,
@ -155,7 +152,10 @@ describe('LeftPaneInboxHelper', () => {
}); });
it("returns the conversation's index if there are only non-pinned conversations", () => { it("returns the conversation's index if there are only non-pinned conversations", () => {
const conversations = [fakeConversation(), fakeConversation()]; const conversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations, conversations,
pinnedConversations: [], pinnedConversations: [],
@ -167,9 +167,12 @@ describe('LeftPaneInboxHelper', () => {
}); });
it("returns the pinned conversation's index + 1 (for the header) if there are both pinned and non-pinned conversations", () => { it("returns the pinned conversation's index + 1 (for the header) if there are both pinned and non-pinned conversations", () => {
const pinnedConversations = [fakeConversation(), fakeConversation()]; const pinnedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [fakeConversation()], conversations: [getDefaultConversation()],
pinnedConversations, pinnedConversations,
archivedConversations: [], archivedConversations: [],
}); });
@ -185,13 +188,16 @@ describe('LeftPaneInboxHelper', () => {
}); });
it("returns the non-pinned conversation's index + pinnedConversations.length + 2 (for the headers) if there are both pinned and non-pinned conversations", () => { it("returns the non-pinned conversation's index + pinnedConversations.length + 2 (for the headers) if there are both pinned and non-pinned conversations", () => {
const conversations = [fakeConversation(), fakeConversation()]; const conversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations, conversations,
pinnedConversations: [ pinnedConversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
], ],
archivedConversations: [], archivedConversations: [],
}); });
@ -206,7 +212,10 @@ describe('LeftPaneInboxHelper', () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [], conversations: [],
pinnedConversations: [], pinnedConversations: [],
archivedConversations: [fakeConversation(), fakeConversation()], archivedConversations: [
getDefaultConversation(),
getDefaultConversation(),
],
}); });
assert.deepEqual(helper.getRow(0), { assert.deepEqual(helper.getRow(0), {
@ -217,7 +226,10 @@ describe('LeftPaneInboxHelper', () => {
}); });
it("returns pinned conversations if that's all there are", () => { it("returns pinned conversations if that's all there are", () => {
const pinnedConversations = [fakeConversation(), fakeConversation()]; const pinnedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [], conversations: [],
@ -237,12 +249,15 @@ describe('LeftPaneInboxHelper', () => {
}); });
it('returns pinned conversations and an archive button if there are no non-pinned conversations', () => { it('returns pinned conversations and an archive button if there are no non-pinned conversations', () => {
const pinnedConversations = [fakeConversation(), fakeConversation()]; const pinnedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [], conversations: [],
pinnedConversations, pinnedConversations,
archivedConversations: [fakeConversation()], archivedConversations: [getDefaultConversation()],
}); });
assert.deepEqual(helper.getRow(0), { assert.deepEqual(helper.getRow(0), {
@ -261,7 +276,10 @@ describe('LeftPaneInboxHelper', () => {
}); });
it("returns non-pinned conversations if that's all there are", () => { it("returns non-pinned conversations if that's all there are", () => {
const conversations = [fakeConversation(), fakeConversation()]; const conversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations, conversations,
@ -281,12 +299,15 @@ describe('LeftPaneInboxHelper', () => {
}); });
it('returns non-pinned conversations and an archive button if there are no pinned conversations', () => { it('returns non-pinned conversations and an archive button if there are no pinned conversations', () => {
const conversations = [fakeConversation(), fakeConversation()]; const conversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations, conversations,
pinnedConversations: [], pinnedConversations: [],
archivedConversations: [fakeConversation()], archivedConversations: [getDefaultConversation()],
}); });
assert.deepEqual(helper.getRow(0), { assert.deepEqual(helper.getRow(0), {
@ -306,11 +327,14 @@ describe('LeftPaneInboxHelper', () => {
it('returns headers if there are both pinned and non-pinned conversations', () => { it('returns headers if there are both pinned and non-pinned conversations', () => {
const conversations = [ const conversations = [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
];
const pinnedConversations = [
getDefaultConversation(),
getDefaultConversation(),
]; ];
const pinnedConversations = [fakeConversation(), fakeConversation()];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations, conversations,
@ -351,16 +375,19 @@ describe('LeftPaneInboxHelper', () => {
it('returns headers if there are both pinned and non-pinned conversations, and an archive button', () => { it('returns headers if there are both pinned and non-pinned conversations, and an archive button', () => {
const conversations = [ const conversations = [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
];
const pinnedConversations = [
getDefaultConversation(),
getDefaultConversation(),
]; ];
const pinnedConversations = [fakeConversation(), fakeConversation()];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations, conversations,
pinnedConversations, pinnedConversations,
archivedConversations: [fakeConversation()], archivedConversations: [getDefaultConversation()],
}); });
assert.deepEqual(helper.getRow(0), { assert.deepEqual(helper.getRow(0), {
@ -402,11 +429,14 @@ describe('LeftPaneInboxHelper', () => {
describe('getConversationAndMessageAtIndex', () => { describe('getConversationAndMessageAtIndex', () => {
it('returns pinned converastions, then non-pinned conversations', () => { it('returns pinned converastions, then non-pinned conversations', () => {
const conversations = [ const conversations = [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
];
const pinnedConversations = [
getDefaultConversation(),
getDefaultConversation(),
]; ];
const pinnedConversations = [fakeConversation(), fakeConversation()];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations, conversations,
@ -437,7 +467,10 @@ describe('LeftPaneInboxHelper', () => {
}); });
it("when requesting an index out of bounds, returns the last pinned conversation when that's all there is", () => { it("when requesting an index out of bounds, returns the last pinned conversation when that's all there is", () => {
const pinnedConversations = [fakeConversation(), fakeConversation()]; const pinnedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [], conversations: [],
@ -462,7 +495,10 @@ describe('LeftPaneInboxHelper', () => {
}); });
it("when requesting an index out of bounds, returns the last non-pinned conversation when that's all there is", () => { it("when requesting an index out of bounds, returns the last non-pinned conversation when that's all there is", () => {
const conversations = [fakeConversation(), fakeConversation()]; const conversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations, conversations,
@ -487,8 +523,14 @@ describe('LeftPaneInboxHelper', () => {
}); });
it('when requesting an index out of bounds, returns the last non-pinned conversation when there are both pinned and non-pinned conversations', () => { it('when requesting an index out of bounds, returns the last non-pinned conversation when there are both pinned and non-pinned conversations', () => {
const conversations = [fakeConversation(), fakeConversation()]; const conversations = [
const pinnedConversations = [fakeConversation(), fakeConversation()]; getDefaultConversation(),
getDefaultConversation(),
];
const pinnedConversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations, conversations,
@ -516,7 +558,7 @@ describe('LeftPaneInboxHelper', () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [], conversations: [],
pinnedConversations: [], pinnedConversations: [],
archivedConversations: [fakeConversation()], archivedConversations: [getDefaultConversation()],
}); });
assert.isUndefined(helper.getConversationAndMessageAtIndex(0)); assert.isUndefined(helper.getConversationAndMessageAtIndex(0));
@ -527,8 +569,11 @@ describe('LeftPaneInboxHelper', () => {
describe('getConversationAndMessageInDirection', () => { describe('getConversationAndMessageInDirection', () => {
it('returns the next conversation when searching downward', () => { it('returns the next conversation when searching downward', () => {
const pinnedConversations = [fakeConversation(), fakeConversation()]; const pinnedConversations = [
const conversations = [fakeConversation()]; getDefaultConversation(),
getDefaultConversation(),
];
const conversations = [getDefaultConversation()];
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations, conversations,
pinnedConversations, pinnedConversations,
@ -552,23 +597,32 @@ describe('LeftPaneInboxHelper', () => {
it("returns false if the number of conversations in each section doesn't change", () => { it("returns false if the number of conversations in each section doesn't change", () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [ conversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
], ],
pinnedConversations: [fakeConversation(), fakeConversation()], pinnedConversations: [
archivedConversations: [fakeConversation()], getDefaultConversation(),
getDefaultConversation(),
],
archivedConversations: [getDefaultConversation()],
}); });
assert.isFalse( assert.isFalse(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
conversations: [ conversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
],
pinnedConversations: [
getDefaultConversation(),
getDefaultConversation(),
],
archivedConversations: [
getDefaultConversation(),
getDefaultConversation(),
], ],
pinnedConversations: [fakeConversation(), fakeConversation()],
archivedConversations: [fakeConversation(), fakeConversation()],
}) })
); );
}); });
@ -576,22 +630,28 @@ describe('LeftPaneInboxHelper', () => {
it('returns false if the only thing changed is whether conversations are archived', () => { it('returns false if the only thing changed is whether conversations are archived', () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [ conversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
], ],
pinnedConversations: [fakeConversation(), fakeConversation()], pinnedConversations: [
archivedConversations: [fakeConversation()], getDefaultConversation(),
getDefaultConversation(),
],
archivedConversations: [getDefaultConversation()],
}); });
assert.isFalse( assert.isFalse(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
conversations: [ conversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
],
pinnedConversations: [
getDefaultConversation(),
getDefaultConversation(),
], ],
pinnedConversations: [fakeConversation(), fakeConversation()],
archivedConversations: [], archivedConversations: [],
}) })
); );
@ -600,53 +660,65 @@ describe('LeftPaneInboxHelper', () => {
it('returns false if the only thing changed is the number of non-pinned conversations', () => { it('returns false if the only thing changed is the number of non-pinned conversations', () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [ conversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
], ],
pinnedConversations: [fakeConversation(), fakeConversation()], pinnedConversations: [
archivedConversations: [fakeConversation()], getDefaultConversation(),
getDefaultConversation(),
],
archivedConversations: [getDefaultConversation()],
}); });
assert.isFalse( assert.isFalse(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
conversations: [fakeConversation()], conversations: [getDefaultConversation()],
pinnedConversations: [fakeConversation(), fakeConversation()], pinnedConversations: [
archivedConversations: [fakeConversation(), fakeConversation()], getDefaultConversation(),
getDefaultConversation(),
],
archivedConversations: [
getDefaultConversation(),
getDefaultConversation(),
],
}) })
); );
}); });
it('returns true if the number of pinned conversations changes', () => { it('returns true if the number of pinned conversations changes', () => {
const helper = new LeftPaneInboxHelper({ const helper = new LeftPaneInboxHelper({
conversations: [fakeConversation()], conversations: [getDefaultConversation()],
pinnedConversations: [fakeConversation(), fakeConversation()], pinnedConversations: [
archivedConversations: [fakeConversation()], getDefaultConversation(),
getDefaultConversation(),
],
archivedConversations: [getDefaultConversation()],
}); });
assert.isTrue( assert.isTrue(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
conversations: [fakeConversation()], conversations: [getDefaultConversation()],
pinnedConversations: [ pinnedConversations: [
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
fakeConversation(), getDefaultConversation(),
], ],
archivedConversations: [fakeConversation()], archivedConversations: [getDefaultConversation()],
}) })
); );
assert.isTrue( assert.isTrue(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
conversations: [fakeConversation()], conversations: [getDefaultConversation()],
pinnedConversations: [fakeConversation()], pinnedConversations: [getDefaultConversation()],
archivedConversations: [fakeConversation()], archivedConversations: [getDefaultConversation()],
}) })
); );
assert.isTrue( assert.isTrue(
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
conversations: [fakeConversation()], conversations: [getDefaultConversation()],
pinnedConversations: [], pinnedConversations: [],
archivedConversations: [fakeConversation()], archivedConversations: [getDefaultConversation()],
}) })
); );
}); });

View file

@ -5,16 +5,11 @@ import { assert } from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { RowType } from '../../../components/ConversationList'; import { RowType } from '../../../components/ConversationList';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
import { LeftPaneSearchHelper } from '../../../components/leftPane/LeftPaneSearchHelper'; import { LeftPaneSearchHelper } from '../../../components/leftPane/LeftPaneSearchHelper';
describe('LeftPaneSearchHelper', () => { describe('LeftPaneSearchHelper', () => {
const fakeConversation = () => ({
id: uuid(),
title: uuid(),
type: 'direct' as const,
});
const fakeMessage = () => ({ const fakeMessage = () => ({
id: uuid(), id: uuid(),
conversationId: uuid(), conversationId: uuid(),
@ -54,7 +49,7 @@ describe('LeftPaneSearchHelper', () => {
new LeftPaneSearchHelper({ new LeftPaneSearchHelper({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation(), fakeConversation()], results: [getDefaultConversation(), getDefaultConversation()],
}, },
contactResults: { isLoading: true }, contactResults: { isLoading: true },
messageResults: { isLoading: true }, messageResults: { isLoading: true },
@ -88,7 +83,7 @@ describe('LeftPaneSearchHelper', () => {
const helper = new LeftPaneSearchHelper({ const helper = new LeftPaneSearchHelper({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation(), fakeConversation()], results: [getDefaultConversation(), getDefaultConversation()],
}, },
contactResults: { isLoading: false, results: [] }, contactResults: { isLoading: false, results: [] },
messageResults: { isLoading: false, results: [fakeMessage()] }, messageResults: { isLoading: false, results: [fakeMessage()] },
@ -111,7 +106,7 @@ describe('LeftPaneSearchHelper', () => {
new LeftPaneSearchHelper({ new LeftPaneSearchHelper({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation(), fakeConversation()], results: [getDefaultConversation(), getDefaultConversation()],
}, },
contactResults: { isLoading: true }, contactResults: { isLoading: true },
messageResults: { isLoading: true }, messageResults: { isLoading: true },
@ -139,8 +134,11 @@ describe('LeftPaneSearchHelper', () => {
}); });
it('returns header + results when all sections have loaded with results', () => { it('returns header + results when all sections have loaded with results', () => {
const conversations = [fakeConversation(), fakeConversation()]; const conversations = [
const contacts = [fakeConversation()]; getDefaultConversation(),
getDefaultConversation(),
];
const contacts = [getDefaultConversation()];
const messages = [fakeMessage(), fakeMessage()]; const messages = [fakeMessage(), fakeMessage()];
const helper = new LeftPaneSearchHelper({ const helper = new LeftPaneSearchHelper({
@ -188,7 +186,7 @@ describe('LeftPaneSearchHelper', () => {
}); });
it('omits conversations when there are no conversation results', () => { it('omits conversations when there are no conversation results', () => {
const contacts = [fakeConversation()]; const contacts = [getDefaultConversation()];
const messages = [fakeMessage(), fakeMessage()]; const messages = [fakeMessage(), fakeMessage()];
const helper = new LeftPaneSearchHelper({ const helper = new LeftPaneSearchHelper({
@ -224,7 +222,10 @@ describe('LeftPaneSearchHelper', () => {
}); });
it('omits contacts when there are no contact results', () => { it('omits contacts when there are no contact results', () => {
const conversations = [fakeConversation(), fakeConversation()]; const conversations = [
getDefaultConversation(),
getDefaultConversation(),
];
const messages = [fakeMessage(), fakeMessage()]; const messages = [fakeMessage(), fakeMessage()];
const helper = new LeftPaneSearchHelper({ const helper = new LeftPaneSearchHelper({
@ -265,8 +266,8 @@ describe('LeftPaneSearchHelper', () => {
}); });
it('omits messages when there are no message results', () => { it('omits messages when there are no message results', () => {
const conversations = [fakeConversation(), fakeConversation()]; const conversations = [getDefaultConversation(), getDefaultConversation()];
const contacts = [fakeConversation()]; const contacts = [getDefaultConversation()];
const helper = new LeftPaneSearchHelper({ const helper = new LeftPaneSearchHelper({
conversationResults: { conversationResults: {
@ -313,7 +314,7 @@ describe('LeftPaneSearchHelper', () => {
new LeftPaneSearchHelper({ new LeftPaneSearchHelper({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation(), fakeConversation()], results: [getDefaultConversation(), getDefaultConversation()],
}, },
contactResults: { isLoading: true }, contactResults: { isLoading: true },
messageResults: { isLoading: true }, messageResults: { isLoading: true },
@ -336,7 +337,7 @@ describe('LeftPaneSearchHelper', () => {
const helper = new LeftPaneSearchHelper({ const helper = new LeftPaneSearchHelper({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation(), fakeConversation()], results: [getDefaultConversation(), getDefaultConversation()],
}, },
contactResults: { isLoading: false, results: [] }, contactResults: { isLoading: false, results: [] },
messageResults: { messageResults: {
@ -354,7 +355,7 @@ describe('LeftPaneSearchHelper', () => {
const helper = new LeftPaneSearchHelper({ const helper = new LeftPaneSearchHelper({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation(), fakeConversation()], results: [getDefaultConversation(), getDefaultConversation()],
}, },
contactResults: { isLoading: false, results: [] }, contactResults: { isLoading: false, results: [] },
messageResults: { messageResults: {
@ -368,7 +369,7 @@ describe('LeftPaneSearchHelper', () => {
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation(), fakeConversation()], results: [getDefaultConversation(), getDefaultConversation()],
}, },
contactResults: { isLoading: false, results: [] }, contactResults: { isLoading: false, results: [] },
messageResults: { messageResults: {
@ -392,7 +393,7 @@ describe('LeftPaneSearchHelper', () => {
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation()], results: [getDefaultConversation()],
}, },
contactResults: { isLoading: true }, contactResults: { isLoading: true },
messageResults: { isLoading: true }, messageResults: { isLoading: true },
@ -413,7 +414,7 @@ describe('LeftPaneSearchHelper', () => {
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation(), fakeConversation()], results: [getDefaultConversation(), getDefaultConversation()],
}, },
contactResults: { isLoading: false, results: [] }, contactResults: { isLoading: false, results: [] },
messageResults: { isLoading: false, results: [fakeMessage()] }, messageResults: { isLoading: false, results: [fakeMessage()] },
@ -426,7 +427,7 @@ describe('LeftPaneSearchHelper', () => {
const helper = new LeftPaneSearchHelper({ const helper = new LeftPaneSearchHelper({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation(), fakeConversation()], results: [getDefaultConversation(), getDefaultConversation()],
}, },
contactResults: { isLoading: false, results: [] }, contactResults: { isLoading: false, results: [] },
messageResults: { isLoading: false, results: [] }, messageResults: { isLoading: false, results: [] },
@ -437,7 +438,7 @@ describe('LeftPaneSearchHelper', () => {
helper.shouldRecomputeRowHeights({ helper.shouldRecomputeRowHeights({
conversationResults: { conversationResults: {
isLoading: false, isLoading: false,
results: [fakeConversation()], results: [getDefaultConversation()],
}, },
contactResults: { isLoading: true }, contactResults: { isLoading: true },
messageResults: { isLoading: true }, messageResults: { isLoading: true },

View file

@ -3,18 +3,12 @@
import { assert } from 'chai'; import { assert } from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { v4 as uuid } from 'uuid';
import { RowType } from '../../../components/ConversationList'; import { RowType } from '../../../components/ConversationList';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
import { LeftPaneSetGroupMetadataHelper } from '../../../components/leftPane/LeftPaneSetGroupMetadataHelper'; import { LeftPaneSetGroupMetadataHelper } from '../../../components/leftPane/LeftPaneSetGroupMetadataHelper';
describe('LeftPaneSetGroupMetadataHelper', () => { describe('LeftPaneSetGroupMetadataHelper', () => {
const fakeContact = () => ({
id: uuid(),
title: uuid(),
type: 'direct' as const,
});
describe('getBackAction', () => { describe('getBackAction', () => {
it('returns the "show composer" action if a request is not active', () => { it('returns the "show composer" action if a request is not active', () => {
const showChooseGroupMembers = sinon.fake(); const showChooseGroupMembers = sinon.fake();
@ -68,7 +62,10 @@ describe('LeftPaneSetGroupMetadataHelper', () => {
groupName: '', groupName: '',
hasError: false, hasError: false,
isCreating: false, isCreating: false,
selectedContacts: [fakeContact(), fakeContact()], selectedContacts: [
getDefaultConversation(),
getDefaultConversation(),
],
}).getRowCount(), }).getRowCount(),
4 4
); );
@ -89,7 +86,10 @@ describe('LeftPaneSetGroupMetadataHelper', () => {
}); });
it('returns a header, then the contacts, then a blank space if there are contacts', () => { it('returns a header, then the contacts, then a blank space if there are contacts', () => {
const selectedContacts = [fakeContact(), fakeContact()]; const selectedContacts = [
getDefaultConversation(),
getDefaultConversation(),
];
const helper = new LeftPaneSetGroupMetadataHelper({ const helper = new LeftPaneSetGroupMetadataHelper({
groupAvatar: undefined, groupAvatar: undefined,
groupName: '', groupName: '',

View file

@ -2,21 +2,17 @@
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai'; import { assert } from 'chai';
import { v4 as uuid } from 'uuid';
import { import {
FindDirection, FindDirection,
ToFindType, ToFindType,
} from '../../../components/leftPane/LeftPaneHelper'; } from '../../../components/leftPane/LeftPaneHelper';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
import { getConversationInDirection } from '../../../components/leftPane/getConversationInDirection'; import { getConversationInDirection } from '../../../components/leftPane/getConversationInDirection';
describe('getConversationInDirection', () => { describe('getConversationInDirection', () => {
const fakeConversation = (markedUnread = false) => ({ const fakeConversation = (markedUnread = false) =>
id: uuid(), getDefaultConversation({ markedUnread });
title: uuid(),
type: 'direct' as const,
markedUnread,
});
const fakeConversations = [ const fakeConversations = [
fakeConversation(), fakeConversation(),

View file

@ -1,12 +1,13 @@
// Copyright 2020 Signal Messenger, LLC // Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai'; import { assert } from 'chai';
import { ConversationType } from '../../state/ducks/conversations'; import { ConversationType } from '../../state/ducks/conversations';
import { MemberRepository } from '../../quill/memberRepository'; import { MemberRepository } from '../../quill/memberRepository';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
const memberMahershala: ConversationType = { const memberMahershala: ConversationType = getDefaultConversation({
id: '555444', id: '555444',
uuid: 'abcdefg', uuid: 'abcdefg',
title: 'Pal', title: 'Pal',
@ -17,9 +18,9 @@ const memberMahershala: ConversationType = {
lastUpdated: Date.now(), lastUpdated: Date.now(),
markedUnread: false, markedUnread: false,
areWeAdmin: false, areWeAdmin: false,
}; });
const memberShia: ConversationType = { const memberShia: ConversationType = getDefaultConversation({
id: '333222', id: '333222',
uuid: 'hijklmno', uuid: 'hijklmno',
title: 'Buddy', title: 'Buddy',
@ -30,11 +31,11 @@ const memberShia: ConversationType = {
lastUpdated: Date.now(), lastUpdated: Date.now(),
markedUnread: false, markedUnread: false,
areWeAdmin: false, areWeAdmin: false,
}; });
const members: Array<ConversationType> = [memberMahershala, memberShia]; const members: Array<ConversationType> = [memberMahershala, memberShia];
const singleMember: ConversationType = { const singleMember: ConversationType = getDefaultConversation({
id: '666777', id: '666777',
uuid: 'pqrstuv', uuid: 'pqrstuv',
title: 'The Guy', title: 'The Guy',
@ -45,7 +46,7 @@ const singleMember: ConversationType = {
lastUpdated: Date.now(), lastUpdated: Date.now(),
markedUnread: false, markedUnread: false,
areWeAdmin: false, areWeAdmin: false,
}; });
describe('MemberRepository', () => { describe('MemberRepository', () => {
describe('#updateMembers', () => { describe('#updateMembers', () => {

View file

@ -8,6 +8,7 @@ import Delta from 'quill-delta';
import { matchMention } from '../../../quill/mentions/matchers'; import { matchMention } from '../../../quill/mentions/matchers';
import { MemberRepository } from '../../../quill/memberRepository'; import { MemberRepository } from '../../../quill/memberRepository';
import { ConversationType } from '../../../state/ducks/conversations'; import { ConversationType } from '../../../state/ducks/conversations';
import { getDefaultConversation } from '../../../test-both/helpers/getDefaultConversation';
class FakeTokenList<T> extends Array<T> { class FakeTokenList<T> extends Array<T> {
constructor(elements: Array<T>) { constructor(elements: Array<T>) {
@ -37,7 +38,7 @@ const createMockMentionBlotElement = (
dataset: Record<string, string> dataset: Record<string, string>
): HTMLElement => createMockElement('mention-blot', dataset); ): HTMLElement => createMockElement('mention-blot', dataset);
const memberMahershala: ConversationType = { const memberMahershala: ConversationType = getDefaultConversation({
id: '555444', id: '555444',
uuid: 'abcdefg', uuid: 'abcdefg',
title: 'Mahershala Ali', title: 'Mahershala Ali',
@ -47,9 +48,9 @@ const memberMahershala: ConversationType = {
lastUpdated: Date.now(), lastUpdated: Date.now(),
markedUnread: false, markedUnread: false,
areWeAdmin: false, areWeAdmin: false,
}; });
const memberShia: ConversationType = { const memberShia: ConversationType = getDefaultConversation({
id: '333222', id: '333222',
uuid: 'hijklmno', uuid: 'hijklmno',
title: 'Shia LaBeouf', title: 'Shia LaBeouf',
@ -59,7 +60,7 @@ const memberShia: ConversationType = {
lastUpdated: Date.now(), lastUpdated: Date.now(),
markedUnread: false, markedUnread: false,
areWeAdmin: false, areWeAdmin: false,
}; });
const members: Array<ConversationType> = [memberMahershala, memberShia]; const members: Array<ConversationType> = [memberMahershala, memberShia];

View file

@ -7,7 +7,7 @@ export const shouldBlurAvatar = ({
acceptedMessageRequest, acceptedMessageRequest,
avatarPath, avatarPath,
isMe, isMe,
sharedGroupNames = [], sharedGroupNames,
unblurredAvatarPath, unblurredAvatarPath,
}: Readonly< }: Readonly<
Pick< Pick<