Chore: Evaluate Message - TypeScript (#3944)
Co-authored-by: GleidsonDaniel <gleidson10daniel@hotmail.com>
This commit is contained in:
parent
6ad4ccd4bd
commit
488074b4ae
|
@ -1,8 +1,7 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { MESSAGES } from './actionsTypes';
|
||||
|
||||
type IMessage = Record<string, string>;
|
||||
import { IMessage } from '../definitions';
|
||||
|
||||
interface IReplyBroadcast extends Action {
|
||||
message: IMessage;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export interface IUserMention {
|
||||
_id: string;
|
||||
username: string;
|
||||
username?: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import React, { useContext } from 'react';
|
|||
import { dequal } from 'dequal';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
import { IMessageAttachments, IMessageAttachedActions } from './interfaces';
|
||||
import { IMessageAttachments } from './interfaces';
|
||||
import Image from './Image';
|
||||
import Audio from './Audio';
|
||||
import Video from './Video';
|
||||
|
@ -23,7 +23,7 @@ export type TElement = {
|
|||
text: string;
|
||||
};
|
||||
|
||||
const AttachedActions = ({ attachment }: IMessageAttachedActions) => {
|
||||
const AttachedActions = ({ attachment }: { attachment: IAttachment }) => {
|
||||
if (!attachment.actions) {
|
||||
return null;
|
||||
}
|
||||
|
@ -55,8 +55,7 @@ const AttachedActions = ({ attachment }: IMessageAttachedActions) => {
|
|||
);
|
||||
};
|
||||
|
||||
const Attachments = React.memo(
|
||||
// @ts-ignore
|
||||
const Attachments: React.FC<IMessageAttachments> = React.memo(
|
||||
({ attachments, timeFormat, showAttachment, style, getCustomEmoji, isReply }: IMessageAttachments) => {
|
||||
if (!attachments || attachments.length === 0) {
|
||||
return null;
|
||||
|
@ -64,7 +63,7 @@ const Attachments = React.memo(
|
|||
|
||||
const { theme } = useTheme();
|
||||
|
||||
return attachments.map((file: IAttachment, index: number) => {
|
||||
const attachmentsElements = attachments.map((file: IAttachment, index: number) => {
|
||||
if (file && file.image_url) {
|
||||
return (
|
||||
<Image
|
||||
|
@ -93,7 +92,6 @@ const Attachments = React.memo(
|
|||
getCustomEmoji={getCustomEmoji}
|
||||
style={style}
|
||||
isReply={isReply}
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -109,6 +107,7 @@ const Attachments = React.memo(
|
|||
|
||||
return <Reply key={index} index={index} attachment={file} timeFormat={timeFormat} getCustomEmoji={getCustomEmoji} />;
|
||||
});
|
||||
return <>{attachmentsElements}</>;
|
||||
},
|
||||
(prevProps, nextProps) => dequal(prevProps.attachments, nextProps.attachments)
|
||||
);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import React from 'react';
|
||||
import { StyleProp, StyleSheet, Text, TextStyle, View } from 'react-native';
|
||||
import { Audio } from 'expo-av';
|
||||
import { Audio, AVPlaybackStatus } from 'expo-av';
|
||||
import Slider from '@react-native-community/slider';
|
||||
import moment from 'moment';
|
||||
import { dequal } from 'dequal';
|
||||
import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
|
||||
import { Sound } from 'expo-av/build/Audio/Sound';
|
||||
|
||||
import Touchable from './Touchable';
|
||||
import Markdown from '../markdown';
|
||||
|
@ -23,7 +24,7 @@ interface IButton {
|
|||
paused: boolean;
|
||||
theme: string;
|
||||
disabled?: boolean;
|
||||
onPress: Function;
|
||||
onPress: () => void;
|
||||
}
|
||||
|
||||
interface IMessageAudioProps {
|
||||
|
@ -108,7 +109,7 @@ Button.displayName = 'MessageAudioButton';
|
|||
class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioState> {
|
||||
static contextType = MessageContext;
|
||||
|
||||
private sound: any;
|
||||
private sound: Sound;
|
||||
|
||||
constructor(props: IMessageAudioProps) {
|
||||
super(props);
|
||||
|
@ -141,7 +142,7 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
|||
this.setState({ loading: false });
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps: any, nextState: any) {
|
||||
shouldComponentUpdate(nextProps: IMessageAudioProps, nextState: IMessageAudioState) {
|
||||
const { currentTime, duration, paused, loading } = this.state;
|
||||
const { file, theme } = this.props;
|
||||
if (nextProps.theme !== theme) {
|
||||
|
@ -182,7 +183,7 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
|||
}
|
||||
}
|
||||
|
||||
onPlaybackStatusUpdate = (status: any) => {
|
||||
onPlaybackStatusUpdate = (status: AVPlaybackStatus) => {
|
||||
if (status) {
|
||||
this.onLoad(status);
|
||||
this.onProgress(status);
|
||||
|
@ -190,26 +191,32 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
|||
}
|
||||
};
|
||||
|
||||
onLoad = (data: any) => {
|
||||
const duration = data.durationMillis / 1000;
|
||||
this.setState({ duration: duration > 0 ? duration : 0 });
|
||||
};
|
||||
|
||||
onProgress = (data: any) => {
|
||||
const { duration } = this.state;
|
||||
const currentTime = data.positionMillis / 1000;
|
||||
if (currentTime <= duration) {
|
||||
this.setState({ currentTime });
|
||||
onLoad = (data: AVPlaybackStatus) => {
|
||||
if (data.isLoaded && data.durationMillis) {
|
||||
const duration = data.durationMillis / 1000;
|
||||
this.setState({ duration: duration > 0 ? duration : 0 });
|
||||
}
|
||||
};
|
||||
|
||||
onEnd = async (data: any) => {
|
||||
if (data.didJustFinish) {
|
||||
try {
|
||||
await this.sound.stopAsync();
|
||||
this.setState({ paused: true, currentTime: 0 });
|
||||
} catch {
|
||||
// do nothing
|
||||
onProgress = (data: AVPlaybackStatus) => {
|
||||
if (data.isLoaded) {
|
||||
const { duration } = this.state;
|
||||
const currentTime = data.positionMillis / 1000;
|
||||
if (currentTime <= duration) {
|
||||
this.setState({ currentTime });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onEnd = async (data: AVPlaybackStatus) => {
|
||||
if (data.isLoaded) {
|
||||
if (data.didJustFinish) {
|
||||
try {
|
||||
await this.sound.stopAsync();
|
||||
this.setState({ paused: true, currentTime: 0 });
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -238,7 +245,7 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
|||
}
|
||||
};
|
||||
|
||||
onValueChange = async (value: any) => {
|
||||
onValueChange = async (value: number) => {
|
||||
try {
|
||||
this.setState({ currentTime: value });
|
||||
await this.sound.setPositionAsync(value * 1000);
|
||||
|
|
|
@ -8,15 +8,17 @@ const Blocks = React.memo(({ blocks, id: mid, rid, blockAction }: IMessageBlocks
|
|||
const appId = blocks[0]?.appId || '';
|
||||
return React.createElement(
|
||||
messageBlockWithContext({
|
||||
action: async ({ actionId, value, blockId }: any) => {
|
||||
await blockAction({
|
||||
actionId,
|
||||
appId,
|
||||
value,
|
||||
blockId,
|
||||
rid,
|
||||
mid
|
||||
});
|
||||
action: async ({ actionId, value, blockId }: { actionId: string; value: string; blockId: string }) => {
|
||||
if (blockAction) {
|
||||
await blockAction({
|
||||
actionId,
|
||||
appId,
|
||||
value,
|
||||
blockId,
|
||||
rid,
|
||||
mid
|
||||
});
|
||||
}
|
||||
},
|
||||
appId,
|
||||
rid
|
||||
|
|
|
@ -9,10 +9,13 @@ import I18n from '../../i18n';
|
|||
import { themes } from '../../constants/colors';
|
||||
import MessageContext from './Context';
|
||||
import { IMessageBroadcast } from './interfaces';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
const Broadcast = React.memo(({ author, broadcast, theme }: IMessageBroadcast) => {
|
||||
const Broadcast = React.memo(({ author, broadcast }: IMessageBroadcast) => {
|
||||
const { user, replyBroadcast } = useContext(MessageContext);
|
||||
const isOwn = author._id === user.id;
|
||||
const { theme } = useTheme();
|
||||
const isOwn = author?._id === user.id;
|
||||
|
||||
if (broadcast && !isOwn) {
|
||||
return (
|
||||
<View style={styles.buttonContainer}>
|
||||
|
|
|
@ -8,21 +8,25 @@ import I18n from '../../i18n';
|
|||
import { CustomIcon } from '../../lib/Icons';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { IMessageCallButton } from './interfaces';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
const CallButton = React.memo(({ theme, callJitsi }: IMessageCallButton) => (
|
||||
<View style={styles.buttonContainer}>
|
||||
<Touchable
|
||||
onPress={callJitsi}
|
||||
background={Touchable.Ripple(themes[theme].bannerBackground)}
|
||||
style={[styles.button, { backgroundColor: themes[theme].tintColor }]}
|
||||
hitSlop={BUTTON_HIT_SLOP}>
|
||||
<>
|
||||
<CustomIcon name='camera' size={16} style={styles.buttonIcon} color={themes[theme].buttonText} />
|
||||
<Text style={[styles.buttonText, { color: themes[theme].buttonText }]}>{I18n.t('Click_to_join')}</Text>
|
||||
</>
|
||||
</Touchable>
|
||||
</View>
|
||||
));
|
||||
const CallButton = React.memo(({ callJitsi }: IMessageCallButton) => {
|
||||
const { theme } = useTheme();
|
||||
return (
|
||||
<View style={styles.buttonContainer}>
|
||||
<Touchable
|
||||
onPress={callJitsi}
|
||||
background={Touchable.Ripple(themes[theme].bannerBackground)}
|
||||
style={[styles.button, { backgroundColor: themes[theme].tintColor }]}
|
||||
hitSlop={BUTTON_HIT_SLOP}>
|
||||
<>
|
||||
<CustomIcon name='camera' size={16} style={styles.buttonIcon} color={themes[theme].buttonText} />
|
||||
<Text style={[styles.buttonText, { color: themes[theme].buttonText }]}>{I18n.t('Click_to_join')}</Text>
|
||||
</>
|
||||
</Touchable>
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
CallButton.displayName = 'CallButton';
|
||||
|
||||
|
|
|
@ -12,15 +12,17 @@ import MessageContext from './Context';
|
|||
import Encrypted from './Encrypted';
|
||||
import { E2E_MESSAGE_TYPE } from '../../lib/encryption/constants';
|
||||
import { IMessageContent } from './interfaces';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
const Content = React.memo(
|
||||
(props: IMessageContent) => {
|
||||
const { theme } = useTheme();
|
||||
if (props.isInfo) {
|
||||
// @ts-ignore
|
||||
const infoMessage = getInfoMessage({ ...props });
|
||||
|
||||
const renderMessageContent = (
|
||||
<Text style={[styles.textInfo, { color: themes[props.theme].auxiliaryText }]} accessibilityLabel={infoMessage}>
|
||||
<Text style={[styles.textInfo, { color: themes[theme].auxiliaryText }]} accessibilityLabel={infoMessage}>
|
||||
{infoMessage}
|
||||
</Text>
|
||||
);
|
||||
|
@ -36,14 +38,12 @@ const Content = React.memo(
|
|||
return renderMessageContent;
|
||||
}
|
||||
|
||||
const isPreview: any = props.tmid && !props.isThreadRoom;
|
||||
const isPreview = props.tmid && !props.isThreadRoom;
|
||||
let content = null;
|
||||
|
||||
if (props.isEncrypted) {
|
||||
content = (
|
||||
<Text
|
||||
style={[styles.textInfo, { color: themes[props.theme].auxiliaryText }]}
|
||||
accessibilityLabel={I18n.t('Encrypted_message')}>
|
||||
<Text style={[styles.textInfo, { color: themes[theme].auxiliaryText }]} accessibilityLabel={I18n.t('Encrypted_message')}>
|
||||
{I18n.t('Encrypted_message')}
|
||||
</Text>
|
||||
);
|
||||
|
@ -65,7 +65,7 @@ const Content = React.memo(
|
|||
navToRoomInfo={props.navToRoomInfo}
|
||||
tmid={props.tmid}
|
||||
useRealName={props.useRealName}
|
||||
theme={props.theme}
|
||||
theme={theme}
|
||||
onLinkPress={onLinkPress}
|
||||
/>
|
||||
);
|
||||
|
@ -76,13 +76,13 @@ const Content = React.memo(
|
|||
content = (
|
||||
<View style={styles.flex}>
|
||||
<View style={styles.contentContainer}>{content}</View>
|
||||
<Encrypted type={props.type} theme={props.theme} />
|
||||
<Encrypted type={props.type} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
if (props.isIgnored) {
|
||||
content = <Text style={[styles.textInfo, { color: themes[props.theme].auxiliaryText }]}>{I18n.t('Message_Ignored')}</Text>;
|
||||
content = <Text style={[styles.textInfo, { color: themes[theme].auxiliaryText }]}>{I18n.t('Message_Ignored')}</Text>;
|
||||
}
|
||||
|
||||
return <View style={props.isTemp && styles.temp}>{content}</View>;
|
||||
|
@ -97,9 +97,6 @@ const Content = React.memo(
|
|||
if (prevProps.type !== nextProps.type) {
|
||||
return false;
|
||||
}
|
||||
if (prevProps.theme !== nextProps.theme) {
|
||||
return false;
|
||||
}
|
||||
if (prevProps.isEncrypted !== nextProps.isEncrypted) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -10,10 +10,12 @@ import { DISCUSSION } from './constants';
|
|||
import { themes } from '../../constants/colors';
|
||||
import MessageContext from './Context';
|
||||
import { formatDateThreads } from '../../utils/room';
|
||||
import { IMessageDiscussion } from './interfaces';
|
||||
import { IMessage } from '../../definitions';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
const Discussion = React.memo(
|
||||
({ msg, dcount, dlm, theme }: IMessageDiscussion) => {
|
||||
({ msg, dcount, dlm }: Pick<IMessage, 'msg' | 'dcount' | 'dlm'>) => {
|
||||
const { theme } = useTheme();
|
||||
let time;
|
||||
if (dlm) {
|
||||
time = formatDateThreads(dlm);
|
||||
|
@ -50,9 +52,6 @@ const Discussion = React.memo(
|
|||
if (prevProps.dlm !== nextProps.dlm) {
|
||||
return false;
|
||||
}
|
||||
if (prevProps.theme !== nextProps.theme) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
|
|
@ -7,13 +7,10 @@ import { themes } from '../../constants/colors';
|
|||
import { BUTTON_HIT_SLOP } from './utils';
|
||||
import MessageContext from './Context';
|
||||
import styles from './styles';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
interface IMessageEncrypted {
|
||||
type: string;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const Encrypted = React.memo(({ type, theme }: IMessageEncrypted) => {
|
||||
const Encrypted = React.memo(({ type }: { type: string }) => {
|
||||
const { theme } = useTheme();
|
||||
if (type !== E2E_MESSAGE_TYPE) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -12,25 +12,20 @@ import { formatAttachmentUrl } from '../../lib/utils';
|
|||
import { themes } from '../../constants/colors';
|
||||
import MessageContext from './Context';
|
||||
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
||||
import { useTheme } from '../../theme';
|
||||
import { IAttachment } from '../../definitions';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
type TMessageButton = {
|
||||
children: JSX.Element;
|
||||
interface IMessageButton {
|
||||
children: React.ReactElement;
|
||||
disabled?: boolean;
|
||||
onPress: Function;
|
||||
onPress: () => void;
|
||||
theme: string;
|
||||
};
|
||||
|
||||
type TMessageImage = {
|
||||
img: string;
|
||||
theme: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IMessageImage {
|
||||
file: IAttachment;
|
||||
imageUrl?: string;
|
||||
showAttachment?: Function;
|
||||
showAttachment?: (file: IAttachment) => void;
|
||||
style?: StyleProp<TextStyle>[];
|
||||
isReply?: boolean;
|
||||
getCustomEmoji?: TGetCustomEmoji;
|
||||
|
@ -38,7 +33,7 @@ interface IMessageImage {
|
|||
|
||||
const ImageProgress = createImageProgress(FastImage);
|
||||
|
||||
const Button = React.memo(({ children, onPress, disabled, theme }: TMessageButton) => (
|
||||
const Button = React.memo(({ children, onPress, disabled, theme }: IMessageButton) => (
|
||||
<Touchable
|
||||
disabled={disabled}
|
||||
onPress={onPress}
|
||||
|
@ -48,10 +43,10 @@ const Button = React.memo(({ children, onPress, disabled, theme }: TMessageButto
|
|||
</Touchable>
|
||||
));
|
||||
|
||||
export const MessageImage = React.memo(({ img, theme }: TMessageImage) => (
|
||||
export const MessageImage = React.memo(({ imgUri, theme }: { imgUri: string; theme: string }) => (
|
||||
<ImageProgress
|
||||
style={[styles.image, { borderColor: themes[theme].borderColor }]}
|
||||
source={{ uri: encodeURI(img) }}
|
||||
source={{ uri: encodeURI(imgUri) }}
|
||||
resizeMode={FastImage.resizeMode.cover}
|
||||
indicator={Progress.Pie}
|
||||
indicatorProps={{
|
||||
|
@ -65,6 +60,7 @@ const ImageContainer = React.memo(
|
|||
const { theme } = useTheme();
|
||||
const { baseUrl, user } = useContext(MessageContext);
|
||||
const img = imageUrl || formatAttachmentUrl(file.image_url, user.id, user.token, baseUrl);
|
||||
|
||||
if (!img) {
|
||||
return null;
|
||||
}
|
||||
|
@ -89,7 +85,7 @@ const ImageContainer = React.memo(
|
|||
getCustomEmoji={getCustomEmoji}
|
||||
theme={theme}
|
||||
/>
|
||||
<MessageImage img={img} theme={theme} />
|
||||
<MessageImage imgUri={img} theme={theme} />
|
||||
</View>
|
||||
</Button>
|
||||
);
|
||||
|
@ -97,7 +93,7 @@ const ImageContainer = React.memo(
|
|||
|
||||
return (
|
||||
<Button disabled={isReply} theme={theme} onPress={onPress}>
|
||||
<MessageImage img={img} theme={theme} />
|
||||
<MessageImage imgUri={img} theme={theme} />
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -19,6 +19,7 @@ import ReadReceipt from './ReadReceipt';
|
|||
import CallButton from './CallButton';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { IMessage, IMessageInner, IMessageTouchable } from './interfaces';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
const MessageInner = React.memo((props: IMessageInner) => {
|
||||
const { attachments } = props;
|
||||
|
@ -85,7 +86,6 @@ const Message = React.memo((props: IMessage) => {
|
|||
<View style={[styles.container, props.style]}>
|
||||
{thread}
|
||||
<View style={styles.flex}>
|
||||
{/* @ts-ignore */}
|
||||
<MessageAvatar small {...props} />
|
||||
<View style={[styles.messageContent, props.isHeader && styles.messageContentWithHeader]}>
|
||||
<Content {...props} />
|
||||
|
@ -98,12 +98,11 @@ const Message = React.memo((props: IMessage) => {
|
|||
return (
|
||||
<View style={[styles.container, props.style]}>
|
||||
<View style={styles.flex}>
|
||||
{/* @ts-ignore */}
|
||||
<MessageAvatar {...props} />
|
||||
<View style={[styles.messageContent, props.isHeader && styles.messageContentWithHeader]}>
|
||||
<MessageInner {...props} />
|
||||
</View>
|
||||
<ReadReceipt isReadReceiptEnabled={props.isReadReceiptEnabled} unread={props.unread || false} theme={props.theme} />
|
||||
<ReadReceipt isReadReceiptEnabled={props.isReadReceiptEnabled} unread={props.unread || false} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
@ -119,12 +118,14 @@ const MessageTouchable = React.memo((props: IMessageTouchable & IMessage) => {
|
|||
);
|
||||
}
|
||||
const { onPress, onLongPress } = useContext(MessageContext);
|
||||
const { theme } = useTheme();
|
||||
|
||||
return (
|
||||
<Touchable
|
||||
onLongPress={onLongPress}
|
||||
onPress={onPress}
|
||||
disabled={(props.isInfo && !props.isThreadReply) || props.archived || props.isTemp || props.type === 'jitsi_call_started'}
|
||||
style={{ backgroundColor: props.highlighted ? themes[props.theme].headerBackground : null }}>
|
||||
style={{ backgroundColor: props.highlighted ? themes[theme].headerBackground : null }}>
|
||||
<View>
|
||||
<Message {...props} />
|
||||
</View>
|
||||
|
|
|
@ -6,14 +6,12 @@ import styles from './styles';
|
|||
import { BUTTON_HIT_SLOP } from './utils';
|
||||
import { themes } from '../../constants/colors';
|
||||
import MessageContext from './Context';
|
||||
|
||||
interface IMessageError {
|
||||
hasError: boolean;
|
||||
theme: string;
|
||||
}
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
const MessageError = React.memo(
|
||||
({ hasError, theme }: IMessageError) => {
|
||||
({ hasError }: { hasError: boolean }) => {
|
||||
const { theme } = useTheme();
|
||||
|
||||
if (!hasError) {
|
||||
return null;
|
||||
}
|
||||
|
@ -24,7 +22,7 @@ const MessageError = React.memo(
|
|||
</Touchable>
|
||||
);
|
||||
},
|
||||
(prevProps, nextProps) => prevProps.hasError === nextProps.hasError && prevProps.theme === nextProps.theme
|
||||
(prevProps, nextProps) => prevProps.hasError === nextProps.hasError
|
||||
);
|
||||
|
||||
MessageError.displayName = 'MessageError';
|
||||
|
|
|
@ -7,30 +7,28 @@ import styles from './styles';
|
|||
import Emoji from './Emoji';
|
||||
import { BUTTON_HIT_SLOP } from './utils';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
import { useTheme } from '../../theme';
|
||||
import MessageContext from './Context';
|
||||
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
||||
|
||||
interface IMessageAddReaction {
|
||||
theme: string;
|
||||
interface IReaction {
|
||||
_id: string;
|
||||
emoji: string;
|
||||
usernames: string[];
|
||||
}
|
||||
|
||||
interface IMessageReaction {
|
||||
reaction: {
|
||||
usernames: [];
|
||||
emoji: object;
|
||||
};
|
||||
reaction: IReaction;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
interface IMessageReactions {
|
||||
reactions?: object[];
|
||||
reactions?: IReaction[];
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const AddReaction = React.memo(({ theme }: IMessageAddReaction) => {
|
||||
const AddReaction = React.memo(({ theme }: { theme: string }) => {
|
||||
const { reactionInit } = useContext(MessageContext);
|
||||
return (
|
||||
<Touchable
|
||||
|
@ -49,7 +47,7 @@ const AddReaction = React.memo(({ theme }: IMessageAddReaction) => {
|
|||
|
||||
const Reaction = React.memo(({ reaction, getCustomEmoji, theme }: IMessageReaction) => {
|
||||
const { onReactionPress, onReactionLongPress, baseUrl, user } = useContext(MessageContext);
|
||||
const reacted = reaction.usernames.findIndex((item: IMessageReaction) => item === user.username) !== -1;
|
||||
const reacted = reaction.usernames.findIndex((item: string) => item === user.username) !== -1;
|
||||
return (
|
||||
<Touchable
|
||||
onPress={() => onReactionPress(reaction.emoji)}
|
||||
|
@ -76,13 +74,15 @@ const Reaction = React.memo(({ reaction, getCustomEmoji, theme }: IMessageReacti
|
|||
);
|
||||
});
|
||||
|
||||
const Reactions = React.memo(({ reactions, getCustomEmoji, theme }: IMessageReactions) => {
|
||||
const Reactions = React.memo(({ reactions, getCustomEmoji }: IMessageReactions) => {
|
||||
const { theme } = useTheme();
|
||||
|
||||
if (!Array.isArray(reactions) || reactions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<View style={styles.reactionsContainer}>
|
||||
{reactions.map((reaction: any) => (
|
||||
{reactions.map(reaction => (
|
||||
<Reaction key={reaction.emoji} reaction={reaction} getCustomEmoji={getCustomEmoji} theme={theme} />
|
||||
))}
|
||||
<AddReaction theme={theme} />
|
||||
|
@ -94,4 +94,4 @@ Reaction.displayName = 'MessageReaction';
|
|||
Reactions.displayName = 'MessageReactions';
|
||||
AddReaction.displayName = 'MessageAddReaction';
|
||||
|
||||
export default withTheme(Reactions);
|
||||
export default Reactions;
|
||||
|
|
|
@ -3,14 +3,10 @@ import React from 'react';
|
|||
import { themes } from '../../constants/colors';
|
||||
import { CustomIcon } from '../../lib/Icons';
|
||||
import styles from './styles';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
interface IMessageReadReceipt {
|
||||
isReadReceiptEnabled: boolean;
|
||||
unread: boolean;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const ReadReceipt = React.memo(({ isReadReceiptEnabled, unread, theme }: IMessageReadReceipt) => {
|
||||
const ReadReceipt = React.memo(({ isReadReceiptEnabled, unread }: { isReadReceiptEnabled?: boolean; unread: boolean }) => {
|
||||
const { theme } = useTheme();
|
||||
if (isReadReceiptEnabled && !unread && unread !== null) {
|
||||
return <CustomIcon name='check' color={themes[theme].tintColor} size={15} style={styles.readReceipt} />;
|
||||
}
|
||||
|
|
|
@ -7,15 +7,18 @@ import { themes } from '../../constants/colors';
|
|||
import I18n from '../../i18n';
|
||||
import { MarkdownPreview } from '../markdown';
|
||||
import { IMessageRepliedThread } from './interfaces';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
const RepliedThread = memo(({ tmid, tmsg, isHeader, fetchThreadName, id, isEncrypted }: IMessageRepliedThread) => {
|
||||
const { theme } = useTheme();
|
||||
|
||||
const RepliedThread = memo(({ tmid, tmsg, isHeader, fetchThreadName, id, isEncrypted, theme }: IMessageRepliedThread) => {
|
||||
if (!tmid || !isHeader) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [msg, setMsg] = useState(isEncrypted ? I18n.t('Encrypted_message') : tmsg);
|
||||
const fetch = async () => {
|
||||
const threadName = await fetchThreadName(tmid, id);
|
||||
const threadName = fetchThreadName ? await fetchThreadName(tmid, id) : '';
|
||||
setMsg(threadName);
|
||||
};
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ const styles = StyleSheet.create({
|
|||
marginBottom: 4
|
||||
},
|
||||
image: {
|
||||
// @ts-ignore
|
||||
// @ts-ignore TODO - check with the team, change this to undefined
|
||||
width: null,
|
||||
height: 200,
|
||||
flex: 1,
|
||||
|
@ -93,24 +93,6 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface IMessageTitle {
|
||||
attachment: IAttachment;
|
||||
timeFormat?: string;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
interface IMessageDescription {
|
||||
attachment: IAttachment;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
interface IMessageFields {
|
||||
attachment: IAttachment;
|
||||
theme: string;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
}
|
||||
|
||||
interface IMessageReply {
|
||||
attachment: IAttachment;
|
||||
timeFormat?: string;
|
||||
|
@ -118,7 +100,7 @@ interface IMessageReply {
|
|||
getCustomEmoji: TGetCustomEmoji;
|
||||
}
|
||||
|
||||
const Title = React.memo(({ attachment, timeFormat, theme }: IMessageTitle) => {
|
||||
const Title = React.memo(({ attachment, timeFormat, theme }: { attachment: IAttachment; timeFormat?: string; theme: string }) => {
|
||||
const time = attachment.message_link && attachment.ts ? moment(attachment.ts).format(timeFormat) : null;
|
||||
return (
|
||||
<View style={styles.authorContainer}>
|
||||
|
@ -132,7 +114,7 @@ const Title = React.memo(({ attachment, timeFormat, theme }: IMessageTitle) => {
|
|||
});
|
||||
|
||||
const Description = React.memo(
|
||||
({ attachment, getCustomEmoji, theme }: IMessageDescription) => {
|
||||
({ attachment, getCustomEmoji, theme }: { attachment: IAttachment; getCustomEmoji: TGetCustomEmoji; theme: string }) => {
|
||||
const text = attachment.text || attachment.title;
|
||||
if (!text) {
|
||||
return null;
|
||||
|
@ -164,7 +146,7 @@ const Description = React.memo(
|
|||
);
|
||||
|
||||
const UrlImage = React.memo(
|
||||
({ image }: any) => {
|
||||
({ image }: { image?: string }) => {
|
||||
if (!image) {
|
||||
return null;
|
||||
}
|
||||
|
@ -176,7 +158,7 @@ const UrlImage = React.memo(
|
|||
);
|
||||
|
||||
const Fields = React.memo(
|
||||
({ attachment, theme, getCustomEmoji }: IMessageFields) => {
|
||||
({ attachment, theme, getCustomEmoji }: { attachment: IAttachment; theme: string; getCustomEmoji: TGetCustomEmoji }) => {
|
||||
if (!attachment.fields) {
|
||||
return null;
|
||||
}
|
||||
|
@ -206,12 +188,12 @@ const Fields = React.memo(
|
|||
const Reply = React.memo(
|
||||
({ attachment, timeFormat, index, getCustomEmoji }: IMessageReply) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { theme } = useTheme();
|
||||
|
||||
if (!attachment) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { theme } = useTheme();
|
||||
const { baseUrl, user, jumpToMessage } = useContext(MessageContext);
|
||||
|
||||
const onPress = async () => {
|
||||
|
|
|
@ -7,9 +7,12 @@ import MessageContext from './Context';
|
|||
import ThreadDetails from '../ThreadDetails';
|
||||
import I18n from '../../i18n';
|
||||
import { IMessageThread } from './interfaces';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
const Thread = React.memo(
|
||||
({ msg, tcount, tlm, isThreadRoom, theme, id }: IMessageThread) => {
|
||||
({ msg, tcount, tlm, isThreadRoom, id }: IMessageThread) => {
|
||||
const { theme } = useTheme();
|
||||
|
||||
if (!tlm || isThreadRoom || tcount === 0) {
|
||||
return null;
|
||||
}
|
||||
|
@ -38,9 +41,6 @@ const Thread = React.memo(
|
|||
if (prevProps.tcount !== nextProps.tcount) {
|
||||
return false;
|
||||
}
|
||||
if (prevProps.theme !== nextProps.theme) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
|
|
@ -8,11 +8,12 @@ import Touchable from './Touchable';
|
|||
import openLink from '../../utils/openLink';
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
import { useTheme, withTheme } from '../../theme';
|
||||
import { LISTENER } from '../Toast';
|
||||
import EventEmitter from '../../utils/events';
|
||||
import I18n from '../../i18n';
|
||||
import MessageContext from './Context';
|
||||
import { IUrl } from '../../definitions';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
|
@ -50,29 +51,6 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface IMessageUrlContent {
|
||||
title: string;
|
||||
description: string;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
interface IMessageUrl {
|
||||
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) {
|
||||
|
@ -86,7 +64,7 @@ const UrlImage = React.memo(
|
|||
);
|
||||
|
||||
const UrlContent = React.memo(
|
||||
({ title, description, theme }: IMessageUrlContent) => (
|
||||
({ title, description, theme }: { title: string; description: string; theme: string }) => (
|
||||
<View style={styles.textContainer}>
|
||||
{title ? (
|
||||
<Text style={[styles.title, { color: themes[theme].tintColor }]} numberOfLines={2}>
|
||||
|
@ -115,7 +93,7 @@ const UrlContent = React.memo(
|
|||
);
|
||||
|
||||
const Url = React.memo(
|
||||
({ url, index, theme }: IMessageUrl) => {
|
||||
({ url, index, theme }: { url: IUrl; index: number; theme: string }) => {
|
||||
if (!url || url?.ignoreParse) {
|
||||
return null;
|
||||
}
|
||||
|
@ -152,14 +130,17 @@ const Url = React.memo(
|
|||
);
|
||||
|
||||
const Urls = React.memo(
|
||||
({ urls, theme }: IMessageUrls) => {
|
||||
// TODO - didn't work - (React.ReactElement | null)[] | React.ReactElement | null
|
||||
({ urls }: { urls?: IUrl[] }): any => {
|
||||
const { theme } = useTheme();
|
||||
|
||||
if (!urls || urls.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return urls.map((url: any, index: number) => <Url url={url} key={url.url} index={index} theme={theme!} />);
|
||||
return urls.map((url: IUrl, index: number) => <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)
|
||||
);
|
||||
|
||||
UrlImage.displayName = 'MessageUrlImage';
|
||||
|
|
|
@ -3,12 +3,14 @@ import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
|||
import moment from 'moment';
|
||||
|
||||
import { themes } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
import { useTheme } from '../../theme';
|
||||
import MessageError from './MessageError';
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import messageStyles from './styles';
|
||||
import MessageContext from './Context';
|
||||
import { SYSTEM_MESSAGE_TYPES_WITH_AUTHOR_NAME } from './utils';
|
||||
import { SubscriptionType } from '../../definitions';
|
||||
import { IRoomInfoParam } from '../../views/SearchMessagesView';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -49,15 +51,15 @@ interface IMessageUser {
|
|||
alias?: string;
|
||||
ts?: Date;
|
||||
timeFormat?: string;
|
||||
theme: string;
|
||||
navToRoomInfo?: Function;
|
||||
navToRoomInfo?: (navParam: IRoomInfoParam) => void;
|
||||
type: string;
|
||||
}
|
||||
|
||||
const User = React.memo(
|
||||
({ isHeader, useRealName, author, alias, ts, timeFormat, hasError, theme, navToRoomInfo, type, ...props }: IMessageUser) => {
|
||||
({ isHeader, useRealName, author, alias, ts, timeFormat, hasError, navToRoomInfo, type, ...props }: IMessageUser) => {
|
||||
if (isHeader || hasError) {
|
||||
const { user } = useContext(MessageContext);
|
||||
const { theme } = useTheme();
|
||||
const username = (useRealName && author?.name) || author?.username;
|
||||
const aliasUsername = alias ? (
|
||||
<Text style={[styles.alias, { color: themes[theme].auxiliaryText }]}> @{username}</Text>
|
||||
|
@ -65,8 +67,8 @@ const User = React.memo(
|
|||
const time = moment(ts).format(timeFormat);
|
||||
const onUserPress = () => {
|
||||
navToRoomInfo?.({
|
||||
t: 'd',
|
||||
rid: author?._id
|
||||
t: SubscriptionType.DIRECT,
|
||||
rid: author?._id || ''
|
||||
});
|
||||
};
|
||||
const isDisabled = author?._id === user.id;
|
||||
|
@ -83,7 +85,7 @@ const User = React.memo(
|
|||
<Text
|
||||
style={[styles.usernameInfoMessage, { color: themes[theme].titleText }]}
|
||||
onPress={onUserPress}
|
||||
// @ts-ignore
|
||||
// @ts-ignore // TODO - check this prop
|
||||
disabled={isDisabled}>
|
||||
{textContent}
|
||||
</Text>
|
||||
|
@ -98,7 +100,7 @@ const User = React.memo(
|
|||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={[messageStyles.time, { color: themes[theme].auxiliaryTintColor }]}>{time}</Text>
|
||||
{hasError && <MessageError hasError={hasError} theme={theme} {...props} />}
|
||||
{hasError ? <MessageError hasError={hasError} {...props} /> : null}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -108,4 +110,4 @@ const User = React.memo(
|
|||
|
||||
User.displayName = 'MessageUser';
|
||||
|
||||
export default withTheme(User);
|
||||
export default User;
|
||||
|
|
|
@ -16,9 +16,10 @@ import I18n from '../../i18n';
|
|||
import { IAttachment } from '../../definitions/IAttachment';
|
||||
import RCActivityIndicator from '../ActivityIndicator';
|
||||
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(isIOS ? [] : ['video/3gp', 'video/mkv'])];
|
||||
const isTypeSupported = (type: any) => SUPPORTED_TYPES.indexOf(type) !== -1;
|
||||
const isTypeSupported = (type: string) => SUPPORTED_TYPES.indexOf(type) !== -1;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
|
@ -33,23 +34,24 @@ const styles = StyleSheet.create({
|
|||
|
||||
interface IMessageVideo {
|
||||
file: IAttachment;
|
||||
showAttachment?: Function;
|
||||
showAttachment?: (file: IAttachment) => void;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
style?: StyleProp<TextStyle>[];
|
||||
isReply?: boolean;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const Video = React.memo(
|
||||
({ file, showAttachment, getCustomEmoji, style, isReply, theme }: IMessageVideo) => {
|
||||
({ file, showAttachment, getCustomEmoji, style, isReply }: IMessageVideo) => {
|
||||
const { baseUrl, user } = useContext(MessageContext);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { theme } = useTheme();
|
||||
|
||||
if (!baseUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const onPress = async () => {
|
||||
if (isTypeSupported(file.video_type) && showAttachment) {
|
||||
if (file.video_type && isTypeSupported(file.video_type) && showAttachment) {
|
||||
return showAttachment(file);
|
||||
}
|
||||
|
||||
|
@ -93,7 +95,7 @@ const Video = React.memo(
|
|||
</>
|
||||
);
|
||||
},
|
||||
(prevProps, nextProps) => dequal(prevProps.file, nextProps.file) && prevProps.theme === nextProps.theme
|
||||
(prevProps, nextProps) => dequal(prevProps.file, nextProps.file)
|
||||
);
|
||||
|
||||
export default Video;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Keyboard, ViewStyle } from 'react-native';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import Message from './Message';
|
||||
import MessageContext from './Context';
|
||||
|
@ -7,10 +8,11 @@ import debounce from '../../utils/debounce';
|
|||
import { SYSTEM_MESSAGES, getMessageTranslation } from './utils';
|
||||
import { E2E_MESSAGE_TYPE, E2E_STATUS } from '../../lib/encryption/constants';
|
||||
import messagesStatus from '../../constants/messagesStatus';
|
||||
import { withTheme } from '../../theme';
|
||||
import { useTheme, withTheme } from '../../theme';
|
||||
import openLink from '../../utils/openLink';
|
||||
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
||||
import { TAnyMessageModel } from '../../definitions';
|
||||
import { IAttachment, TAnyMessageModel } from '../../definitions';
|
||||
import { IRoomInfoParam } from '../../views/SearchMessagesView';
|
||||
|
||||
interface IMessageContainerProps {
|
||||
item: TAnyMessageModel;
|
||||
|
@ -20,7 +22,7 @@ interface IMessageContainerProps {
|
|||
token: string;
|
||||
};
|
||||
msg?: string;
|
||||
rid?: string;
|
||||
rid: string;
|
||||
timeFormat?: string;
|
||||
style?: ViewStyle;
|
||||
archived?: boolean;
|
||||
|
@ -37,44 +39,35 @@ interface IMessageContainerProps {
|
|||
isIgnored?: boolean;
|
||||
highlighted?: boolean;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
onLongPress?: Function;
|
||||
onReactionPress?: Function;
|
||||
onEncryptedPress?: Function;
|
||||
onDiscussionPress?: Function;
|
||||
onThreadPress?: Function;
|
||||
errorActionsShow?: Function;
|
||||
replyBroadcast?: Function;
|
||||
reactionInit?: Function;
|
||||
fetchThreadName?: Function;
|
||||
showAttachment?: Function;
|
||||
onReactionLongPress?: Function;
|
||||
navToRoomInfo?: Function;
|
||||
callJitsi?: Function;
|
||||
blockAction?: Function;
|
||||
onAnswerButtonPress?: Function;
|
||||
theme?: string;
|
||||
onLongPress?: (item: TAnyMessageModel) => void;
|
||||
onReactionPress?: (emoji: string, id: string) => void;
|
||||
onEncryptedPress?: () => void;
|
||||
onDiscussionPress?: (item: TAnyMessageModel) => void;
|
||||
onThreadPress?: (item: TAnyMessageModel) => void;
|
||||
errorActionsShow?: (item: TAnyMessageModel) => void;
|
||||
replyBroadcast?: (item: TAnyMessageModel) => void;
|
||||
reactionInit?: (item: TAnyMessageModel) => void;
|
||||
fetchThreadName?: (tmid: string, id: string) => Promise<string | undefined>;
|
||||
showAttachment: (file: IAttachment) => void;
|
||||
onReactionLongPress?: (item: TAnyMessageModel) => void;
|
||||
navToRoomInfo: (navParam: IRoomInfoParam) => void;
|
||||
callJitsi?: () => void;
|
||||
blockAction?: (params: { actionId: string; appId: string; value: string; blockId: string; rid: string; mid: string }) => void;
|
||||
onAnswerButtonPress?: (message: string, tmid?: string, tshow?: boolean) => void;
|
||||
threadBadgeColor?: string;
|
||||
toggleFollowThread?: Function;
|
||||
jumpToMessage?: Function;
|
||||
onPress?: Function;
|
||||
toggleFollowThread?: (isFollowingThread: boolean, tmid?: string) => Promise<void>;
|
||||
jumpToMessage?: (link: string) => void;
|
||||
onPress?: () => void;
|
||||
}
|
||||
|
||||
class MessageContainer extends React.Component<IMessageContainerProps> {
|
||||
interface IMessageContainerState {
|
||||
isManualUnignored: boolean;
|
||||
}
|
||||
|
||||
class MessageContainer extends React.Component<IMessageContainerProps, IMessageContainerState> {
|
||||
static defaultProps = {
|
||||
getCustomEmoji: () => null,
|
||||
onLongPress: () => {},
|
||||
onReactionPress: () => {},
|
||||
onEncryptedPress: () => {},
|
||||
onDiscussionPress: () => {},
|
||||
onThreadPress: () => {},
|
||||
onAnswerButtonPress: () => {},
|
||||
errorActionsShow: () => {},
|
||||
replyBroadcast: () => {},
|
||||
reactionInit: () => {},
|
||||
fetchThreadName: () => {},
|
||||
showAttachment: () => {},
|
||||
onReactionLongPress: () => {},
|
||||
navToRoomInfo: () => {},
|
||||
callJitsi: () => {},
|
||||
blockAction: () => {},
|
||||
archived: false,
|
||||
|
@ -85,7 +78,7 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
|
||||
state = { isManualUnignored: false };
|
||||
|
||||
private subscription: any;
|
||||
private subscription?: Subscription;
|
||||
|
||||
componentDidMount() {
|
||||
const { item } = this.props;
|
||||
|
@ -97,12 +90,9 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps: any, nextState: any) {
|
||||
shouldComponentUpdate(nextProps: IMessageContainerProps, nextState: IMessageContainerState) {
|
||||
const { isManualUnignored } = this.state;
|
||||
const { theme, threadBadgeColor, isIgnored, highlighted } = this.props;
|
||||
if (nextProps.theme !== theme) {
|
||||
return true;
|
||||
}
|
||||
const { threadBadgeColor, isIgnored, highlighted } = this.props;
|
||||
if (nextProps.highlighted !== highlighted) {
|
||||
return true;
|
||||
}
|
||||
|
@ -169,7 +159,7 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
}
|
||||
};
|
||||
|
||||
onReactionPress = (emoji: any) => {
|
||||
onReactionPress = (emoji: string) => {
|
||||
const { onReactionPress, item } = this.props;
|
||||
if (onReactionPress) {
|
||||
onReactionPress(emoji, item.id);
|
||||
|
@ -228,7 +218,7 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
previousItem.u.username === item.u.username &&
|
||||
!(previousItem.groupable === false || item.groupable === false || broadcast === true) &&
|
||||
// @ts-ignore TODO: IMessage vs IMessageFromServer non-sense
|
||||
item.ts - previousItem.ts < Message_GroupingPeriod! * 1000 &&
|
||||
item.ts - previousItem.ts < Message_GroupingPeriod * 1000 &&
|
||||
previousItem.tmid === item.tmid
|
||||
) {
|
||||
return false;
|
||||
|
@ -303,10 +293,11 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
};
|
||||
|
||||
onLinkPress = (link: string): void => {
|
||||
const { item, theme, jumpToMessage } = this.props;
|
||||
const isMessageLink = item?.attachments?.findIndex((att: any) => att?.message_link === link) !== -1;
|
||||
if (isMessageLink) {
|
||||
return jumpToMessage!(link);
|
||||
const { theme } = useTheme();
|
||||
const { item, jumpToMessage } = this.props;
|
||||
const isMessageLink = item?.attachments?.findIndex((att: IAttachment) => att?.message_link === link) !== -1;
|
||||
if (isMessageLink && jumpToMessage) {
|
||||
return jumpToMessage(link);
|
||||
}
|
||||
openLink(link, theme);
|
||||
};
|
||||
|
@ -332,7 +323,6 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
callJitsi,
|
||||
blockAction,
|
||||
rid,
|
||||
theme,
|
||||
threadBadgeColor,
|
||||
toggleFollowThread,
|
||||
jumpToMessage,
|
||||
|
@ -371,8 +361,8 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
let message = msg;
|
||||
// "autoTranslateRoom" and "autoTranslateLanguage" are properties from the subscription
|
||||
// "autoTranslateMessage" is a toggle between "View Original" and "Translate" state
|
||||
if (autoTranslateRoom && autoTranslateMessage) {
|
||||
message = getMessageTranslation(item, autoTranslateLanguage!) || message;
|
||||
if (autoTranslateRoom && autoTranslateMessage && autoTranslateLanguage) {
|
||||
message = getMessageTranslation(item, autoTranslateLanguage) || message;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -396,14 +386,15 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
toggleFollowThread,
|
||||
replies
|
||||
}}>
|
||||
{/* @ts-ignore*/}
|
||||
<Message
|
||||
id={id}
|
||||
msg={message}
|
||||
md={md}
|
||||
rid={rid!}
|
||||
rid={rid}
|
||||
author={u}
|
||||
ts={ts}
|
||||
type={t as any}
|
||||
type={t}
|
||||
attachments={attachments}
|
||||
blocks={blocks}
|
||||
urls={urls}
|
||||
|
@ -413,23 +404,20 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
emoji={emoji}
|
||||
timeFormat={timeFormat}
|
||||
style={style}
|
||||
archived={archived!}
|
||||
broadcast={broadcast!}
|
||||
archived={archived}
|
||||
broadcast={broadcast}
|
||||
useRealName={useRealName}
|
||||
isReadReceiptEnabled={isReadReceiptEnabled!}
|
||||
isReadReceiptEnabled={isReadReceiptEnabled}
|
||||
unread={unread}
|
||||
role={role}
|
||||
drid={drid}
|
||||
dcount={dcount}
|
||||
// @ts-ignore
|
||||
dlm={dlm}
|
||||
tmid={tmid}
|
||||
tcount={tcount}
|
||||
// @ts-ignore
|
||||
tlm={tlm}
|
||||
tmsg={tmsg}
|
||||
fetchThreadName={fetchThreadName!}
|
||||
// @ts-ignore
|
||||
fetchThreadName={fetchThreadName}
|
||||
mentions={mentions}
|
||||
channels={channels}
|
||||
isIgnored={this.isIgnored}
|
||||
|
@ -442,13 +430,12 @@ class MessageContainer extends React.Component<IMessageContainerProps> {
|
|||
isTemp={this.isTemp}
|
||||
isEncrypted={this.isEncrypted}
|
||||
hasError={this.hasError}
|
||||
showAttachment={showAttachment!}
|
||||
showAttachment={showAttachment}
|
||||
getCustomEmoji={getCustomEmoji}
|
||||
navToRoomInfo={navToRoomInfo!}
|
||||
callJitsi={callJitsi!}
|
||||
blockAction={blockAction!}
|
||||
theme={theme as string}
|
||||
highlighted={highlighted!}
|
||||
navToRoomInfo={navToRoomInfo}
|
||||
callJitsi={callJitsi}
|
||||
blockAction={blockAction}
|
||||
highlighted={highlighted}
|
||||
/>
|
||||
</MessageContext.Provider>
|
||||
);
|
||||
|
|
|
@ -1,63 +1,45 @@
|
|||
import { MarkdownAST } from '@rocket.chat/message-parser';
|
||||
import { StyleProp, TextStyle } from 'react-native';
|
||||
import { ImageStyle } from '@rocket.chat/react-native-fast-image';
|
||||
|
||||
import { IUserChannel, IUserMention } from '../markdown/interfaces';
|
||||
import { IUserChannel } from '../markdown/interfaces';
|
||||
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
||||
import { IAttachment } from '../../definitions';
|
||||
|
||||
export type TMessageType = 'discussion-created' | 'jitsi_call_started';
|
||||
import { IAttachment, IThread, IUrl, IUserMention, IUserMessage, MessageType, TAnyMessageModel } from '../../definitions';
|
||||
import { IRoomInfoParam } from '../../views/SearchMessagesView';
|
||||
|
||||
export interface IMessageAttachments {
|
||||
attachments?: IAttachment[];
|
||||
timeFormat?: string;
|
||||
style?: StyleProp<TextStyle>[];
|
||||
isReply?: boolean;
|
||||
showAttachment?: Function;
|
||||
showAttachment?: (file: IAttachment) => void;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
}
|
||||
|
||||
export interface IMessageAttachedActions {
|
||||
attachment: IAttachment;
|
||||
}
|
||||
|
||||
export interface IMessageAvatar {
|
||||
isHeader: boolean;
|
||||
avatar: string;
|
||||
emoji: string;
|
||||
author: {
|
||||
username: string;
|
||||
_id: string;
|
||||
};
|
||||
avatar?: string;
|
||||
emoji?: string;
|
||||
author?: IUserMessage;
|
||||
small?: boolean;
|
||||
navToRoomInfo: Function;
|
||||
navToRoomInfo: (navParam: IRoomInfoParam) => void;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
}
|
||||
|
||||
export interface IMessageBlocks {
|
||||
blocks: any;
|
||||
blocks: { appId?: string }[];
|
||||
id: string;
|
||||
rid: string;
|
||||
blockAction: Function;
|
||||
blockAction?: (params: { actionId: string; appId: string; value: string; blockId: string; rid: string; mid: string }) => void;
|
||||
}
|
||||
|
||||
export interface IMessageBroadcast {
|
||||
author: {
|
||||
_id: string;
|
||||
};
|
||||
broadcast: boolean;
|
||||
theme: string;
|
||||
author?: IUserMessage;
|
||||
broadcast?: boolean;
|
||||
}
|
||||
|
||||
export interface IMessageCallButton {
|
||||
theme: string;
|
||||
callJitsi: Function;
|
||||
}
|
||||
|
||||
export interface IUser {
|
||||
id: string;
|
||||
username: string;
|
||||
token: string;
|
||||
name: string;
|
||||
callJitsi?: () => void;
|
||||
}
|
||||
|
||||
export interface IMessageContent {
|
||||
|
@ -68,40 +50,27 @@ export interface IMessageContent {
|
|||
isThreadRoom: boolean;
|
||||
msg?: string;
|
||||
md?: MarkdownAST;
|
||||
theme: string;
|
||||
isEdited: boolean;
|
||||
isEncrypted: boolean;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
channels?: IUserChannel[];
|
||||
mentions?: IUserMention[];
|
||||
navToRoomInfo?: Function;
|
||||
navToRoomInfo: (navParam: IRoomInfoParam) => void;
|
||||
useRealName?: boolean;
|
||||
isIgnored: boolean;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface IMessageDiscussion {
|
||||
msg?: string;
|
||||
dcount?: number;
|
||||
dlm?: Date;
|
||||
theme: string;
|
||||
}
|
||||
|
||||
export interface IMessageEmoji {
|
||||
content: any;
|
||||
content: string;
|
||||
baseUrl: string;
|
||||
standardEmojiStyle: object;
|
||||
customEmojiStyle: object;
|
||||
standardEmojiStyle: { fontSize: number };
|
||||
customEmojiStyle: StyleProp<ImageStyle>;
|
||||
getCustomEmoji: TGetCustomEmoji;
|
||||
}
|
||||
|
||||
export interface IMessageThread {
|
||||
msg?: string;
|
||||
tcount?: number | null;
|
||||
theme: string;
|
||||
tlm?: Date;
|
||||
export interface IMessageThread extends Pick<IThread, 'msg' | 'tcount' | 'tlm' | 'id'> {
|
||||
isThreadRoom: boolean;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface IMessageTouchable {
|
||||
|
@ -109,40 +78,35 @@ export interface IMessageTouchable {
|
|||
isInfo: boolean;
|
||||
isThreadReply: boolean;
|
||||
isTemp: boolean;
|
||||
archived: boolean;
|
||||
highlighted: boolean;
|
||||
theme: string;
|
||||
ts?: any;
|
||||
urls?: any;
|
||||
archived?: boolean;
|
||||
highlighted?: boolean;
|
||||
ts?: string | Date;
|
||||
urls?: IUrl[];
|
||||
reactions?: any;
|
||||
alias?: any;
|
||||
role?: any;
|
||||
drid?: any;
|
||||
alias?: string;
|
||||
role?: string;
|
||||
drid?: string;
|
||||
}
|
||||
|
||||
export interface IMessageRepliedThread {
|
||||
tmid?: string;
|
||||
tmsg?: string;
|
||||
id: string;
|
||||
export interface IMessageRepliedThread extends Pick<IThread, 'tmid' | 'tmsg' | 'id'> {
|
||||
isHeader: boolean;
|
||||
theme: string;
|
||||
fetchThreadName: Function;
|
||||
fetchThreadName?: (tmid: string, id: string) => Promise<string | undefined>;
|
||||
isEncrypted: boolean;
|
||||
}
|
||||
|
||||
export interface IMessageInner
|
||||
extends IMessageDiscussion,
|
||||
IMessageContent,
|
||||
extends IMessageContent,
|
||||
IMessageCallButton,
|
||||
IMessageBlocks,
|
||||
IMessageThread,
|
||||
IMessageAttachments,
|
||||
IMessageBroadcast {
|
||||
type: TMessageType;
|
||||
type: MessageType;
|
||||
blocks: [];
|
||||
urls?: IUrl[];
|
||||
}
|
||||
|
||||
export interface IMessage extends IMessageRepliedThread, IMessageInner {
|
||||
export interface IMessage extends IMessageRepliedThread, IMessageInner, IMessageAvatar {
|
||||
isThreadReply: boolean;
|
||||
isThreadSequential: boolean;
|
||||
isInfo: boolean;
|
||||
|
@ -150,9 +114,11 @@ export interface IMessage extends IMessageRepliedThread, IMessageInner {
|
|||
isHeader: boolean;
|
||||
hasError: boolean;
|
||||
style: any;
|
||||
onLongPress: Function;
|
||||
isReadReceiptEnabled: boolean;
|
||||
// style: ViewStyle;
|
||||
onLongPress?: (item: TAnyMessageModel) => void;
|
||||
isReadReceiptEnabled?: boolean;
|
||||
unread?: boolean;
|
||||
theme: string;
|
||||
isIgnored: boolean;
|
||||
dcount: number | undefined;
|
||||
dlm: string | Date | undefined;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ export interface IAttachment {
|
|||
image_size?: number;
|
||||
author_name?: string;
|
||||
author_icon?: string;
|
||||
actions?: [];
|
||||
actions?: { type: string; msg: string; text: string }[];
|
||||
message_link?: string;
|
||||
text?: string;
|
||||
short?: boolean;
|
||||
|
|
|
@ -6,7 +6,7 @@ import { IAttachment } from './IAttachment';
|
|||
import { IReaction } from './IReaction';
|
||||
import { TThreadMessageModel } from './IThreadMessage';
|
||||
import { TThreadModel } from './IThread';
|
||||
import { IUrlFromServer } from './IUrl';
|
||||
import { IUrl, IUrlFromServer } from './IUrl';
|
||||
|
||||
export type MessageType = 'jitsi_call_started' | 'discussion-created' | 'e2e' | 'load_more' | 'rm' | 'uj' | MessageTypeLoad;
|
||||
|
||||
|
@ -75,7 +75,7 @@ export interface IMessageFromServer {
|
|||
ts: string | Date; // wm date issue
|
||||
u: IUserMessage;
|
||||
_updatedAt: string | Date;
|
||||
urls?: IUrlFromServer[];
|
||||
urls?: IUrl[];
|
||||
mentions?: IUserMention[];
|
||||
channels?: IUserChannel[];
|
||||
md?: MarkdownAST;
|
||||
|
@ -111,7 +111,7 @@ export interface ILoadMoreMessage {
|
|||
|
||||
export interface IMessage extends IMessageFromServer {
|
||||
id: string;
|
||||
t?: MessageType;
|
||||
t: MessageType;
|
||||
alias?: string;
|
||||
parseUrls?: boolean;
|
||||
avatar?: string;
|
||||
|
|
|
@ -45,5 +45,4 @@ export interface IUrl extends IUrlFromServer {
|
|||
title: string;
|
||||
description: string;
|
||||
image: string;
|
||||
url: string;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ export type ChatsStackParamList = {
|
|||
};
|
||||
RoomInfoView: {
|
||||
room?: ISubscription;
|
||||
member: any;
|
||||
member?: any;
|
||||
rid: string;
|
||||
t: SubscriptionType;
|
||||
showCloseModal?: boolean;
|
||||
|
|
|
@ -22,6 +22,7 @@ import styles from './styles';
|
|||
import { ChatsStackParamList } from '../../stacks/types';
|
||||
import { ISubscription, SubscriptionType } from '../../definitions/ISubscription';
|
||||
import { IEmoji } from '../../definitions/IEmoji';
|
||||
import { IRoomInfoParam } from '../SearchMessagesView';
|
||||
import { TMessageModel } from '../../definitions';
|
||||
|
||||
interface IMessagesViewProps {
|
||||
|
@ -43,14 +44,6 @@ interface IMessagesViewProps {
|
|||
isMasterDetail: boolean;
|
||||
}
|
||||
|
||||
interface IRoomInfoParam {
|
||||
room: ISubscription;
|
||||
member: any;
|
||||
rid: string;
|
||||
t: SubscriptionType;
|
||||
joined: boolean;
|
||||
}
|
||||
|
||||
interface IMessagesViewState {
|
||||
loading: boolean;
|
||||
messages: [];
|
||||
|
@ -188,7 +181,8 @@ class MessagesView extends React.Component<IMessagesViewProps, any> {
|
|||
showAttachment: this.showAttachment,
|
||||
getCustomEmoji: this.getCustomEmoji,
|
||||
navToRoomInfo: this.navToRoomInfo,
|
||||
onPress: () => this.jumpToMessage({ item })
|
||||
onPress: () => this.jumpToMessage({ item }),
|
||||
rid: this.rid
|
||||
});
|
||||
|
||||
return {
|
||||
|
@ -219,7 +213,6 @@ class MessagesView extends React.Component<IMessagesViewProps, any> {
|
|||
}
|
||||
]
|
||||
}}
|
||||
theme={theme}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
|
|
@ -867,7 +867,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
}
|
||||
};
|
||||
|
||||
replyBroadcast = (message: Record<string, string>) => {
|
||||
replyBroadcast = (message: IMessage) => {
|
||||
const { dispatch } = this.props;
|
||||
dispatch(replyBroadcast(message));
|
||||
};
|
||||
|
|
|
@ -42,12 +42,12 @@ interface ISearchMessagesViewState {
|
|||
searchText: string;
|
||||
}
|
||||
|
||||
interface IRoomInfoParam {
|
||||
room: ISubscription;
|
||||
member: any;
|
||||
export interface IRoomInfoParam {
|
||||
room?: ISubscription;
|
||||
member?: any;
|
||||
rid: string;
|
||||
t: SubscriptionType;
|
||||
joined: boolean;
|
||||
joined?: boolean;
|
||||
}
|
||||
|
||||
interface INavigationOption {
|
||||
|
|
Loading…
Reference in New Issue