Rocket.Chat.ReactNative/app/containers/message/Reply.tsx

287 lines
7.5 KiB
TypeScript
Raw Normal View History

import React, { useContext, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import moment from 'moment';
import { dequal } from 'dequal';
import FastImage from 'react-native-fast-image';
import Touchable from './Touchable';
import Markdown from '../markdown';
import openLink from '../../lib/methods/helpers/openLink';
import sharedStyles from '../../views/Styles';
import { themes } from '../../lib/constants';
import MessageContext from './Context';
import { fileDownloadAndPreview } from './helpers/fileDownload';
import { IAttachment, TGetCustomEmoji } from '../../definitions';
import RCActivityIndicator from '../ActivityIndicator';
2022-03-21 20:44:06 +00:00
import Attachments from './Attachments';
import { TSupportedThemes, useTheme } from '../../theme';
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
import messageStyles from './styles';
const styles = StyleSheet.create({
button: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
2022-03-21 20:44:06 +00:00
marginVertical: 4,
alignSelf: 'flex-start',
2022-03-21 20:44:06 +00:00
borderLeftWidth: 2
},
attachmentContainer: {
flex: 1,
borderRadius: 4,
flexDirection: 'column',
2022-03-21 20:44:06 +00:00
paddingVertical: 4,
paddingLeft: 8
},
backdrop: {
...StyleSheet.absoluteFillObject
},
authorContainer: {
flex: 1,
flexDirection: 'row',
2022-03-21 20:44:06 +00:00
alignItems: 'center',
marginBottom: 8
},
author: {
fontSize: 16,
...sharedStyles.textMedium,
flexShrink: 1
},
fieldsContainer: {
flex: 1,
flexWrap: 'wrap',
flexDirection: 'row'
},
fieldContainer: {
flexDirection: 'column',
padding: 10
},
fieldTitle: {
fontSize: 14,
...sharedStyles.textSemibold
},
fieldValue: {
fontSize: 14,
...sharedStyles.textRegular
},
marginTop: {
marginTop: 4
},
marginBottom: {
marginBottom: 4
},
image: {
height: 200,
flex: 1,
borderTopLeftRadius: 4,
borderTopRightRadius: 4,
marginBottom: 1
},
title: {
flex: 1,
fontSize: 16,
marginBottom: 3,
...sharedStyles.textMedium
}
});
interface IMessageReply {
attachment: IAttachment;
timeFormat?: string;
index: number;
getCustomEmoji: TGetCustomEmoji;
}
const Title = React.memo(
({ attachment, timeFormat, theme }: { attachment: IAttachment; timeFormat?: string; theme: TSupportedThemes }) => {
const time = attachment.message_link && attachment.ts ? moment(attachment.ts).format(timeFormat) : null;
return (
<View style={styles.authorContainer}>
{attachment.author_name ? (
<Text numberOfLines={1} style={[styles.author, { color: themes[theme].auxiliaryTintColor }]}>
{attachment.author_name}
</Text>
) : null}
{time ? <Text style={[messageStyles.time, { color: themes[theme].auxiliaryText }]}>{time}</Text> : null}
{attachment.title ? <Text style={[styles.title, { color: themes[theme].bodyText }]}>{attachment.title}</Text> : null}
</View>
);
}
);
const Description = React.memo(
({
attachment,
getCustomEmoji,
theme
}: {
attachment: IAttachment;
getCustomEmoji: TGetCustomEmoji;
theme: TSupportedThemes;
}) => {
const { user } = useContext(MessageContext);
const text = attachment.text || attachment.title;
if (!text) {
return null;
}
2022-03-21 20:44:06 +00:00
return (
<Markdown
msg={text}
style={[{ color: themes[theme].auxiliaryTintColor, fontSize: 14 }]}
username={user.username}
getCustomEmoji={getCustomEmoji}
theme={theme}
2022-03-21 20:44:06 +00:00
/>
);
},
(prevProps, nextProps) => {
if (prevProps.attachment.text !== nextProps.attachment.text) {
return false;
}
if (prevProps.attachment.title !== nextProps.attachment.title) {
return false;
}
if (prevProps.theme !== nextProps.theme) {
return false;
}
return true;
}
);
const UrlImage = React.memo(
({ image }: { image?: string }) => {
const { baseUrl, user } = useContext(MessageContext);
if (!image) {
return null;
}
image = image.includes('http') ? image : `${baseUrl}/${image}?rc_uid=${user.id}&rc_token=${user.token}`;
return <FastImage source={{ uri: image }} style={styles.image} resizeMode={FastImage.resizeMode.cover} />;
},
(prevProps, nextProps) => prevProps.image === nextProps.image
);
const Fields = React.memo(
({
attachment,
theme,
getCustomEmoji
}: {
attachment: IAttachment;
theme: TSupportedThemes;
getCustomEmoji: TGetCustomEmoji;
}) => {
const { user } = useContext(MessageContext);
if (!attachment.fields) {
return null;
}
return (
<View style={styles.fieldsContainer}>
{attachment.fields.map(field => (
<View key={field.title} style={[styles.fieldContainer, { width: field.short ? '50%' : '100%' }]}>
<Text style={[styles.fieldTitle, { color: themes[theme].bodyText }]}>{field.title}</Text>
<Markdown msg={field?.value || ''} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
</View>
))}
</View>
);
},
(prevProps, nextProps) =>
dequal(prevProps.attachment.fields, nextProps.attachment.fields) && prevProps.theme === nextProps.theme
);
const Reply = React.memo(
feat: add media auto-download (#5076) * feat: media auto-download view * media auto download view completed and saving the settings in mmkv * audio download preference * audio auto download when the user who sent the audio is the same logged on mobile * creation of isAutoDownloadEnabled, evaluate hist hook, Image Full Size preload done * minor tweak audio show play button after download * refactor audioFile to handleMediaDownload and fixed the audio download * desestructured params to download too * image download and autoDownload, algo fix the formatAttachmentUrl to show the image from local * add the possibility to cancel image download and clear local images * refactor blur component * video download and auto download, also keeped the behavior to download unsuportted videos to the gallery * add the possibility to start downloading a video, then exit the room, back again to room and cancel the video previously downloading * remove the custom hook for autoDownload * remove blurcomponent, fix the blur style in image.tsx, minor tweak video function name * send messageId to video * introducing the reducer to keep the downloads in progress * create a media download selector * remove all the redux stuff and do the same as file upload * video download behavior * done for image and audio * fix the try catch download media * clean up * image container uiKit * fix lint * change rn-fetch-blob to expo-filesystem * add pt-br * pass the correct message id when there is an attachment on reply * refactor some changes requested * fix audio and move the netInfo from autoDownloadPreference to redux * variable isAutoDownloadEnable name and handleMediaDownload getExtension * message/Image refactored, change the component to show the image from FastImage to Image * refactor handleMediaDownload and deleteMedia * minor tweak * refactor audio * refactor video * fix the type on the messagesView(the view of files) * minor tweak * fix the name of searchMediaFIleAsync's result * minor tweak, add the default behavior, add the OFF as label * minor tweaks * verify if the media auto download exists on settings view * fix media auto download view layout and minor tweak wifi * avoid auto download from reply * minor tweak at comment * tweak list.section * change the name to netInfoState and Local_document_directory * remove mediaType and refactor audio and image * separate blurview * thumbnail video and video behavior * add Audio to i18n and minor tweak * set the blur as always dark and add the possibility to overlay * don't need to controle the filepath in the view * fix the loading in image and video at begin * save the file with a similar filename as expected * removed the necessity of messageId or id * minor tweak * switch useLayoutEffect to useEffect * avoid onpress do some edge case because of cached at video * minor tweak * tweak at audio comment extension * minor tweak type userpreferences * remove test id from mediaAutoDownloadView * change action's name to SET_NET_INFO_STATE * caching and deleting video's thumbnails * remove generate thumbnail * minor tweak in image * update camera-roll and save the file from local url * remove local_cache_directory and deleteThumbnail * update blur to fix error on android * fix blur is hiding the file description * avoid download unsupported video * return void when it is loading the audio
2023-08-07 14:02:30 +00:00
({ attachment, timeFormat, index, getCustomEmoji }: IMessageReply) => {
const [loading, setLoading] = useState(false);
const { theme } = useTheme();
const { baseUrl, user, jumpToMessage } = useContext(MessageContext);
if (!attachment) {
return null;
}
2022-03-21 20:44:06 +00:00
const onPress = async () => {
let url = attachment.title_link || attachment.author_link;
if (attachment.message_link) {
return jumpToMessage(attachment.message_link);
}
if (!url) {
return;
}
if (attachment.type === 'file' && attachment.title_link) {
setLoading(true);
url = formatAttachmentUrl(attachment.title_link, user.id, user.token, baseUrl);
await fileDownloadAndPreview(url, attachment);
setLoading(false);
return;
}
openLink(url, theme);
};
2022-03-21 20:44:06 +00:00
let { borderColor } = themes[theme];
if (attachment.color) {
borderColor = attachment.color;
}
return (
<>
{/* The testID is to test properly quoted messages using it as ancestor */}
<Touchable
testID={`reply-${attachment?.author_name}-${attachment?.text}`}
onPress={onPress}
style={[
styles.button,
index > 0 && styles.marginTop,
attachment.description && styles.marginBottom,
{
borderColor
}
]}
background={Touchable.Ripple(themes[theme].bannerBackground)}
disabled={loading}
>
<View style={styles.attachmentContainer}>
<Title attachment={attachment} timeFormat={timeFormat} theme={theme} />
<Description attachment={attachment} getCustomEmoji={getCustomEmoji} theme={theme} />
<UrlImage image={attachment.thumb_url} />
2022-03-21 20:44:06 +00:00
<Attachments
attachments={attachment.attachments}
getCustomEmoji={getCustomEmoji}
timeFormat={timeFormat}
style={[{ color: themes[theme].auxiliaryTintColor, fontSize: 14, marginBottom: 8 }]}
isReply
/>
<Fields attachment={attachment} getCustomEmoji={getCustomEmoji} theme={theme} />
{loading ? (
<View style={[styles.backdrop]}>
<View
style={[
styles.backdrop,
{ backgroundColor: themes[theme].bannerBackground, opacity: themes[theme].attachmentLoadingOpacity }
]}
></View>
<RCActivityIndicator />
</View>
) : null}
</View>
</Touchable>
<Markdown msg={attachment.description} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
</>
);
},
2022-03-21 20:44:06 +00:00
(prevProps, nextProps) => dequal(prevProps.attachment, nextProps.attachment)
);
Reply.displayName = 'MessageReply';
Title.displayName = 'MessageReplyTitle';
Description.displayName = 'MessageReplyDescription';
Fields.displayName = 'MessageReplyFields';
export default Reply;