Take an author object in <Message>
This commit is contained in:
parent
bca664b5d9
commit
5f17d01f49
7 changed files with 67 additions and 71 deletions
|
@ -66,12 +66,18 @@ 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,
|
||||||
authorId: overrideProps.authorId || 'some-id',
|
author: overrideProps.author || createAuthorProp(),
|
||||||
authorColor: select('authorColor', Colors, Colors[0]),
|
|
||||||
authorAvatarPath: overrideProps.authorAvatarPath,
|
|
||||||
authorTitle: text('authorTitle', overrideProps.authorTitle || ''),
|
|
||||||
bodyRanges: overrideProps.bodyRanges,
|
bodyRanges: overrideProps.bodyRanges,
|
||||||
canReply: true,
|
canReply: true,
|
||||||
canDownload: true,
|
canDownload: true,
|
||||||
|
@ -212,7 +218,7 @@ story.add('Pending', () => {
|
||||||
|
|
||||||
story.add('Collapsed Metadata', () => {
|
story.add('Collapsed Metadata', () => {
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
authorTitle: 'Fred Willard',
|
author: createAuthorProp({ title: 'Fred Willard' }),
|
||||||
collapseMetadata: true,
|
collapseMetadata: true,
|
||||||
conversationType: 'group',
|
conversationType: 'group',
|
||||||
text: 'Hello there from a pal!',
|
text: 'Hello there from a pal!',
|
||||||
|
@ -425,7 +431,7 @@ story.add('Reactions (short message)', () => {
|
||||||
|
|
||||||
story.add('Avatar in Group', () => {
|
story.add('Avatar in Group', () => {
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
authorAvatarPath: pngUrl,
|
author: createAuthorProp({ avatarPath: pngUrl }),
|
||||||
conversationType: 'group',
|
conversationType: 'group',
|
||||||
status: 'sent',
|
status: 'sent',
|
||||||
text: 'Hello it is me, the saxophone.',
|
text: 'Hello it is me, the saxophone.',
|
||||||
|
@ -921,15 +927,16 @@ story.add('Dangerous File Type', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
story.add('Colors', () => {
|
story.add('Colors', () => {
|
||||||
const defaultProps = createProps({
|
|
||||||
text:
|
|
||||||
'Hello there from a pal! I am sending a long message so that it will wrap a bit, since I like that look.',
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Colors.map(color => (
|
{Colors.map(color => (
|
||||||
<Message {...defaultProps} authorColor={color} />
|
<Message
|
||||||
|
{...createProps({
|
||||||
|
author: createAuthorProp({ color }),
|
||||||
|
text:
|
||||||
|
'Hello there from a pal! I am sending a long message so that it will wrap a bit, since I like that look.',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { drop, groupBy, orderBy, take } from 'lodash';
|
||||||
import { ContextMenu, ContextMenuTrigger, MenuItem } from 'react-contextmenu';
|
import { ContextMenu, ContextMenuTrigger, MenuItem } from 'react-contextmenu';
|
||||||
import { Manager, Popper, Reference } from 'react-popper';
|
import { Manager, Popper, Reference } from 'react-popper';
|
||||||
|
|
||||||
|
import { ConversationType } from '../../state/ducks/conversations';
|
||||||
import { Avatar } from '../Avatar';
|
import { Avatar } from '../Avatar';
|
||||||
import { Spinner } from '../Spinner';
|
import { Spinner } from '../Spinner';
|
||||||
import { MessageBody } from './MessageBody';
|
import { MessageBody } from './MessageBody';
|
||||||
|
@ -105,12 +106,16 @@ export type PropsData = {
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
status?: MessageStatusType;
|
status?: MessageStatusType;
|
||||||
contact?: ContactType;
|
contact?: ContactType;
|
||||||
authorId: string;
|
author: Pick<
|
||||||
authorTitle: string;
|
ConversationType,
|
||||||
authorName?: string;
|
| 'avatarPath'
|
||||||
authorProfileName?: string;
|
| 'color'
|
||||||
authorPhoneNumber?: string;
|
| 'id'
|
||||||
authorColor?: ColorType;
|
| 'name'
|
||||||
|
| 'phoneNumber'
|
||||||
|
| 'profileName'
|
||||||
|
| 'title'
|
||||||
|
>;
|
||||||
conversationType: ConversationTypesType;
|
conversationType: ConversationTypesType;
|
||||||
attachments?: Array<AttachmentType>;
|
attachments?: Array<AttachmentType>;
|
||||||
quote?: {
|
quote?: {
|
||||||
|
@ -128,7 +133,6 @@ export type PropsData = {
|
||||||
referencedMessageNotFound: boolean;
|
referencedMessageNotFound: boolean;
|
||||||
};
|
};
|
||||||
previews: Array<LinkPreviewType>;
|
previews: Array<LinkPreviewType>;
|
||||||
authorAvatarPath?: string;
|
|
||||||
isExpired?: boolean;
|
isExpired?: boolean;
|
||||||
|
|
||||||
isTapToView?: boolean;
|
isTapToView?: boolean;
|
||||||
|
@ -633,10 +637,7 @@ export class Message extends React.Component<Props, State> {
|
||||||
|
|
||||||
public renderAuthor(): JSX.Element | null {
|
public renderAuthor(): JSX.Element | null {
|
||||||
const {
|
const {
|
||||||
authorTitle,
|
author,
|
||||||
authorName,
|
|
||||||
authorPhoneNumber,
|
|
||||||
authorProfileName,
|
|
||||||
collapseMetadata,
|
collapseMetadata,
|
||||||
conversationType,
|
conversationType,
|
||||||
direction,
|
direction,
|
||||||
|
@ -653,7 +654,7 @@ export class Message extends React.Component<Props, State> {
|
||||||
if (
|
if (
|
||||||
direction !== 'incoming' ||
|
direction !== 'incoming' ||
|
||||||
conversationType !== 'group' ||
|
conversationType !== 'group' ||
|
||||||
!authorTitle
|
!author.title
|
||||||
) {
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -669,10 +670,10 @@ export class Message extends React.Component<Props, State> {
|
||||||
return (
|
return (
|
||||||
<div className={moduleName}>
|
<div className={moduleName}>
|
||||||
<ContactName
|
<ContactName
|
||||||
title={authorTitle}
|
title={author.title}
|
||||||
phoneNumber={authorPhoneNumber}
|
phoneNumber={author.phoneNumber}
|
||||||
name={authorName}
|
name={author.name}
|
||||||
profileName={authorProfileName}
|
profileName={author.profileName}
|
||||||
module={moduleName}
|
module={moduleName}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
/>
|
/>
|
||||||
|
@ -996,8 +997,8 @@ export class Message extends React.Component<Props, State> {
|
||||||
|
|
||||||
public renderQuote(): JSX.Element | null {
|
public renderQuote(): JSX.Element | null {
|
||||||
const {
|
const {
|
||||||
|
author,
|
||||||
conversationType,
|
conversationType,
|
||||||
authorColor,
|
|
||||||
direction,
|
direction,
|
||||||
disableScroll,
|
disableScroll,
|
||||||
i18n,
|
i18n,
|
||||||
|
@ -1012,7 +1013,7 @@ export class Message extends React.Component<Props, State> {
|
||||||
const withContentAbove =
|
const withContentAbove =
|
||||||
conversationType === 'group' && direction === 'incoming';
|
conversationType === 'group' && direction === 'incoming';
|
||||||
const quoteColor =
|
const quoteColor =
|
||||||
direction === 'incoming' ? authorColor : quote.authorColor;
|
direction === 'incoming' ? author.color : quote.authorColor;
|
||||||
const { referencedMessageNotFound } = quote;
|
const { referencedMessageNotFound } = quote;
|
||||||
|
|
||||||
const clickHandler = disableScroll
|
const clickHandler = disableScroll
|
||||||
|
@ -1104,14 +1105,8 @@ export class Message extends React.Component<Props, State> {
|
||||||
|
|
||||||
public renderAvatar(): JSX.Element | undefined {
|
public renderAvatar(): JSX.Element | undefined {
|
||||||
const {
|
const {
|
||||||
authorAvatarPath,
|
author,
|
||||||
authorId,
|
|
||||||
authorName,
|
|
||||||
authorPhoneNumber,
|
|
||||||
authorProfileName,
|
|
||||||
authorTitle,
|
|
||||||
collapseMetadata,
|
collapseMetadata,
|
||||||
authorColor,
|
|
||||||
conversationType,
|
conversationType,
|
||||||
direction,
|
direction,
|
||||||
i18n,
|
i18n,
|
||||||
|
@ -1135,18 +1130,18 @@ export class Message extends React.Component<Props, State> {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="module-message__author-avatar"
|
className="module-message__author-avatar"
|
||||||
onClick={() => showContactModal(authorId)}
|
onClick={() => showContactModal(author.id)}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
avatarPath={authorAvatarPath}
|
avatarPath={author.avatarPath}
|
||||||
color={authorColor}
|
color={author.color}
|
||||||
conversationType="direct"
|
conversationType="direct"
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
name={authorName}
|
name={author.name}
|
||||||
phoneNumber={authorPhoneNumber}
|
phoneNumber={author.phoneNumber}
|
||||||
profileName={authorProfileName}
|
profileName={author.profileName}
|
||||||
title={authorTitle}
|
title={author.title}
|
||||||
size={28}
|
size={28}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
@ -2191,7 +2186,7 @@ export class Message extends React.Component<Props, State> {
|
||||||
|
|
||||||
public renderContainer(): JSX.Element {
|
public renderContainer(): JSX.Element {
|
||||||
const {
|
const {
|
||||||
authorColor,
|
author,
|
||||||
deletedForEveryone,
|
deletedForEveryone,
|
||||||
direction,
|
direction,
|
||||||
isSticker,
|
isSticker,
|
||||||
|
@ -2216,13 +2211,13 @@ export class Message extends React.Component<Props, State> {
|
||||||
? 'module-message__container--with-tap-to-view-expired'
|
? 'module-message__container--with-tap-to-view-expired'
|
||||||
: null,
|
: null,
|
||||||
!isSticker && direction === 'incoming'
|
!isSticker && direction === 'incoming'
|
||||||
? `module-message__container--incoming-${authorColor}`
|
? `module-message__container--incoming-${author.color}`
|
||||||
: null,
|
: null,
|
||||||
isTapToView && isAttachmentPending && !isTapToViewExpired
|
isTapToView && isAttachmentPending && !isTapToViewExpired
|
||||||
? 'module-message__container--with-tap-to-view-pending'
|
? 'module-message__container--with-tap-to-view-pending'
|
||||||
: null,
|
: null,
|
||||||
isTapToView && isAttachmentPending && !isTapToViewExpired
|
isTapToView && isAttachmentPending && !isTapToViewExpired
|
||||||
? `module-message__container--${direction}-${authorColor}-tap-to-view-pending`
|
? `module-message__container--${direction}-${author.color}-tap-to-view-pending`
|
||||||
: null,
|
: null,
|
||||||
isTapToViewError
|
isTapToViewError
|
||||||
? 'module-message__container--with-tap-to-view-error'
|
? 'module-message__container--with-tap-to-view-error'
|
||||||
|
@ -2249,7 +2244,7 @@ export class Message extends React.Component<Props, State> {
|
||||||
|
|
||||||
public render(): JSX.Element | null {
|
public render(): JSX.Element | null {
|
||||||
const {
|
const {
|
||||||
authorId,
|
author,
|
||||||
attachments,
|
attachments,
|
||||||
direction,
|
direction,
|
||||||
id,
|
id,
|
||||||
|
@ -2260,7 +2255,7 @@ export class Message extends React.Component<Props, State> {
|
||||||
|
|
||||||
// This id is what connects our triple-dot click with our associated pop-up menu.
|
// This id is what connects our triple-dot click with our associated pop-up menu.
|
||||||
// It needs to be unique.
|
// It needs to be unique.
|
||||||
const triggerId = String(id || `${authorId}-${timestamp}`);
|
const triggerId = String(id || `${author.id}-${timestamp}`);
|
||||||
|
|
||||||
if (expired) {
|
if (expired) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -17,8 +17,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 = {
|
||||||
authorId: 'some-id',
|
author: {
|
||||||
authorTitle: 'Max',
|
id: 'some-id',
|
||||||
|
title: 'Max',
|
||||||
|
},
|
||||||
canReply: true,
|
canReply: true,
|
||||||
canDeleteForEveryone: true,
|
canDeleteForEveryone: true,
|
||||||
canDownload: true,
|
canDownload: true,
|
||||||
|
|
|
@ -27,8 +27,10 @@ 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 = {
|
||||||
authorId: 'some-id',
|
author: {
|
||||||
authorTitle: 'Person X',
|
id: 'some-id',
|
||||||
|
title: 'Person X',
|
||||||
|
},
|
||||||
canReply: true,
|
canReply: true,
|
||||||
canDeleteForEveryone: true,
|
canDeleteForEveryone: true,
|
||||||
canDownload: true,
|
canDownload: true,
|
||||||
|
|
|
@ -84,8 +84,10 @@ storiesOf('Components/Conversation/TimelineItem', module)
|
||||||
id: 'id-1',
|
id: 'id-1',
|
||||||
direction: 'incoming',
|
direction: 'incoming',
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
authorPhoneNumber: '(202) 555-2001',
|
author: {
|
||||||
authorColor: 'green',
|
phoneNumber: '(202) 555-2001',
|
||||||
|
color: 'green',
|
||||||
|
},
|
||||||
text: '🔥',
|
text: '🔥',
|
||||||
},
|
},
|
||||||
} as TimelineItemProps['item'];
|
} as TimelineItemProps['item'];
|
||||||
|
|
|
@ -884,12 +884,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
getPropsForMessage(): PropsForMessage {
|
getPropsForMessage(): PropsForMessage {
|
||||||
const sourceId = this.getContactId();
|
const sourceId = this.getContactId();
|
||||||
const contact = this.findAndFormatContact(sourceId);
|
const contact = this.findAndFormatContact(sourceId);
|
||||||
const contactModel = this.findContact(sourceId);
|
|
||||||
|
|
||||||
const authorColor = contactModel ? contactModel.getColor() : undefined;
|
|
||||||
const authorAvatarPath = contactModel
|
|
||||||
? contactModel.getAbsoluteAvatarPath()
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const expirationLength = this.get('expireTimer') * 1000;
|
const expirationLength = this.get('expireTimer') * 1000;
|
||||||
const expireTimerStart = this.get('expirationStartTimestamp');
|
const expireTimerStart = this.get('expirationStartTimestamp');
|
||||||
|
@ -921,6 +915,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
).emoji;
|
).emoji;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
author: contact,
|
||||||
text: this.createNonBreakingLastSeparator(this.get('body')),
|
text: this.createNonBreakingLastSeparator(this.get('body')),
|
||||||
textPending: this.get('bodyPending'),
|
textPending: this.get('bodyPending'),
|
||||||
id: this.id,
|
id: this.id,
|
||||||
|
@ -933,17 +928,10 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
canReply: this.canReply(),
|
canReply: this.canReply(),
|
||||||
canDeleteForEveryone: this.canDeleteForEveryone(),
|
canDeleteForEveryone: this.canDeleteForEveryone(),
|
||||||
canDownload: this.canDownload(),
|
canDownload: this.canDownload(),
|
||||||
authorId: contact.id,
|
|
||||||
authorTitle: contact.title,
|
|
||||||
authorColor,
|
|
||||||
authorName: contact.name,
|
|
||||||
authorProfileName: contact.profileName,
|
|
||||||
authorPhoneNumber: contact.phoneNumber,
|
|
||||||
conversationType: isGroup ? 'group' : 'direct',
|
conversationType: isGroup ? 'group' : 'direct',
|
||||||
attachments: this.getAttachmentsForMessage(),
|
attachments: this.getAttachmentsForMessage(),
|
||||||
previews: this.getPropsForPreview(),
|
previews: this.getPropsForPreview(),
|
||||||
quote: this.getPropsForQuote(),
|
quote: this.getPropsForQuote(),
|
||||||
authorAvatarPath,
|
|
||||||
isExpired: this.hasExpired,
|
isExpired: this.hasExpired,
|
||||||
expirationLength,
|
expirationLength,
|
||||||
expirationTimestamp,
|
expirationTimestamp,
|
||||||
|
|
|
@ -16573,7 +16573,7 @@
|
||||||
"rule": "React-createRef",
|
"rule": "React-createRef",
|
||||||
"path": "ts/components/conversation/Message.tsx",
|
"path": "ts/components/conversation/Message.tsx",
|
||||||
"line": " public focusRef: React.RefObject<HTMLDivElement> = React.createRef();",
|
"line": " public focusRef: React.RefObject<HTMLDivElement> = React.createRef();",
|
||||||
"lineNumber": 242,
|
"lineNumber": 246,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2021-03-05T19:57:01.431Z",
|
"updated": "2021-03-05T19:57:01.431Z",
|
||||||
"reasonDetail": "Used for managing focus only"
|
"reasonDetail": "Used for managing focus only"
|
||||||
|
@ -16582,7 +16582,7 @@
|
||||||
"rule": "React-createRef",
|
"rule": "React-createRef",
|
||||||
"path": "ts/components/conversation/Message.tsx",
|
"path": "ts/components/conversation/Message.tsx",
|
||||||
"line": " public audioButtonRef: React.RefObject<HTMLButtonElement> = React.createRef();",
|
"line": " public audioButtonRef: React.RefObject<HTMLButtonElement> = React.createRef();",
|
||||||
"lineNumber": 244,
|
"lineNumber": 248,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2021-03-05T19:57:01.431Z",
|
"updated": "2021-03-05T19:57:01.431Z",
|
||||||
"reasonDetail": "Used for propagating click from the Message to MessageAudio's button"
|
"reasonDetail": "Used for propagating click from the Message to MessageAudio's button"
|
||||||
|
@ -16591,7 +16591,7 @@
|
||||||
"rule": "React-createRef",
|
"rule": "React-createRef",
|
||||||
"path": "ts/components/conversation/Message.tsx",
|
"path": "ts/components/conversation/Message.tsx",
|
||||||
"line": " public reactionsContainerRef: React.RefObject<HTMLDivElement> = React.createRef();",
|
"line": " public reactionsContainerRef: React.RefObject<HTMLDivElement> = React.createRef();",
|
||||||
"lineNumber": 246,
|
"lineNumber": 250,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2021-03-05T19:57:01.431Z",
|
"updated": "2021-03-05T19:57:01.431Z",
|
||||||
"reasonDetail": "Used for detecting clicks outside reaction viewer"
|
"reasonDetail": "Used for detecting clicks outside reaction viewer"
|
||||||
|
|
Loading…
Reference in a new issue