Improve types for `ConversationType`'s `lastMessage`

This commit is contained in:
Evan Hahn 2021-09-20 14:20:53 -05:00 committed by GitHub
parent c19a801b89
commit 4e43459d34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 68 deletions

View File

@ -230,6 +230,7 @@ story.add('Contact checkboxes: disabled', () => (
MessageStatuses.reduce((m, s) => ({ ...m, [s]: s }), {}),
'read'
),
deletedForEveryone: false,
},
lastUpdated: date(
'lastUpdated',
@ -264,6 +265,7 @@ story.add('Contact checkboxes: disabled', () => (
lastMessage: {
text: 'Just a second',
status: 'read',
deletedForEveryone: false,
},
name: 'Myself',
title: 'Myself',
@ -277,7 +279,7 @@ story.add('Contact checkboxes: disabled', () => (
MessageStatuses.map(status => ({
type: RowType.Conversation,
conversation: createConversation({
lastMessage: { text: status, status },
lastMessage: { text: status, status, deletedForEveryone: false },
}),
}))
)}
@ -302,11 +304,7 @@ story.add('Contact checkboxes: disabled', () => (
story.add('Conversation: Deleted for everyone', () =>
renderConversation({
lastMessage: {
status: 'sent',
text: 'You should not see this!',
deletedForEveryone: true,
},
lastMessage: { deletedForEveryone: true },
})
);
@ -316,6 +314,7 @@ story.add('Contact checkboxes: disabled', () => (
lastMessage: {
text: 'A Message',
status: 'delivered',
deletedForEveryone: false,
},
})
);
@ -326,7 +325,11 @@ story.add('Contact checkboxes: disabled', () => (
[4, 10, 250].map(unreadCount => ({
type: RowType.Conversation,
conversation: createConversation({
lastMessage: { text: 'Hey there!', status: 'delivered' },
lastMessage: {
text: 'Hey there!',
status: 'delivered',
deletedForEveryone: false,
},
unreadCount,
}),
}))
@ -343,6 +346,7 @@ story.add('Contact checkboxes: disabled', () => (
lastMessage: {
text: 'Hey there!',
status: 'read',
deletedForEveryone: false,
},
isSelected: true,
})
@ -353,6 +357,7 @@ story.add('Contact checkboxes: disabled', () => (
lastMessage: {
text: '🔥',
status: 'read',
deletedForEveryone: false,
},
})
);
@ -362,6 +367,7 @@ story.add('Contact checkboxes: disabled', () => (
lastMessage: {
text: 'Download at http://signal.org',
status: 'read',
deletedForEveryone: false,
},
})
);
@ -394,6 +400,7 @@ Line 4, well.`,
lastMessage: {
text: messageText,
status: 'read',
deletedForEveryone: false,
},
}),
}))
@ -420,6 +427,7 @@ Line 4, well.`,
lastMessage: {
text: messageText,
status: 'read',
deletedForEveryone: false,
},
}),
}))
@ -449,9 +457,9 @@ Line 4, well.`,
story.add('Conversation: Missing Text', () =>
renderConversation({
lastMessage: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
text: undefined as any,
text: '',
status: 'sent',
deletedForEveryone: false,
},
})
);
@ -469,6 +477,7 @@ Line 4, well.`,
lastMessage: {
text: '@Leia Organa I know',
status: 'read',
deletedForEveryone: false,
},
})
);

View File

