message/Image refactored, change the component to show the image from FastImage to Image

This commit is contained in:
Reinaldo Neto 2023-06-07 17:14:31 -03:00
parent 6f3dc60994
commit 8c0c1d7dc0
4 changed files with 81 additions and 96 deletions

View File

@ -3,10 +3,17 @@ import { Image } from 'react-native';
import { FastImageProps } from 'react-native-fast-image';
import { types } from './types';
import { LOCAL_DOCUMENT_PATH } from '../../lib/methods/handleMediaDownload';
export const ImageComponent = (type?: string): React.ComponentType<Partial<Image> | FastImageProps> => {
export function ImageComponent({
type,
uri
}: {
type?: string;
uri: string;
}): React.ComponentType<Partial<Image> | FastImageProps> {
let Component;
if (type === types.REACT_NATIVE_IMAGE) {
if (type === types.REACT_NATIVE_IMAGE || uri.startsWith(LOCAL_DOCUMENT_PATH)) {
const { Image } = require('react-native');
Component = Image;
} else {
@ -14,4 +21,4 @@ export const ImageComponent = (type?: string): React.ComponentType<Partial<Image
Component = FastImage;
}
return Component;
};
}

View File

@ -109,7 +109,7 @@ export const ImageViewer = ({ uri = '', imageComponentType, width, height, ...pr
const gesture = Gesture.Simultaneous(pinchGesture, panGesture, doubleTapGesture);
const Component = ImageComponent(imageComponentType);
const Component = ImageComponent({ type: imageComponentType, uri });
const { colors } = useTheme();

View File

@ -72,7 +72,6 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
style={style}
isReply={isReply}
author={author}
messageId={id}
/>
);
}

View File

@ -2,27 +2,18 @@ import React, { useContext, useLayoutEffect, useRef, useState } from 'react';
import { StyleProp, TextStyle, View } from 'react-native';
import FastImage from 'react-native-fast-image';
import { dequal } from 'dequal';
import { createImageProgress } from 'react-native-image-progress';
import * as Progress from 'react-native-progress';
import { BlurView } from '@react-native-community/blur';
import Touchable from './Touchable';
import Markdown from '../markdown';
import styles from './styles';
import { themes } from '../../lib/constants';
import MessageContext from './Context';
import { TGetCustomEmoji } from '../../definitions/IEmoji';
import { IAttachment, IUserMessage } from '../../definitions';
import { TSupportedThemes, useTheme } from '../../theme';
import { useTheme } from '../../theme';
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
import {
MediaTypes,
cancelDownload,
downloadMediaFile,
isDownloadActive,
searchMediaFileAsync
} from '../../lib/methods/handleMediaDownload';
import { isAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
import { cancelDownload, downloadMediaFile, isDownloadActive, searchMediaFileAsync } from '../../lib/methods/handleMediaDownload';
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
import RCActivityIndicator from '../ActivityIndicator';
import { CustomIcon } from '../CustomIcon';
@ -30,7 +21,6 @@ interface IMessageButton {
children: React.ReactElement;
disabled?: boolean;
onPress: () => void;
theme: TSupportedThemes;
}
interface IMessageImage {
@ -41,25 +31,24 @@ interface IMessageImage {
isReply?: boolean;
getCustomEmoji?: TGetCustomEmoji;
author?: IUserMessage;
messageId: string;
}
const ImageProgress = createImageProgress(FastImage);
const Button = React.memo(({ children, onPress, disabled, theme }: IMessageButton) => (
const Button = React.memo(({ children, onPress, disabled }: IMessageButton) => {
const { colors } = useTheme();
return (
<Touchable
disabled={disabled}
onPress={onPress}
style={styles.imageContainer}
background={Touchable.Ripple(themes[theme].bannerBackground)}
background={Touchable.Ripple(colors.bannerBackground)}
>
{children}
</Touchable>
));
);
});
const BlurComponent = ({ loading = false }: { loading: boolean }) => {
const { theme, colors } = useTheme();
return (
<>
<BlurView
@ -75,136 +64,126 @@ const BlurComponent = ({ loading = false }: { loading: boolean }) => {
);
};
export const MessageImage = React.memo(
({ imgUri, toDownload, loading }: { imgUri: string; toDownload: boolean; loading: boolean }) => {
export const MessageImage = React.memo(({ imgUri, cached, loading }: { imgUri: string; cached: boolean; loading: boolean }) => {
const { colors } = useTheme();
return (
<>
<ImageProgress
<FastImage
style={[styles.image, { borderColor: colors.borderColor }]}
source={{ uri: encodeURI(imgUri) }}
resizeMode={FastImage.resizeMode.cover}
indicator={Progress.Pie}
indicatorProps={{
color: colors.actionTintColor
}}
/>
{toDownload ? <BlurComponent loading={loading} /> : null}
{!cached ? <BlurComponent loading={loading} /> : null}
</>
);
}
);
});
const ImageContainer = React.memo(
({ file, imageUrl, showAttachment, getCustomEmoji, style, isReply, author, messageId }: IMessageImage) => {
const [newFile, setNewFile] = useState(file);
const [toDownload, setToDownload] = useState(true);
({ file, imageUrl, showAttachment, getCustomEmoji, style, isReply, author }: IMessageImage) => {
const [imageCached, setImageCached] = useState(file);
const [cached, setCached] = useState(false);
const [loading, setLoading] = useState(false);
const { theme } = useTheme();
const { baseUrl, user } = useContext(MessageContext);
const img = imageUrl || formatAttachmentUrl(file.image_url, user.id, user.token, baseUrl);
const filePath = useRef('');
const getUrl = (link?: string) => imageUrl || formatAttachmentUrl(link, user.id, user.token, baseUrl);
const img = getUrl(file.image_url);
// The param file.title_link is the one that point to image with best quality, however we still need to test the imageUrl
// And we cannot be certain whether the file.title_link actually exists.
const imgUrlToCache = getUrl(imageCached.title_link || imageCached.image_url);
useLayoutEffect(() => {
const handleAutoDownload = async () => {
const handleImageSearchAndDownload = async () => {
if (img) {
const searchImageCached = await searchMediaFileAsync({
type: MediaTypes.image,
mimeType: newFile.image_type,
messageId
type: 'image',
mimeType: imageCached.image_type,
urlToCache: imgUrlToCache
});
filePath.current = searchImageCached.filePath;
if (searchImageCached.file?.exists) {
setNewFile(prev => ({
setImageCached(prev => ({
...prev,
title_link: searchImageCached.file?.uri
}));
return setToDownload(false);
return setCached(true);
}
if (isDownloadActive(MediaTypes.image, messageId)) {
if (isDownloadActive('image', imgUrlToCache)) {
return setLoading(true);
}
const autoDownload = await isAutoDownloadEnabled('imagesPreferenceDownload', { user, author });
if (autoDownload) {
await handleDownload();
}
await handleAutoDownload();
}
};
handleAutoDownload();
handleImageSearchAndDownload();
}, []);
if (!img) {
return null;
}
const handleAutoDownload = async () => {
const isCurrentUserAuthor = author?._id === user.id;
const autoDownload = fetchAutoDownloadEnabled('imagesPreferenceDownload');
if (autoDownload || isCurrentUserAuthor) {
await handleDownload();
}
};
const handleDownload = async () => {
setLoading(true);
try {
// The param file.title_link is the one that point to image with best quality, however we still need to test the imageUrl
// And we don't have sure that ever exists the file.title_link
const imgUrl = imageUrl || formatAttachmentUrl(newFile.title_link || newFile.image_url, user.id, user.token, baseUrl);
const imageUri = await downloadMediaFile({
downloadUrl: imgUrl,
mediaType: MediaTypes.image,
messageId,
downloadUrl: imgUrlToCache,
mediaType: 'image',
path: filePath.current
});
setNewFile(prev => ({
setImageCached(prev => ({
...prev,
title_link: imageUri
}));
setToDownload(false);
setCached(true);
setLoading(false);
} catch (e) {
setLoading(false);
return setToDownload(true);
return setCached(false);
}
};
const onPress = () => {
if (loading && isDownloadActive(MediaTypes.image, messageId)) {
cancelDownload(MediaTypes.image, messageId);
if (loading && isDownloadActive('image', imgUrlToCache)) {
cancelDownload('image', imgUrlToCache);
setLoading(false);
return setToDownload(true);
return setCached(false);
}
if (toDownload && !loading) {
if (!cached && !loading) {
return handleDownload();
}
if (!showAttachment) {
return;
}
return showAttachment(newFile);
return showAttachment(imageCached);
};
if (newFile.description) {
if (imageCached.description) {
return (
<Button disabled={isReply} theme={theme} onPress={onPress}>
<Button disabled={isReply} onPress={onPress}>
<View>
<Markdown
msg={newFile.description}
msg={imageCached.description}
style={[isReply && style]}
username={user.username}
getCustomEmoji={getCustomEmoji}
theme={theme}
/>
<MessageImage imgUri={img} toDownload={toDownload} loading={loading} />
<MessageImage imgUri={img} cached={cached} loading={loading} />
</View>
</Button>
);
}
return (
<Button disabled={isReply} theme={theme} onPress={onPress}>
<>
<MessageImage imgUri={img} toDownload={toDownload} loading={loading} />
</>
<Button disabled={isReply} onPress={onPress}>
<MessageImage imgUri={img} cached={cached} loading={loading} />
</Button>
);
},