uniformized props for Message

This commit is contained in:
Audric Ackermann 2021-07-08 16:43:32 +10:00
parent ee4a0b9b1e
commit f0fad6edfa
No known key found for this signature in database
GPG key ID: 999F434D76324AD4
10 changed files with 59 additions and 69 deletions

View file

@ -5,7 +5,7 @@ import { Emojify } from './Emojify';
type Props = {
phoneNumber: string;
name?: string;
name?: string | null;
profileName?: string;
module?: string;
boldProfileName?: Boolean;

View file

@ -29,7 +29,6 @@ import _ from 'lodash';
import { animation, contextMenu, Item, Menu } from 'react-contexify';
import uuid from 'uuid';
import { InView } from 'react-intersection-observer';
import { withTheme } from 'styled-components';
import { MessageMetadata } from './message/MessageMetadata';
import { PubKey } from '../../session/types';
import { MessageRegularProps } from '../../models/messageType';
@ -56,7 +55,7 @@ interface State {
const EXPIRATION_CHECK_MINIMUM = 2000;
const EXPIRED_DELAY = 600;
class MessageInner extends React.PureComponent<MessageRegularProps, State> {
export class Message extends React.PureComponent<MessageRegularProps, State> {
public expirationCheckInterval: any;
public expiredTimeout: any;
public ctxMenuID: string;
@ -279,14 +278,7 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
// tslint:disable-next-line cyclomatic-complexity
public renderPreview() {
const {
attachments,
conversationType,
direction,
onClickLinkPreview,
previews,
quote,
} = this.props;
const { attachments, conversationType, direction, previews, quote } = this.props;
// Attachments take precedence over Link Previews
if (attachments && attachments.length) {
@ -316,11 +308,6 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
'module-message__link-preview',
withContentAbove ? 'module-message__link-preview--with-content-above' : null
)}
onClick={() => {
if (onClickLinkPreview) {
onClickLinkPreview(first.url);
}
}}
>
{first.image && previewHasImage && isFullSizeImage ? (
<ImageGrid
@ -898,5 +885,3 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
await removeSenderFromModerator(this.props.authorPhoneNumber, this.props.convoId);
}
}
export const Message = withTheme(MessageInner);

View file

@ -4,25 +4,24 @@ import { OutgoingMessageStatus } from './OutgoingMessageStatus';
import { MetadataBadges } from './MetadataBadge';
import { Timestamp } from '../Timestamp';
import { ExpireTimer } from '../ExpireTimer';
import styled, { DefaultTheme } from 'styled-components';
import styled, { DefaultTheme, useTheme } from 'styled-components';
import { MessageDeliveryStatus, MessageModelType } from '../../../models/messageType';
type Props = {
disableMenu?: boolean;
isAdmin?: boolean;
isDeletable: boolean;
text?: string;
text?: string | null;
id: string;
collapseMetadata?: boolean;
direction: MessageModelType;
timestamp: number;
serverTimestamp?: number;
status?: MessageDeliveryStatus;
status?: MessageDeliveryStatus | null;
expirationLength?: number;
expirationTimestamp?: number;
isPublic?: boolean;
isShowingImage: boolean;
theme: DefaultTheme;
};
// for some reason, we have to extend a styled component as this:
// props => <OpacityMetadataComponent {...props}/>
@ -68,9 +67,10 @@ export const MessageMetadata = (props: Props) => {
isShowingImage,
isPublic,
isAdmin,
theme,
} = props;
const theme = useTheme();
if (collapseMetadata) {
return null;
}
@ -80,7 +80,7 @@ export const MessageMetadata = (props: Props) => {
const showError = status === 'error' && isOutgoing;
const showStatus = Boolean(status?.length && isOutgoing);
const messageStatusColor = withImageNoCaption ? 'white' : props.theme.colors.sentMessageText;
const messageStatusColor = withImageNoCaption ? 'white' : theme.colors.sentMessageText;
return (
<MetadatasContainer withImageNoCaption={withImageNoCaption} {...props}>
{showError ? (

View file

@ -61,7 +61,7 @@ const MessageStatusError = () => {
};
export const OutgoingMessageStatus = (props: {
status?: MessageDeliveryStatus;
status?: MessageDeliveryStatus | null;
iconColor: string;
isInMessageView?: boolean;
}) => {

View file

@ -26,6 +26,7 @@ import {
ReduxConversationType,
PropsForMessage,
SortedMessageModelProps,
fetchMessagesForConversation,
} from '../../../state/ducks/conversations';
import { MessageView } from '../../MainViewController';
import { pushUnblockToSend } from '../../../session/utils/Toast';
@ -304,7 +305,7 @@ export class SessionConversation extends React.Component<Props, State> {
Constants.CONVERSATION.DEFAULT_MESSAGE_FETCH_COUNT,
unreadCount
);
window.inboxStore?.dispatch(
(window.inboxStore?.dispatch as any)(
fetchMessagesForConversation({
conversationKey: selectedConversationKey,
count: messagesToFetch,
@ -991,6 +992,3 @@ export class SessionConversation extends React.Component<Props, State> {
window.inboxStore?.dispatch(updateMentionsMembers(allMembers));
}
}
function fetchMessagesForConversation(arg0: { conversationKey: string; count: number }): any {
throw new Error('Function not implemented.');
}

View file

@ -10,7 +10,11 @@ import { contextMenu } from 'react-contexify';
import { AttachmentType } from '../../../types/Attachment';
import { GroupNotification } from '../../conversation/GroupNotification';
import { GroupInvitation } from '../../conversation/GroupInvitation';
import { ReduxConversationType, SortedMessageModelProps } from '../../../state/ducks/conversations';
import {
fetchMessagesForConversation,
ReduxConversationType,
SortedMessageModelProps,
} from '../../../state/ducks/conversations';
import { SessionLastSeenIndicator } from './SessionLastSeenIndicator';
import { ToastUtils } from '../../../session/utils';
import { TypingBubble } from '../../conversation/TypingBubble';
@ -303,20 +307,12 @@ export class SessionMessagesList extends React.Component<Props, State> {
multiSelectMode: boolean,
playableMessageIndex: number
) {
const regularProps: MessageRegularProps = { ...messageProps.propsForMessage };
const messageId = messageProps.propsForMessage.id;
const selected =
!!messageProps?.propsForMessage.id && this.props.selectedMessages.includes(messageId);
regularProps.selected = selected;
regularProps.firstMessageOfSeries = firstMessageOfSeries;
regularProps.multiSelectMode = multiSelectMode;
regularProps.onSelectMessage = this.props.selectMessage;
regularProps.onDeleteMessage = this.props.deleteMessage;
regularProps.onReply = this.props.replyToMessage;
regularProps.onShowDetail = async () => {
const onShowDetail = async () => {
const found = await getMessageById(messageId);
if (found) {
const messageDetailsProps = await found.getPropsForMessageDetail();
@ -327,10 +323,16 @@ export class SessionMessagesList extends React.Component<Props, State> {
}
};
regularProps.onClickAttachment = (attachment: AttachmentType) => {
const onClickAttachment = (attachment: AttachmentType) => {
this.props.onClickAttachment(attachment, messageProps.propsForMessage);
};
regularProps.onDownload = (attachment: AttachmentType) => {
// tslint:disable-next-line: no-async-without-await
const onQuoteClick = messageProps.propsForMessage.quote
? this.scrollToQuoteMessage
: async () => {};
const onDownload = (attachment: AttachmentType) => {
const messageTimestamp =
messageProps.propsForMessage.timestamp ||
messageProps.propsForMessage.serverTimestamp ||
@ -343,14 +345,23 @@ export class SessionMessagesList extends React.Component<Props, State> {
});
};
regularProps.isQuotedMessageToAnimate = messageId === this.state.animateQuotedMessageId;
// tslint:disable-next-line: no-async-without-await
const onQuoteClick = regularProps.quote ? this.scrollToQuoteMessage : async () => {};
regularProps.nextMessageToPlay = this.state.nextMessageToPlay;
regularProps.playableMessageIndex = playableMessageIndex;
regularProps.playNextMessage = this.playNextMessage;
const regularProps: MessageRegularProps = {
...messageProps.propsForMessage,
selected,
firstMessageOfSeries,
multiSelectMode,
isQuotedMessageToAnimate: messageId === this.state.animateQuotedMessageId,
nextMessageToPlay: this.state.nextMessageToPlay,
playableMessageIndex,
onSelectMessage: this.props.selectMessage,
onDeleteMessage: this.props.deleteMessage,
onReply: this.props.replyToMessage,
onShowDetail,
onClickAttachment,
onDownload,
playNextMessage: this.playNextMessage,
onQuoteClick,
};
return <Message {...regularProps} onQuoteClick={onQuoteClick} key={messageId} />;
}
@ -461,7 +472,7 @@ export class SessionMessagesList extends React.Component<Props, State> {
const oldLen = messagesProps.length;
const previousTopMessage = messagesProps[oldLen - 1]?.propsForMessage.id;
window.inboxStore?.dispatch(
(window.inboxStore?.dispatch as any)(
fetchMessagesForConversation({ conversationKey, count: numMessages })
);
if (previousTopMessage && oldLen !== messagesProps.length) {
@ -623,6 +634,3 @@ export class SessionMessagesList extends React.Component<Props, State> {
return scrollHeight - scrollTop - clientHeight;
}
}
function fetchMessagesForConversation(arg0: { conversationKey: string; count: number }): any {
throw new Error('Function not implemented.');
}

View file

@ -111,7 +111,7 @@ export function unbanUser(userToUnBan: string, conversationId: string) {
);
}
export function copyBodyToClipboard(body?: string) {
export function copyBodyToClipboard(body?: string | null) {
window.clipboard.writeText(body);
ToastUtils.pushCopiedToClipBoard();

View file

@ -548,7 +548,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
text: this.createNonBreakingLastSeparator(this.get('body')),
id: this.id as string,
direction: (this.isIncoming() ? 'incoming' : 'outgoing') as MessageModelType,
timestamp: this.get('sent_at'),
timestamp: this.get('sent_at') || 0,
receivedAt: this.get('received_at'),
serverTimestamp: this.get('serverTimestamp'),
serverId: this.get('serverId'),
@ -574,6 +574,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
weAreAdmin,
isDeletable,
isSenderAdmin,
isExpired: this.isExpired(),
};
return props;

View file

@ -51,7 +51,7 @@ export interface MessageAttributes {
* timestamp is the sent_at timestamp, which is the envelope.timestamp
*/
timestamp?: number;
status: MessageDeliveryStatus;
status?: MessageDeliveryStatus;
dataMessage: any;
sent_to: any;
sent: boolean;
@ -202,20 +202,20 @@ export interface MessageRegularProps {
isDeletable: boolean;
isAdmin?: boolean;
weAreAdmin?: boolean;
text?: string;
text: string | null;
id: string;
collapseMetadata?: boolean;
direction: MessageModelType;
timestamp: number;
serverTimestamp?: number;
status?: MessageDeliveryStatus;
status?: MessageDeliveryStatus | null;
// What if changed this over to a single contact like quote, and put the events on it?
contact?: Contact & {
onSendMessage?: () => void;
onClick?: () => void;
};
authorName?: string;
authorProfileName?: string;
authorName?: string | null;
authorProfileName?: string | null;
/** Note: this should be formatted for display */
authorPhoneNumber: string;
conversationType: ConversationTypeEnum;
@ -247,16 +247,13 @@ export interface MessageRegularProps {
isQuotedMessageToAnimate?: boolean;
isTrustedForAttachmentDownload: boolean;
onClickAttachment?: (attachment: AttachmentType) => void;
onClickLinkPreview?: (url: string) => void;
onClickAttachment: (attachment: AttachmentType) => void;
onSelectMessage: (messageId: string) => void;
onReply?: (messagId: number) => void;
onDownload?: (attachment: AttachmentType) => void;
onReply: (messagId: number) => void;
onDownload: (attachment: AttachmentType) => void;
onDeleteMessage: (messageId: string) => void;
onShowDetail: () => void;
markRead: (readAt: number) => Promise<void>;
onQuoteClick: (options: QuoteClickOptions) => Promise<void>;
theme: DefaultTheme;
playableMessageIndex?: number;
nextMessageToPlay?: number;

View file

@ -137,7 +137,7 @@ export type PropsForMessage = {
text: string | null;
id: string;
direction: MessageModelType;
timestamp: number | undefined;
timestamp: number;
receivedAt: number | undefined;
serverTimestamp: number | undefined;
serverId: number | undefined;
@ -161,6 +161,7 @@ export type PropsForMessage = {
weAreAdmin: boolean;
isSenderAdmin: boolean;
isDeletable: boolean;
isExpired: boolean;
};
export type LastMessageType = {
@ -287,7 +288,7 @@ type FetchedMessageResults = {
messagesProps: Array<SortedMessageModelProps>;
};
const fetchMessagesForConversation = createAsyncThunk(
export const fetchMessagesForConversation = createAsyncThunk(
'messages/fetchByConversationKey',
async ({
conversationKey,