[IMPROVE] - migrating the message container (in progress)

This commit is contained in:
AlexAlexandre 2021-07-22 17:09:06 -03:00
parent 43c4234f73
commit 6db54e9920
12 changed files with 139 additions and 137 deletions

View File

@ -1,20 +1,27 @@
import React from 'react'; import React from 'react';
import { dequal } from 'dequal'; import { dequal } from 'dequal';
import PropTypes from 'prop-types';
import Image from './Image'; import Image from './Image';
import Audio from './Audio'; import Audio from './Audio';
import Video from './Video'; import Video from './Video';
import Reply from './Reply'; import Reply from './Reply';
interface IMessageAttachments {
attachments: any;
timeFormat: string;
showAttachment: Function;
getCustomEmoji: Function;
theme: string;
}
const Attachments = React.memo(({ const Attachments = React.memo(({
attachments, timeFormat, showAttachment, getCustomEmoji, theme attachments, timeFormat, showAttachment, getCustomEmoji, theme
}) => { }: IMessageAttachments) => {
if (!attachments || attachments.length === 0) { if (!attachments || attachments.length === 0) {
return null; return null;
} }
return attachments.map((file, index) => { return attachments.map((file: any, index: number) => {
if (file.image_url) { if (file.image_url) {
return <Image key={file.image_url} file={file} showAttachment={showAttachment} getCustomEmoji={getCustomEmoji} theme={theme} />; return <Image key={file.image_url} file={file} showAttachment={showAttachment} getCustomEmoji={getCustomEmoji} theme={theme} />;
} }
@ -30,13 +37,6 @@ const Attachments = React.memo(({
}); });
}, (prevProps, nextProps) => dequal(prevProps.attachments, nextProps.attachments) && prevProps.theme === nextProps.theme); }, (prevProps, nextProps) => dequal(prevProps.attachments, nextProps.attachments) && prevProps.theme === nextProps.theme);
Attachments.propTypes = {
attachments: PropTypes.array,
timeFormat: PropTypes.string,
showAttachment: PropTypes.func,
getCustomEmoji: PropTypes.func,
theme: PropTypes.string
};
Attachments.displayName = 'MessageAttachments'; Attachments.displayName = 'MessageAttachments';
export default Attachments; export default Attachments;

View File

@ -1,15 +1,19 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { messageBlockWithContext } from '../UIKit/MessageBlock'; import { messageBlockWithContext } from '../UIKit/MessageBlock';
const Blocks = React.memo(({ interface IMessageBlocks {
blocks, id: mid, rid, blockAction blocks: any;
}) => { id: string;
rid: string;
blockAction: Function;
}
const Blocks = React.memo(({ blocks, id: mid, rid, blockAction }: IMessageBlocks) => {
if (blocks && blocks.length > 0) { if (blocks && blocks.length > 0) {
const appId = blocks[0]?.appId || ''; const appId = blocks[0]?.appId || '';
return React.createElement( return React.createElement(
messageBlockWithContext({ messageBlockWithContext({
action: async({ actionId, value, blockId }) => { action: async({ actionId, value, blockId }: any) => {
await blockAction({ await blockAction({
actionId, actionId,
appId, appId,
@ -27,12 +31,6 @@ const Blocks = React.memo(({
return null; return null;
}); });
Blocks.propTypes = {
blocks: PropTypes.array,
id: PropTypes.string,
rid: PropTypes.string,
blockAction: PropTypes.func
};
Blocks.displayName = 'MessageBlocks'; Blocks.displayName = 'MessageBlocks';
export default Blocks; export default Blocks;

View File

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import { View, Text } from 'react-native'; import { View, Text } from 'react-native';
import PropTypes from 'prop-types';
import Touchable from './Touchable'; import Touchable from './Touchable';
import { BUTTON_HIT_SLOP } from './utils'; import { BUTTON_HIT_SLOP } from './utils';
@ -9,9 +8,12 @@ import I18n from '../../i18n';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
const CallButton = React.memo(({ interface IMessageCallButton {
theme, callJitsi theme: string;
}) => ( callJitsi: Function;
}
const CallButton = React.memo(({ theme, callJitsi }: IMessageCallButton) => (
<View style={styles.buttonContainer}> <View style={styles.buttonContainer}>
<Touchable <Touchable
onPress={callJitsi} onPress={callJitsi}
@ -27,10 +29,6 @@ const CallButton = React.memo(({
</View> </View>
)); ));
CallButton.propTypes = {
theme: PropTypes.string,
callJitsi: PropTypes.func
};
CallButton.displayName = 'CallButton'; CallButton.displayName = 'CallButton';
export default CallButton; export default CallButton;

View File

@ -25,7 +25,7 @@ type TMessageImage = {
interface IMessageImage { interface IMessageImage {
file: { image_url: string; description: string; }; file: { image_url: string; description: string; };
imageUrl: string; imageUrl?: string;
showAttachment: Function; showAttachment: Function;
theme: string; theme: string;
getCustomEmoji: Function; getCustomEmoji: Function;

View File

@ -1,13 +1,26 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import Avatar from '../Avatar'; import Avatar from '../Avatar';
import styles from './styles'; import styles from './styles';
import MessageContext from './Context'; import MessageContext from './Context';
interface IMessageAvatar {
isHeader: boolean;
avatar: string;
emoji: string;
author: {
username: string
_id: string;
};
small: boolean;
navToRoomInfo: Function;
getCustomEmoji(): void;
theme: string;
}
const MessageAvatar = React.memo(({ const MessageAvatar = React.memo(({
isHeader, avatar, author, small, navToRoomInfo, emoji, getCustomEmoji, theme isHeader, avatar, author, small, navToRoomInfo, emoji, getCustomEmoji, theme
}) => { }: IMessageAvatar) => {
const { user } = useContext(MessageContext); const { user } = useContext(MessageContext);
if (isHeader && author) { if (isHeader && author) {
const navParam = { const navParam = {
@ -31,16 +44,6 @@ const MessageAvatar = React.memo(({
return null; return null;
}); });
MessageAvatar.propTypes = {
isHeader: PropTypes.bool,
avatar: PropTypes.string,
emoji: PropTypes.string,
author: PropTypes.obj,
small: PropTypes.bool,
navToRoomInfo: PropTypes.func,
getCustomEmoji: PropTypes.func,
theme: PropTypes.string
};
MessageAvatar.displayName = 'MessageAvatar'; MessageAvatar.displayName = 'MessageAvatar';
export default MessageAvatar; export default MessageAvatar;

View File

@ -1,5 +1,4 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import Touchable from './Touchable'; import Touchable from './Touchable';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
@ -8,7 +7,12 @@ import { BUTTON_HIT_SLOP } from './utils';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import MessageContext from './Context'; import MessageContext from './Context';
const MessageError = React.memo(({ hasError, theme }) => { interface IMessageError {
hasError: boolean;
theme: string;
}
const MessageError = React.memo(({ hasError, theme }: IMessageError) => {
if (!hasError) { if (!hasError) {
return null; return null;
} }
@ -20,10 +24,6 @@ const MessageError = React.memo(({ hasError, theme }) => {
); );
}, (prevProps, nextProps) => prevProps.hasError === nextProps.hasError && prevProps.theme === nextProps.theme); }, (prevProps, nextProps) => prevProps.hasError === nextProps.hasError && prevProps.theme === nextProps.theme);
MessageError.propTypes = {
hasError: PropTypes.bool,
theme: PropTypes.string
};
MessageError.displayName = 'MessageError'; MessageError.displayName = 'MessageError';
export default MessageError; export default MessageError;

View File

@ -1,11 +1,16 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
import styles from './styles'; import styles from './styles';
const ReadReceipt = React.memo(({ isReadReceiptEnabled, unread, theme }) => { interface IMessageReadReceipt {
isReadReceiptEnabled: boolean;
unread: boolean;
theme: string;
}
const ReadReceipt = React.memo(({ isReadReceiptEnabled, unread, theme }: IMessageReadReceipt) => {
if (isReadReceiptEnabled && !unread && unread !== null) { if (isReadReceiptEnabled && !unread && unread !== null) {
return <CustomIcon name='check' color={themes[theme].tintColor} size={15} style={styles.readReceipt} />; return <CustomIcon name='check' color={themes[theme].tintColor} size={15} style={styles.readReceipt} />;
} }
@ -13,10 +18,4 @@ const ReadReceipt = React.memo(({ isReadReceiptEnabled, unread, theme }) => {
}); });
ReadReceipt.displayName = 'MessageReadReceipt'; ReadReceipt.displayName = 'MessageReadReceipt';
ReadReceipt.propTypes = {
isReadReceiptEnabled: PropTypes.bool,
unread: PropTypes.bool,
theme: PropTypes.bool
};
export default ReadReceipt; export default ReadReceipt;

View File

@ -1,6 +1,5 @@
import React, { memo, useEffect, useState } from 'react'; import React, { memo, useEffect, useState } from 'react';
import { View } from 'react-native'; import { View } from 'react-native';
import PropTypes from 'prop-types';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
import styles from './styles'; import styles from './styles';
@ -8,9 +7,19 @@ import { themes } from '../../constants/colors';
import I18n from '../../i18n'; import I18n from '../../i18n';
import Markdown from '../markdown'; import Markdown from '../markdown';
interface IMessageRepliedThread {
tmid: string;
tmsg: string;
id: string;
isHeader: boolean;
theme: string;
fetchThreadName: Function;
isEncrypted: boolean;
}
const RepliedThread = memo(({ const RepliedThread = memo(({
tmid, tmsg, isHeader, fetchThreadName, id, isEncrypted, theme tmid, tmsg, isHeader, fetchThreadName, id, isEncrypted, theme
}) => { }: IMessageRepliedThread) => {
if (!tmid || !isHeader) { if (!tmid || !isHeader) {
return null; return null;
} }
@ -34,6 +43,7 @@ const RepliedThread = memo(({
return ( return (
<View style={styles.repliedThread} testID={`message-thread-replied-on-${ msg }`}> <View style={styles.repliedThread} testID={`message-thread-replied-on-${ msg }`}>
<CustomIcon name='threads' size={20} style={styles.repliedThreadIcon} color={themes[theme].tintColor} /> <CustomIcon name='threads' size={20} style={styles.repliedThreadIcon} color={themes[theme].tintColor} />
{/*@ts-ignore*/}
<Markdown <Markdown
msg={msg} msg={msg}
theme={theme} theme={theme}
@ -52,15 +62,6 @@ const RepliedThread = memo(({
); );
}); });
RepliedThread.propTypes = {
tmid: PropTypes.string,
tmsg: PropTypes.string,
id: PropTypes.string,
isHeader: PropTypes.bool,
theme: PropTypes.string,
fetchThreadName: PropTypes.func,
isEncrypted: PropTypes.bool
};
RepliedThread.displayName = 'MessageRepliedThread'; RepliedThread.displayName = 'MessageRepliedThread';
export default RepliedThread; export default RepliedThread;

View File

@ -1,6 +1,5 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { View, Text } from 'react-native'; import { View, Text } from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles'; import styles from './styles';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
@ -8,9 +7,16 @@ import MessageContext from './Context';
import ThreadDetails from '../ThreadDetails'; import ThreadDetails from '../ThreadDetails';
import I18n from '../../i18n'; import I18n from '../../i18n';
const Thread = React.memo(({ interface IMessageThread {
msg, tcount, tlm, isThreadRoom, theme, id msg: string;
}) => { tcount: number;
theme: string;
tlm: string;
isThreadRoom: boolean;
id: string;
}
const Thread = React.memo(({ msg, tcount, tlm, isThreadRoom, theme, id }: IMessageThread) => {
if (!tlm || isThreadRoom || tcount === 0) { if (!tlm || isThreadRoom || tcount === 0) {
return null; return null;
} }
@ -50,14 +56,6 @@ const Thread = React.memo(({
return true; return true;
}); });
Thread.propTypes = {
msg: PropTypes.string,
tcount: PropTypes.string,
theme: PropTypes.string,
tlm: PropTypes.string,
isThreadRoom: PropTypes.bool,
id: PropTypes.string
};
Thread.displayName = 'MessageThread'; Thread.displayName = 'MessageThread';
export default Thread; export default Thread;

View File

@ -1,8 +1,5 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { import { View, Text, StyleSheet, Clipboard } from 'react-native';
View, Text, StyleSheet, Clipboard
} from 'react-native';
import PropTypes from 'prop-types';
import FastImage from '@rocket.chat/react-native-fast-image'; import FastImage from '@rocket.chat/react-native-fast-image';
import { dequal } from 'dequal'; import { dequal } from 'dequal';
@ -52,7 +49,30 @@ const styles = StyleSheet.create({
} }
}); });
const UrlImage = React.memo(({ image }) => { type TMessageUrlContent = {
title: string;
description: string;
theme: string;
};
type TMessageUrl = {
url: {
ignoreParse: boolean;
url: string;
image: string;
title: string;
description: string;
};
index: number;
theme: string;
};
interface IMessageUrls {
urls: any;
theme: string;
}
const UrlImage = React.memo(({ image }: {image: string}) => {
if (!image) { if (!image) {
return null; return null;
} }
@ -61,7 +81,7 @@ const UrlImage = React.memo(({ image }) => {
return <FastImage source={{ uri: image }} style={styles.image} resizeMode={FastImage.resizeMode.cover} />; return <FastImage source={{ uri: image }} style={styles.image} resizeMode={FastImage.resizeMode.cover} />;
}, (prevProps, nextProps) => prevProps.image === nextProps.image); }, (prevProps, nextProps) => prevProps.image === nextProps.image);
const UrlContent = React.memo(({ title, description, theme }) => ( const UrlContent = React.memo(({ title, description, theme }: TMessageUrlContent) => (
<View style={styles.textContainer}> <View style={styles.textContainer}>
{title ? <Text style={[styles.title, { color: themes[theme].tintColor }]} numberOfLines={2}>{title}</Text> : null} {title ? <Text style={[styles.title, { color: themes[theme].tintColor }]} numberOfLines={2}>{title}</Text> : null}
{description ? <Text style={[styles.description, { color: themes[theme].auxiliaryText }]} numberOfLines={2}>{description}</Text> : null} {description ? <Text style={[styles.description, { color: themes[theme].auxiliaryText }]} numberOfLines={2}>{description}</Text> : null}
@ -79,7 +99,7 @@ const UrlContent = React.memo(({ title, description, theme }) => (
return true; return true;
}); });
const Url = React.memo(({ url, index, theme }) => { const Url = React.memo(({ url, index, theme }: TMessageUrl) => {
if (!url || url?.ignoreParse) { if (!url || url?.ignoreParse) {
return null; return null;
} }
@ -114,39 +134,19 @@ const Url = React.memo(({ url, index, theme }) => {
); );
}, (oldProps, newProps) => dequal(oldProps.url, newProps.url) && oldProps.theme === newProps.theme); }, (oldProps, newProps) => dequal(oldProps.url, newProps.url) && oldProps.theme === newProps.theme);
const Urls = React.memo(({ urls, theme }) => { const Urls = React.memo(({ urls, theme }: IMessageUrls) => {
if (!urls || urls.length === 0) { if (!urls || urls.length === 0) {
return null; return null;
} }
return urls.map((url, index) => ( return urls.map((url: any, index: number) => (
<Url url={url} key={url.url} index={index} theme={theme} /> <Url url={url} key={url.url} index={index} theme={theme} />
)); ));
}, (oldProps, newProps) => dequal(oldProps.urls, newProps.urls) && oldProps.theme === newProps.theme); }, (oldProps, newProps) => dequal(oldProps.urls, newProps.urls) && oldProps.theme === newProps.theme);
UrlImage.propTypes = {
image: PropTypes.string
};
UrlImage.displayName = 'MessageUrlImage'; UrlImage.displayName = 'MessageUrlImage';
UrlContent.propTypes = {
title: PropTypes.string,
description: PropTypes.string,
theme: PropTypes.string
};
UrlContent.displayName = 'MessageUrlContent'; UrlContent.displayName = 'MessageUrlContent';
Url.propTypes = {
url: PropTypes.object.isRequired,
index: PropTypes.number,
theme: PropTypes.string
};
Url.displayName = 'MessageUrl'; Url.displayName = 'MessageUrl';
Urls.propTypes = {
urls: PropTypes.array,
theme: PropTypes.string
};
Urls.displayName = 'MessageUrls'; Urls.displayName = 'MessageUrls';
export default withTheme(Urls); export default withTheme(Urls);

View File

@ -1,8 +1,5 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import PropTypes from 'prop-types'; import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import {
View, Text, StyleSheet, TouchableOpacity
} from 'react-native';
import moment from 'moment'; import moment from 'moment';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
@ -41,9 +38,26 @@ const styles = StyleSheet.create({
} }
}); });
interface IMessageUser {
isHeader: boolean;
hasError: boolean;
useRealName: boolean;
author: {
_id: string;
name: string;
username: string;
};
alias: string;
ts: Date;
timeFormat: string;
theme: string;
navToRoomInfo: Function;
type: string;
}
const User = React.memo(({ const User = React.memo(({
isHeader, useRealName, author, alias, ts, timeFormat, hasError, theme, navToRoomInfo, type, ...props isHeader, useRealName, author, alias, ts, timeFormat, hasError, theme, navToRoomInfo, type, ...props
}) => { }: IMessageUser) => {
if (isHeader || hasError) { if (isHeader || hasError) {
const navParam = { const navParam = {
t: 'd', t: 'd',
@ -68,6 +82,7 @@ const User = React.memo(({
<Text <Text
style={[styles.usernameInfoMessage, { color: themes[theme].titleText }]} style={[styles.usernameInfoMessage, { color: themes[theme].titleText }]}
onPress={onUserPress} onPress={onUserPress}
// @ts-ignore
disabled={isDisabled} disabled={isDisabled}
> >
{textContent} {textContent}
@ -94,18 +109,6 @@ const User = React.memo(({
return null; return null;
}); });
User.propTypes = {
isHeader: PropTypes.bool,
hasError: PropTypes.bool,
useRealName: PropTypes.bool,
author: PropTypes.object,
alias: PropTypes.string,
ts: PropTypes.instanceOf(Date),
timeFormat: PropTypes.string,
theme: PropTypes.string,
navToRoomInfo: PropTypes.func,
type: PropTypes.string
};
User.displayName = 'MessageUser'; User.displayName = 'MessageUser';
export default withTheme(User); export default withTheme(User);

View File

@ -1,5 +1,4 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
import { dequal } from 'dequal'; import { dequal } from 'dequal';
@ -13,7 +12,7 @@ import { themes } from '../../constants/colors';
import MessageContext from './Context'; import MessageContext from './Context';
const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(isIOS ? [] : ['video/3gp', 'video/mkv'])]; const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(isIOS ? [] : ['video/3gp', 'video/mkv'])];
const isTypeSupported = type => SUPPORTED_TYPES.indexOf(type) !== -1; const isTypeSupported = (type: any) => SUPPORTED_TYPES.indexOf(type) !== -1;
const styles = StyleSheet.create({ const styles = StyleSheet.create({
button: { button: {
@ -26,9 +25,18 @@ const styles = StyleSheet.create({
} }
}); });
const Video = React.memo(({ interface IMessageVideo {
file, showAttachment, getCustomEmoji, theme file: {
}) => { video_type: string;
video_url: string;
description: string;
};
showAttachment: Function;
getCustomEmoji: Function;
theme: string;
}
const Video = React.memo(({ file, showAttachment, getCustomEmoji, theme }: IMessageVideo) => {
const { baseUrl, user } = useContext(MessageContext); const { baseUrl, user } = useContext(MessageContext);
if (!baseUrl) { if (!baseUrl) {
return null; return null;
@ -54,16 +62,10 @@ const Video = React.memo(({
color={themes[theme].buttonText} color={themes[theme].buttonText}
/> />
</Touchable> </Touchable>
{/*@ts-ignore*/}
<Markdown msg={file.description} baseUrl={baseUrl} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} /> <Markdown msg={file.description} baseUrl={baseUrl} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
</> </>
); );
}, (prevProps, nextProps) => dequal(prevProps.file, nextProps.file) && prevProps.theme === nextProps.theme); }, (prevProps, nextProps) => dequal(prevProps.file, nextProps.file) && prevProps.theme === nextProps.theme);
Video.propTypes = {
file: PropTypes.object,
showAttachment: PropTypes.func,
getCustomEmoji: PropTypes.func,
theme: PropTypes.string
};
export default Video; export default Video;