@ -97,60 +97,44 @@ export const ConversationListItem: FunctionComponent<Props> = React.memo(
let messageText: ReactNode = null;
let messageStatusIcon: ReactNode = null;
if (lastMessage || typingContact) {
const messageBody = lastMessage ? lastMessage.text : '';
const showingDraft = shouldShowDraft && draftPreview;
const deletedForEveryone = Boolean(
lastMessage && lastMessage.deletedForEveryone
if (!acceptedMessageRequest) {
messageText = (
<span className={`${MESSAGE_TEXT_CLASS_NAME}__message-request`}>
{i18n('ConversationListItem--message-request')}
</span>
);
/* eslint-disable no-nested-ternary */
} else if (typingContact) {
messageText = <TypingAnimation i18n={i18n} />;
} else if (shouldShowDraft && draftPreview) {
messageText = (
<>
{muteExpiresAt && Date.now() < muteExpiresAt ? (
<span className={`${MESSAGE_TEXT_CLASS_NAME}__muted`} />
) : null}
{!acceptedMessageRequest ? (
<span className={`${MESSAGE_TEXT_CLASS_NAME}__message-request`}>
{i18n('ConversationListItem--message-request')}
</span>
) : typingContact ? (
<TypingAnimation i18n={i18n} />
) : (
<>
{showingDraft ? (
<>
<span className={`${MESSAGE_TEXT_CLASS_NAME}__draft-prefix`}>
{i18n('ConversationListItem--draft-prefix')}
</span>
<MessageBody
text={truncateMessageText(draftPreview)}
disableJumbomoji
disableLinks
i18n={i18n}
/>
</>
) : deletedForEveryone ? (
<span
className={`${MESSAGE_TEXT_CLASS_NAME}__deleted-for-everyone`}
>
{i18n('message--deletedForEveryone')}
</span>
) : (
<MessageBody
text={truncateMessageText(messageBody)}
disableJumbomoji
disableLinks
i18n={i18n}
/>
)}
</>
)}
<span className={`${MESSAGE_TEXT_CLASS_NAME}__draft-prefix`}>
{i18n('ConversationListItem--draft-prefix')}
</span>
<MessageBody
text={truncateMessageText(draftPreview)}
disableJumbomoji
disableLinks
i18n={i18n}
/>
</>
);
/* eslint-enable no-nested-ternary */
if (!showingDraft && lastMessage && lastMessage.status) {
} else if (lastMessage?.deletedForEveryone) {
messageText = (
<span className={`${MESSAGE_TEXT_CLASS_NAME}__deleted-for-everyone`}>
{i18n('message--deletedForEveryone')}
</span>
);
} else if (lastMessage) {
messageText = (
<MessageBody
text={truncateMessageText(lastMessage.text)}
disableJumbomoji
disableLinks
i18n={i18n}
/>
);
if (lastMessage.status) {
messageStatusIcon = (
<div
className={classNames(
@ -162,6 +146,16 @@ export const ConversationListItem: FunctionComponent<Props> = React.memo(
}
}
const isMuted = Boolean(muteExpiresAt && Date.now() < muteExpiresAt);
if (isMuted) {
messageText = (
<>
<span className={`${MESSAGE_TEXT_CLASS_NAME}__muted`} />
{messageText}
</>
);
}
const onClickItem = useCallback(() => onClick(id), [onClick, id]);
return (

View File

@ -7,6 +7,7 @@ import { compact } from 'lodash';
import {
ConversationAttributesType,
ConversationModelCollectionType,
LastMessageStatus,
MessageAttributesType,
MessageModelCollectionType,
QuotedMessageType,
@ -50,6 +51,7 @@ import { BodyRangesType } from '../types/Util';
import { getTextWithMentions } from '../util';
import { migrateColor } from '../util/migrateColor';
import { isNotNil } from '../util/isNotNil';
import { dropNull } from '../util/dropNull';
import { ourProfileKeyService } from '../services/ourProfileKey';
import { getSendOptions } from '../util/getSendOptions';
import { isConversationAccepted } from '../util/isConversationAccepted';
@ -1348,6 +1350,28 @@ export class ConversationModel extends window.Backbone
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const color = this.getColor()!;
let lastMessage:
| undefined
| {
status?: LastMessageStatus;
text: string;
deletedForEveryone: false;
}
| { deletedForEveryone: true };
if (this.get('lastMessageDeletedForEveryone')) {
lastMessage = { deletedForEveryone: true };
} else {
const lastMessageText = this.get('lastMessage');
if (lastMessageText) {
lastMessage = {
status: dropNull(this.get('lastMessageStatus')),
text: lastMessageText,
deletedForEveryone: false,
};
}
}
const typingValues = window._.values(this.contactTypingTimers || {});
const typingMostRecent = window._.first(
window._.sortBy(typingValues, 'timestamp')
@ -1440,11 +1464,7 @@ export class ConversationModel extends window.Backbone
isUntrusted: this.isUntrusted(),
isVerified: this.isVerified(),
isFetchingUUID: this.isFetchingUUID,
lastMessage: {
status: this.get('lastMessageStatus')!,
text: this.get('lastMessage')!,
deletedForEveryone: this.get('lastMessageDeletedForEveryone')!,
},
lastMessage,
lastUpdated: this.get('timestamp')!,
left: Boolean(this.get('left')),
markedUnread: this.get('markedUnread')!,

View File

@ -116,11 +116,13 @@ export type ConversationType = {
timestamp?: number;
inboxPosition?: number;
left?: boolean;
lastMessage?: {
status: LastMessageStatus;
text: string;
deletedForEveryone?: boolean;
};
lastMessage?:
| {
status?: LastMessageStatus;
text: string;
deletedForEveryone: false;
}
| { deletedForEveryone: true };
markedUnread?: boolean;
phoneNumber?: string;
membersCount?: number;