[IMPROVE] - migrating the message container (finished)

This commit is contained in:
AlexAlexandre 2021-07-22 22:59:16 -03:00
parent 6db54e9920
commit 024c744615
16 changed files with 200 additions and 194 deletions

View File

@ -3,7 +3,7 @@ import { ActivityIndicator, ActivityIndicatorProps, StyleSheet } from 'react-nat
import { themes } from '../constants/colors'; import { themes } from '../constants/colors';
interface IActivityIndicator extends ActivityIndicatorProps{ interface IActivityIndicator extends ActivityIndicatorProps{
theme?: 'light' | 'dark' | 'black', theme?: 'light' | 'dark' | 'black' | string,
absolute?: boolean, absolute?: boolean,
props?: object props?: object
} }

View File

@ -6,7 +6,7 @@ import Audio from './Audio';
import Video from './Video'; import Video from './Video';
import Reply from './Reply'; import Reply from './Reply';
interface IMessageAttachments { export interface IMessageAttachments {
attachments: any; attachments: any;
timeFormat: string; timeFormat: string;
showAttachment: Function; showAttachment: Function;

View File

@ -1,8 +1,5 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import { View, StyleSheet, Text, Easing } from 'react-native';
import {
View, StyleSheet, Text, Easing
} from 'react-native';
import { Audio } from 'expo-av'; import { Audio } from 'expo-av';
import Slider from '@react-native-community/slider'; import Slider from '@react-native-community/slider';
import moment from 'moment'; import moment from 'moment';
@ -19,6 +16,30 @@ import MessageContext from './Context';
import ActivityIndicator from '../ActivityIndicator'; import ActivityIndicator from '../ActivityIndicator';
import { withDimensions } from '../../dimensions'; import { withDimensions } from '../../dimensions';
type TButton = {
loading: boolean;
paused: boolean;
theme: string;
onPress: Function;
};
interface IMessageAudioProps {
file: {
audio_url: string;
description: string;
};
theme: string;
getCustomEmoji: Function;
scale: number;
}
interface IMessageAudioState {
loading: boolean,
currentTime: number,
duration: number,
paused: boolean
}
const mode = { const mode = {
allowsRecordingIOS: false, allowsRecordingIOS: false,
playsInSilentModeIOS: true, playsInSilentModeIOS: true,
@ -57,19 +78,17 @@ const styles = StyleSheet.create({
} }
}); });
const formatTime = seconds => moment.utc(seconds * 1000).format('mm:ss'); const formatTime = (seconds: number) => moment.utc(seconds * 1000).format('mm:ss');
const BUTTON_HIT_SLOP = {
top: 12, right: 12, bottom: 12, left: 12 const BUTTON_HIT_SLOP = { top: 12, right: 12, bottom: 12, left: 12 };
};
const sliderAnimationConfig = { const sliderAnimationConfig = {
duration: 250, duration: 250,
easing: Easing.linear, easing: Easing.linear,
delay: 0 delay: 0
}; };
const Button = React.memo(({ const Button = React.memo(({ loading, paused, onPress, theme }: TButton) => (
loading, paused, onPress, theme
}) => (
<Touchable <Touchable
style={styles.playPauseButton} style={styles.playPauseButton}
onPress={onPress} onPress={onPress}
@ -84,25 +103,13 @@ const Button = React.memo(({
</Touchable> </Touchable>
)); ));
Button.propTypes = {
loading: PropTypes.bool,
paused: PropTypes.bool,
theme: PropTypes.string,
onPress: PropTypes.func
};
Button.displayName = 'MessageAudioButton'; Button.displayName = 'MessageAudioButton';
class MessageAudio extends React.Component { class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioState> {
static contextType = MessageContext; static contextType = MessageContext;
private sound: any;
static propTypes = { constructor(props: IMessageAudioProps) {
file: PropTypes.object.isRequired,
theme: PropTypes.string,
getCustomEmoji: PropTypes.func,
scale: PropTypes.number
}
constructor(props) {
super(props); super(props);
this.state = { this.state = {
loading: false, loading: false,
@ -133,7 +140,7 @@ class MessageAudio extends React.Component {
this.setState({ loading: false }); this.setState({ loading: false });
} }
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps: any, nextState: any) {
const { const {
currentTime, duration, paused, loading currentTime, duration, paused, loading
} = this.state; } = this.state;
@ -176,7 +183,7 @@ class MessageAudio extends React.Component {
} }
} }
onPlaybackStatusUpdate = (status) => { onPlaybackStatusUpdate = (status: any) => {
if (status) { if (status) {
this.onLoad(status); this.onLoad(status);
this.onProgress(status); this.onProgress(status);
@ -184,12 +191,12 @@ class MessageAudio extends React.Component {
} }
} }
onLoad = (data) => { onLoad = (data: any) => {
const duration = data.durationMillis / 1000; const duration = data.durationMillis / 1000;
this.setState({ duration: duration > 0 ? duration : 0 }); this.setState({ duration: duration > 0 ? duration : 0 });
} }
onProgress = (data) => { onProgress = (data: any) => {
const { duration } = this.state; const { duration } = this.state;
const currentTime = data.positionMillis / 1000; const currentTime = data.positionMillis / 1000;
if (currentTime <= duration) { if (currentTime <= duration) {
@ -197,7 +204,7 @@ class MessageAudio extends React.Component {
} }
} }
onEnd = async(data) => { onEnd = async(data: any) => {
if (data.didJustFinish) { if (data.didJustFinish) {
try { try {
await this.sound.stopAsync(); await this.sound.stopAsync();
@ -232,7 +239,7 @@ class MessageAudio extends React.Component {
} }
} }
onValueChange = async(value) => { onValueChange = async(value: any) => {
try { try {
this.setState({ currentTime: value }); this.setState({ currentTime: value });
await this.sound.setPositionAsync(value * 1000); await this.sound.setPositionAsync(value * 1000);
@ -275,10 +282,12 @@ class MessageAudio extends React.Component {
minimumTrackTintColor={themes[theme].tintColor} minimumTrackTintColor={themes[theme].tintColor}
maximumTrackTintColor={themes[theme].auxiliaryText} maximumTrackTintColor={themes[theme].auxiliaryText}
onValueChange={this.onValueChange} onValueChange={this.onValueChange}
/*@ts-ignore*/
thumbImage={isIOS && { uri: 'audio_thumb', scale }} thumbImage={isIOS && { uri: 'audio_thumb', scale }}
/> />
<Text style={[styles.duration, { color: themes[theme].auxiliaryText }]}>{this.duration}</Text> <Text style={[styles.duration, { color: themes[theme].auxiliaryText }]}>{this.duration}</Text>
</View> </View>
{/*@ts-ignore*/}
<Markdown msg={description} baseUrl={baseUrl} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} /> <Markdown msg={description} baseUrl={baseUrl} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
</> </>
); );

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { messageBlockWithContext } from '../UIKit/MessageBlock'; import { messageBlockWithContext } from '../UIKit/MessageBlock';
interface IMessageBlocks { export interface IMessageBlocks {
blocks: any; blocks: any;
id: string; id: string;
rid: string; rid: string;

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 Touchable from './Touchable'; import Touchable from './Touchable';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
@ -10,9 +9,15 @@ import I18n from '../../i18n';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import MessageContext from './Context'; import MessageContext from './Context';
const Broadcast = React.memo(({ export interface IMessageBroadcast {
author, broadcast, theme author: {
}) => { _id: string
};
broadcast: boolean;
theme: string
}
const Broadcast = React.memo(({ author, broadcast, theme }: IMessageBroadcast) => {
const { user, replyBroadcast } = useContext(MessageContext); const { user, replyBroadcast } = useContext(MessageContext);
const isOwn = author._id === user.id; const isOwn = author._id === user.id;
if (broadcast && !isOwn) { if (broadcast && !isOwn) {
@ -36,11 +41,6 @@ const Broadcast = React.memo(({
return null; return null;
}); });
Broadcast.propTypes = {
author: PropTypes.object,
broadcast: PropTypes.bool,
theme: PropTypes.string
};
Broadcast.displayName = 'MessageBroadcast'; Broadcast.displayName = 'MessageBroadcast';
export default Broadcast; export default Broadcast;

View File

@ -8,7 +8,7 @@ import I18n from '../../i18n';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
interface IMessageCallButton { export interface IMessageCallButton {
theme: string; theme: string;
callJitsi: Function; callJitsi: Function;
} }

View File

@ -1,6 +1,5 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { Text, View } from 'react-native'; import { Text, View } from 'react-native';
import PropTypes from 'prop-types';
import { dequal } from 'dequal'; import { dequal } from 'dequal';
import I18n from '../../i18n'; import I18n from '../../i18n';
@ -12,9 +11,29 @@ import { themes } from '../../constants/colors';
import MessageContext from './Context'; import MessageContext from './Context';
import Encrypted from './Encrypted'; import Encrypted from './Encrypted';
import { E2E_MESSAGE_TYPE } from '../../lib/encryption/constants'; import { E2E_MESSAGE_TYPE } from '../../lib/encryption/constants';
import {TChannel} from "../markdown/Hashtag";
const Content = React.memo((props) => { export interface IMessageContent {
isTemp: boolean;
isInfo: boolean;
tmid: string;
isThreadRoom: boolean;
msg: string;
theme: string;
isEdited: boolean;
isEncrypted: boolean;
getCustomEmoji: Function;
channels: TChannel[];
mentions: object[];
navToRoomInfo: Function;
useRealName: boolean;
isIgnored: boolean;
type: string;
}
const Content = React.memo((props: IMessageContent) => {
if (props.isInfo) { if (props.isInfo) {
// @ts-ignore
const infoMessage = getInfoMessage({ ...props }); const infoMessage = getInfoMessage({ ...props });
const renderMessageContent = ( const renderMessageContent = (
@ -37,7 +56,7 @@ const Content = React.memo((props) => {
return renderMessageContent; return renderMessageContent;
} }
const isPreview = props.tmid && !props.isThreadRoom; const isPreview: any = props.tmid && !props.isThreadRoom;
let content = null; let content = null;
if (props.tmid && !props.msg) { if (props.tmid && !props.msg) {
@ -47,6 +66,7 @@ const Content = React.memo((props) => {
} else { } else {
const { baseUrl, user, onLinkPress } = useContext(MessageContext); const { baseUrl, user, onLinkPress } = useContext(MessageContext);
content = ( content = (
// @ts-ignore
<Markdown <Markdown
msg={props.msg} msg={props.msg}
baseUrl={baseUrl} baseUrl={baseUrl}
@ -118,23 +138,6 @@ const Content = React.memo((props) => {
return true; return true;
}); });
Content.propTypes = {
isTemp: PropTypes.bool,
isInfo: PropTypes.bool,
tmid: PropTypes.string,
isThreadRoom: PropTypes.bool,
msg: PropTypes.string,
theme: PropTypes.string,
isEdited: PropTypes.bool,
isEncrypted: PropTypes.bool,
getCustomEmoji: PropTypes.func,
channels: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
navToRoomInfo: PropTypes.func,
useRealName: PropTypes.bool,
isIgnored: PropTypes.bool,
type: PropTypes.string
};
Content.displayName = 'MessageContent'; Content.displayName = 'MessageContent';
export default Content; export default Content;

View File

@ -1,4 +0,0 @@
import React from 'react';
const MessageContext = React.createContext();
export default MessageContext;

View File

@ -0,0 +1,5 @@
import React from 'react';
// @ts-ignore
const MessageContext = React.createContext<any>();
export default MessageContext;

View File

@ -11,7 +11,7 @@ import { themes } from '../../constants/colors';
import MessageContext from './Context'; import MessageContext from './Context';
import { formatDateThreads } from '../../utils/room'; import { formatDateThreads } from '../../utils/room';
interface IMessageDiscussion { export interface IMessageDiscussion {
msg: string; msg: string;
dcount: number; dcount: number;
dlm: string; dlm: string;

View File

@ -1,5 +1,4 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native'; import { View } from 'react-native';
import Touchable from 'react-native-platform-touchable'; import Touchable from 'react-native-platform-touchable';
@ -7,21 +6,59 @@ import MessageContext from './Context';
import User from './User'; import User from './User';
import styles from './styles'; import styles from './styles';
import RepliedThread from './RepliedThread'; import RepliedThread, {IMessageRepliedThread} from './RepliedThread';
import MessageAvatar from './MessageAvatar'; import MessageAvatar, {IMessageAvatar} from './MessageAvatar';
import Attachments from './Attachments'; import Attachments, {IMessageAttachments} from './Attachments';
import Urls from './Urls'; import Urls from './Urls';
import Thread from './Thread'; import Thread, {IMessageThread} from './Thread';
import Blocks from './Blocks'; import Blocks, {IMessageBlocks} from './Blocks';
import Reactions from './Reactions'; import Reactions from './Reactions';
import Broadcast from './Broadcast'; import Broadcast, {IMessageBroadcast} from './Broadcast';
import Discussion from './Discussion'; import Discussion, {IMessageDiscussion} from './Discussion';
import Content from './Content'; import Content, {IMessageContent} from './Content';
import ReadReceipt from './ReadReceipt'; import ReadReceipt from './ReadReceipt';
import CallButton from './CallButton'; import CallButton, {IMessageCallButton} from './CallButton';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
const MessageInner = React.memo((props) => {
type TMessageInner = {
type: string;
blocks: [];
} & IMessageDiscussion & IMessageContent & IMessageCallButton & IMessageBlocks
& IMessageThread & IMessageAttachments & IMessageBroadcast;
type TMessage = {
isThreadReply: boolean;
isThreadSequential: boolean;
isInfo: boolean;
isTemp: boolean;
isHeader: boolean;
hasError: boolean;
style: any;
onLongPress: Function;
isReadReceiptEnabled: boolean;
unread: boolean;
theme: string;
isIgnored: boolean;
} & IMessageRepliedThread & IMessageAvatar & IMessageContent & TMessageInner;
interface IMessageTouchable {
hasError: boolean;
isInfo: boolean;
isThreadReply: boolean;
isTemp: boolean;
archived: boolean;
highlighted: boolean;
theme: string;
ts?: any
urls?: any;
reactions?: any;
alias?: any;
role?: any;
drid?: any;
}
const MessageInner = React.memo((props: TMessageInner) => {
if (props.type === 'discussion-created') { if (props.type === 'discussion-created') {
return ( return (
<> <>
@ -63,7 +100,7 @@ const MessageInner = React.memo((props) => {
}); });
MessageInner.displayName = 'MessageInner'; MessageInner.displayName = 'MessageInner';
const Message = React.memo((props) => { const Message = React.memo((props: TMessage) => {
if (props.isThreadReply || props.isThreadSequential || props.isInfo || props.isIgnored) { if (props.isThreadReply || props.isThreadSequential || props.isInfo || props.isIgnored) {
const thread = props.isThreadReply ? <RepliedThread {...props} /> : null; const thread = props.isThreadReply ? <RepliedThread {...props} /> : null;
return ( return (
@ -107,7 +144,7 @@ const Message = React.memo((props) => {
}); });
Message.displayName = 'Message'; Message.displayName = 'Message';
const MessageTouchable = React.memo((props) => { const MessageTouchable = React.memo((props: IMessageTouchable & TMessage) => {
if (props.hasError) { if (props.hasError) {
return ( return (
<View> <View>
@ -129,36 +166,7 @@ const MessageTouchable = React.memo((props) => {
</Touchable> </Touchable>
); );
}); });
MessageTouchable.displayName = 'MessageTouchable'; MessageTouchable.displayName = 'MessageTouchable';
MessageTouchable.propTypes = {
hasError: PropTypes.bool,
isInfo: PropTypes.bool,
isThreadReply: PropTypes.bool,
isTemp: PropTypes.bool,
archived: PropTypes.bool,
highlighted: PropTypes.bool,
theme: PropTypes.string
};
Message.propTypes = {
isThreadReply: PropTypes.bool,
isThreadSequential: PropTypes.bool,
isInfo: PropTypes.bool,
isTemp: PropTypes.bool,
isHeader: PropTypes.bool,
hasError: PropTypes.bool,
style: PropTypes.any,
onLongPress: PropTypes.func,
isReadReceiptEnabled: PropTypes.bool,
unread: PropTypes.bool,
theme: PropTypes.string,
isIgnored: PropTypes.bool
};
MessageInner.propTypes = {
type: PropTypes.string,
blocks: PropTypes.array
};
export default MessageTouchable; export default MessageTouchable;

View File

@ -4,7 +4,7 @@ import Avatar from '../Avatar';
import styles from './styles'; import styles from './styles';
import MessageContext from './Context'; import MessageContext from './Context';
interface IMessageAvatar { export interface IMessageAvatar {
isHeader: boolean; isHeader: boolean;
avatar: string; avatar: string;
emoji: string; emoji: string;
@ -12,7 +12,7 @@ interface IMessageAvatar {
username: string username: string
_id: string; _id: string;
}; };
small: boolean; small?: boolean;
navToRoomInfo: Function; navToRoomInfo: Function;
getCustomEmoji(): void; getCustomEmoji(): void;
theme: string; theme: string;

View File

@ -7,7 +7,7 @@ import { themes } from '../../constants/colors';
import I18n from '../../i18n'; import I18n from '../../i18n';
import Markdown from '../markdown'; import Markdown from '../markdown';
interface IMessageRepliedThread { export interface IMessageRepliedThread {
tmid: string; tmid: string;
tmsg: string; tmsg: string;
id: string; id: string;

View File

@ -7,7 +7,7 @@ import MessageContext from './Context';
import ThreadDetails from '../ThreadDetails'; import ThreadDetails from '../ThreadDetails';
import I18n from '../../i18n'; import I18n from '../../i18n';
interface IMessageThread { export interface IMessageThread {
msg: string; msg: string;
tcount: number; tcount: number;
theme: string; theme: string;

View File

@ -11,75 +11,62 @@ import messagesStatus from '../../constants/messagesStatus';
import { withTheme } from '../../theme'; import { withTheme } from '../../theme';
import openLink from '../../utils/openLink'; import openLink from '../../utils/openLink';
class MessageContainer extends React.Component { interface IMessageContainerProps {
static propTypes = { item: any;
item: PropTypes.object.isRequired, user: {
user: PropTypes.shape({ id: string;
id: PropTypes.string.isRequired, username: string;
username: PropTypes.string.isRequired, token: string;
token: PropTypes.string.isRequired };
}), rid: string;
rid: PropTypes.string, timeFormat: string;
timeFormat: PropTypes.string, style: any;
style: PropTypes.any, archived: boolean;
archived: PropTypes.bool, broadcast: boolean;
broadcast: PropTypes.bool, previousItem: {
previousItem: PropTypes.object, ts: any;
baseUrl: PropTypes.string, u: any;
Message_GroupingPeriod: PropTypes.number, groupable: any;
isReadReceiptEnabled: PropTypes.bool, id: any;
isThreadRoom: PropTypes.bool, tmid: any;
useRealName: PropTypes.bool, status: any
autoTranslateRoom: PropTypes.bool, };
autoTranslateLanguage: PropTypes.string, baseUrl: string;
status: PropTypes.number, Message_GroupingPeriod: number;
isIgnored: PropTypes.bool, isReadReceiptEnabled: boolean;
highlighted: PropTypes.bool, isThreadRoom: boolean;
getCustomEmoji: PropTypes.func, useRealName: boolean;
onLongPress: PropTypes.func, autoTranslateRoom: boolean;
onReactionPress: PropTypes.func, autoTranslateLanguage: string;
onEncryptedPress: PropTypes.func, status: number;
onDiscussionPress: PropTypes.func, isIgnored: boolean;
onThreadPress: PropTypes.func, highlighted: boolean;
errorActionsShow: PropTypes.func, getCustomEmoji(): void;
replyBroadcast: PropTypes.func, onLongPress: Function;
reactionInit: PropTypes.func, onReactionPress: Function;
fetchThreadName: PropTypes.func, onEncryptedPress: Function;
showAttachment: PropTypes.func, onDiscussionPress: Function;
onReactionLongPress: PropTypes.func, onThreadPress: Function;
navToRoomInfo: PropTypes.func, errorActionsShow: Function;
callJitsi: PropTypes.func, replyBroadcast: Function;
blockAction: PropTypes.func, reactionInit: Function;
theme: PropTypes.string, fetchThreadName: Function;
threadBadgeColor: PropTypes.string, showAttachment: Function;
toggleFollowThread: PropTypes.func, onReactionLongPress: Function;
jumpToMessage: PropTypes.func, navToRoomInfo: Function;
onPress: PropTypes.func callJitsi: Function;
blockAction: Function;
theme: string;
threadBadgeColor: string;
toggleFollowThread: Function;
jumpToMessage: Function;
onPress: Function;
} }
static defaultProps = { class MessageContainer extends React.Component<IMessageContainerProps, any> {
getCustomEmoji: () => {},
onLongPress: () => {},
onReactionPress: () => {},
onEncryptedPress: () => {},
onDiscussionPress: () => {},
onThreadPress: () => {},
errorActionsShow: () => {},
replyBroadcast: () => {},
reactionInit: () => {},
fetchThreadName: () => {},
showAttachment: () => {},
onReactionLongPress: () => {},
navToRoomInfo: () => {},
callJitsi: () => {},
blockAction: () => {},
archived: false,
broadcast: false,
isIgnored: false,
theme: 'light'
}
state = { isManualUnignored: false }; state = { isManualUnignored: false };
private subscription: any;
componentDidMount() { componentDidMount() {
const { item } = this.props; const { item } = this.props;
@ -91,7 +78,7 @@ class MessageContainer extends React.Component {
} }
} }
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps: any, nextState: any) {
const { isManualUnignored } = this.state; const { isManualUnignored } = this.state;
const { const {
theme, threadBadgeColor, isIgnored, highlighted theme, threadBadgeColor, isIgnored, highlighted
@ -155,7 +142,7 @@ class MessageContainer extends React.Component {
} }
} }
onReactionPress = (emoji) => { onReactionPress = (emoji: any) => {
const { onReactionPress, item } = this.props; const { onReactionPress, item } = this.props;
if (onReactionPress) { if (onReactionPress) {
onReactionPress(emoji, item.id); onReactionPress(emoji, item.id);
@ -195,9 +182,7 @@ class MessageContainer extends React.Component {
} }
get isHeader() { get isHeader() {
const { const { item, previousItem, broadcast, Message_GroupingPeriod } = this.props;
item, previousItem, broadcast, Message_GroupingPeriod
} = this.props;
if (this.hasError || (previousItem && previousItem.status === messagesStatus.ERROR)) { if (this.hasError || (previousItem && previousItem.status === messagesStatus.ERROR)) {
return true; return true;
} }
@ -218,9 +203,7 @@ class MessageContainer extends React.Component {
} }
get isThreadReply() { get isThreadReply() {
const { const { item, previousItem, isThreadRoom } = this.props;
item, previousItem, isThreadRoom
} = this.props;
if (isThreadRoom) { if (isThreadRoom) {
return false; return false;
} }
@ -279,9 +262,9 @@ class MessageContainer extends React.Component {
} }
} }
onLinkPress = (link) => { onLinkPress = (link: any) => {
const { item, theme, jumpToMessage } = this.props; const { item, theme, jumpToMessage } = this.props;
const isMessageLink = item?.attachments?.findIndex(att => att?.message_link === link) !== -1; const isMessageLink = item?.attachments?.findIndex((att: any) => att?.message_link === link) !== -1;
if (isMessageLink) { if (isMessageLink) {
return jumpToMessage(link); return jumpToMessage(link);
} }
@ -372,6 +355,7 @@ class MessageContainer extends React.Component {
replies replies
}} }}
> >
{/*@ts-ignore*/}
<Message <Message
id={id} id={id}
msg={message} msg={message}

View File

@ -2,4 +2,5 @@ declare module 'rn-extensions-share';
declare module 'commonmark'; declare module 'commonmark';
declare module 'commonmark-react-renderer'; declare module 'commonmark-react-renderer';
declare module 'remove-markdown'; declare module 'remove-markdown';
declare module 'react-native-image-progress' declare module 'react-native-image-progress';
declare module 'react-native-platform-touchable';