message/Image refactored, change the component to show the image from FastImage to Image
This commit is contained in:
parent
6f3dc60994
commit
8c0c1d7dc0
|
@ -3,10 +3,17 @@ import { Image } from 'react-native';
|
||||||
import { FastImageProps } from 'react-native-fast-image';
|
import { FastImageProps } from 'react-native-fast-image';
|
||||||
|
|
||||||
import { types } from './types';
|
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;
|
let Component;
|
||||||
if (type === types.REACT_NATIVE_IMAGE) {
|
if (type === types.REACT_NATIVE_IMAGE || uri.startsWith(LOCAL_DOCUMENT_PATH)) {
|
||||||
const { Image } = require('react-native');
|
const { Image } = require('react-native');
|
||||||
Component = Image;
|
Component = Image;
|
||||||
} else {
|
} else {
|
||||||
|
@ -14,4 +21,4 @@ export const ImageComponent = (type?: string): React.ComponentType<Partial<Image
|
||||||
Component = FastImage;
|
Component = FastImage;
|
||||||
}
|
}
|
||||||
return Component;
|
return Component;
|
||||||
};
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ export const ImageViewer = ({ uri = '', imageComponentType, width, height, ...pr
|
||||||
|
|
||||||
const gesture = Gesture.Simultaneous(pinchGesture, panGesture, doubleTapGesture);
|
const gesture = Gesture.Simultaneous(pinchGesture, panGesture, doubleTapGesture);
|
||||||
|
|
||||||
const Component = ImageComponent(imageComponentType);
|
const Component = ImageComponent({ type: imageComponentType, uri });
|
||||||
|
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,6 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
|
||||||
style={style}
|
style={style}
|
||||||
isReply={isReply}
|
isReply={isReply}
|
||||||
author={author}
|
author={author}
|
||||||
messageId={id}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,27 +2,18 @@ import React, { useContext, useLayoutEffect, useRef, useState } from 'react';
|
||||||
import { StyleProp, TextStyle, View } from 'react-native';
|
import { StyleProp, TextStyle, View } from 'react-native';
|
||||||
import FastImage from 'react-native-fast-image';
|
import FastImage from 'react-native-fast-image';
|
||||||
import { dequal } from 'dequal';
|
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 { BlurView } from '@react-native-community/blur';
|
||||||
|
|
||||||
import Touchable from './Touchable';
|
import Touchable from './Touchable';
|
||||||
import Markdown from '../markdown';
|
import Markdown from '../markdown';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import { themes } from '../../lib/constants';
|
|
||||||
import MessageContext from './Context';
|
import MessageContext from './Context';
|
||||||
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
||||||
import { IAttachment, IUserMessage } from '../../definitions';
|
import { IAttachment, IUserMessage } from '../../definitions';
|
||||||
import { TSupportedThemes, useTheme } from '../../theme';
|
import { useTheme } from '../../theme';
|
||||||
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
|
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
|
||||||
import {
|
import { cancelDownload, downloadMediaFile, isDownloadActive, searchMediaFileAsync } from '../../lib/methods/handleMediaDownload';
|
||||||
MediaTypes,
|
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
|
||||||
cancelDownload,
|
|
||||||
downloadMediaFile,
|
|
||||||
isDownloadActive,
|
|
||||||
searchMediaFileAsync
|
|
||||||
} from '../../lib/methods/handleMediaDownload';
|
|
||||||
import { isAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
|
|
||||||
import RCActivityIndicator from '../ActivityIndicator';
|
import RCActivityIndicator from '../ActivityIndicator';
|
||||||
import { CustomIcon } from '../CustomIcon';
|
import { CustomIcon } from '../CustomIcon';
|
||||||
|
|
||||||
|
@ -30,7 +21,6 @@ interface IMessageButton {
|
||||||
children: React.ReactElement;
|
children: React.ReactElement;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
onPress: () => void;
|
onPress: () => void;
|
||||||
theme: TSupportedThemes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMessageImage {
|
interface IMessageImage {
|
||||||
|
@ -41,25 +31,24 @@ interface IMessageImage {
|
||||||
isReply?: boolean;
|
isReply?: boolean;
|
||||||
getCustomEmoji?: TGetCustomEmoji;
|
getCustomEmoji?: TGetCustomEmoji;
|
||||||
author?: IUserMessage;
|
author?: IUserMessage;
|
||||||
messageId: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImageProgress = createImageProgress(FastImage);
|
const Button = React.memo(({ children, onPress, disabled }: IMessageButton) => {
|
||||||
|
const { colors } = useTheme();
|
||||||
const Button = React.memo(({ children, onPress, disabled, theme }: IMessageButton) => (
|
return (
|
||||||
<Touchable
|
<Touchable
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
style={styles.imageContainer}
|
style={styles.imageContainer}
|
||||||
background={Touchable.Ripple(themes[theme].bannerBackground)}
|
background={Touchable.Ripple(colors.bannerBackground)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Touchable>
|
</Touchable>
|
||||||
));
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const BlurComponent = ({ loading = false }: { loading: boolean }) => {
|
const BlurComponent = ({ loading = false }: { loading: boolean }) => {
|
||||||
const { theme, colors } = useTheme();
|
const { theme, colors } = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<BlurView
|
<BlurView
|
||||||
|
@ -75,136 +64,126 @@ const BlurComponent = ({ loading = false }: { loading: boolean }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MessageImage = React.memo(
|
export const MessageImage = React.memo(({ imgUri, cached, loading }: { imgUri: string; cached: boolean; loading: boolean }) => {
|
||||||
({ imgUri, toDownload, loading }: { imgUri: string; toDownload: boolean; loading: boolean }) => {
|
const { colors } = useTheme();
|
||||||
const { colors } = useTheme();
|
return (
|
||||||
|
<>
|
||||||
return (
|
<FastImage
|
||||||
<>
|
style={[styles.image, { borderColor: colors.borderColor }]}
|
||||||
<ImageProgress
|
source={{ uri: encodeURI(imgUri) }}
|
||||||
style={[styles.image, { borderColor: colors.borderColor }]}
|
resizeMode={FastImage.resizeMode.cover}
|
||||||
source={{ uri: encodeURI(imgUri) }}
|
/>
|
||||||
resizeMode={FastImage.resizeMode.cover}
|
{!cached ? <BlurComponent loading={loading} /> : null}
|
||||||
indicator={Progress.Pie}
|
</>
|
||||||
indicatorProps={{
|
);
|
||||||
color: colors.actionTintColor
|
});
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{toDownload ? <BlurComponent loading={loading} /> : null}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const ImageContainer = React.memo(
|
const ImageContainer = React.memo(
|
||||||
({ file, imageUrl, showAttachment, getCustomEmoji, style, isReply, author, messageId }: IMessageImage) => {
|
({ file, imageUrl, showAttachment, getCustomEmoji, style, isReply, author }: IMessageImage) => {
|
||||||
const [newFile, setNewFile] = useState(file);
|
const [imageCached, setImageCached] = useState(file);
|
||||||
const [toDownload, setToDownload] = useState(true);
|
const [cached, setCached] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
const { baseUrl, user } = useContext(MessageContext);
|
const { baseUrl, user } = useContext(MessageContext);
|
||||||
const img = imageUrl || formatAttachmentUrl(file.image_url, user.id, user.token, baseUrl);
|
|
||||||
const filePath = useRef('');
|
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(() => {
|
useLayoutEffect(() => {
|
||||||
const handleAutoDownload = async () => {
|
const handleImageSearchAndDownload = async () => {
|
||||||
if (img) {
|
if (img) {
|
||||||
const searchImageCached = await searchMediaFileAsync({
|
const searchImageCached = await searchMediaFileAsync({
|
||||||
type: MediaTypes.image,
|
type: 'image',
|
||||||
mimeType: newFile.image_type,
|
mimeType: imageCached.image_type,
|
||||||
messageId
|
urlToCache: imgUrlToCache
|
||||||
});
|
});
|
||||||
filePath.current = searchImageCached.filePath;
|
filePath.current = searchImageCached.filePath;
|
||||||
if (searchImageCached.file?.exists) {
|
if (searchImageCached.file?.exists) {
|
||||||
setNewFile(prev => ({
|
setImageCached(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
title_link: searchImageCached.file?.uri
|
title_link: searchImageCached.file?.uri
|
||||||
}));
|
}));
|
||||||
return setToDownload(false);
|
return setCached(true);
|
||||||
}
|
}
|
||||||
|
if (isDownloadActive('image', imgUrlToCache)) {
|
||||||
if (isDownloadActive(MediaTypes.image, messageId)) {
|
|
||||||
return setLoading(true);
|
return setLoading(true);
|
||||||
}
|
}
|
||||||
|
await handleAutoDownload();
|
||||||
const autoDownload = await isAutoDownloadEnabled('imagesPreferenceDownload', { user, author });
|
|
||||||
if (autoDownload) {
|
|
||||||
await handleDownload();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
handleAutoDownload();
|
handleImageSearchAndDownload();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!img) {
|
if (!img) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleAutoDownload = async () => {
|
||||||
|
const isCurrentUserAuthor = author?._id === user.id;
|
||||||
|
const autoDownload = fetchAutoDownloadEnabled('imagesPreferenceDownload');
|
||||||
|
if (autoDownload || isCurrentUserAuthor) {
|
||||||
|
await handleDownload();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleDownload = async () => {
|
const handleDownload = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
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({
|
const imageUri = await downloadMediaFile({
|
||||||
downloadUrl: imgUrl,
|
downloadUrl: imgUrlToCache,
|
||||||
mediaType: MediaTypes.image,
|
mediaType: 'image',
|
||||||
messageId,
|
|
||||||
path: filePath.current
|
path: filePath.current
|
||||||
});
|
});
|
||||||
|
setImageCached(prev => ({
|
||||||
setNewFile(prev => ({
|
|
||||||
...prev,
|
...prev,
|
||||||
title_link: imageUri
|
title_link: imageUri
|
||||||
}));
|
}));
|
||||||
setToDownload(false);
|
setCached(true);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return setToDownload(true);
|
return setCached(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPress = () => {
|
const onPress = () => {
|
||||||
if (loading && isDownloadActive(MediaTypes.image, messageId)) {
|
if (loading && isDownloadActive('image', imgUrlToCache)) {
|
||||||
cancelDownload(MediaTypes.image, messageId);
|
cancelDownload('image', imgUrlToCache);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return setToDownload(true);
|
return setCached(false);
|
||||||
}
|
}
|
||||||
|
if (!cached && !loading) {
|
||||||
if (toDownload && !loading) {
|
|
||||||
return handleDownload();
|
return handleDownload();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!showAttachment) {
|
if (!showAttachment) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
return showAttachment(imageCached);
|
||||||
return showAttachment(newFile);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (newFile.description) {
|
if (imageCached.description) {
|
||||||
return (
|
return (
|
||||||
<Button disabled={isReply} theme={theme} onPress={onPress}>
|
<Button disabled={isReply} onPress={onPress}>
|
||||||
<View>
|
<View>
|
||||||
<Markdown
|
<Markdown
|
||||||
msg={newFile.description}
|
msg={imageCached.description}
|
||||||
style={[isReply && style]}
|
style={[isReply && style]}
|
||||||
username={user.username}
|
username={user.username}
|
||||||
getCustomEmoji={getCustomEmoji}
|
getCustomEmoji={getCustomEmoji}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
<MessageImage imgUri={img} toDownload={toDownload} loading={loading} />
|
<MessageImage imgUri={img} cached={cached} loading={loading} />
|
||||||
</View>
|
</View>
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button disabled={isReply} theme={theme} onPress={onPress}>
|
<Button disabled={isReply} onPress={onPress}>
|
||||||
<>
|
<MessageImage imgUri={img} cached={cached} loading={loading} />
|
||||||
<MessageImage imgUri={img} toDownload={toDownload} loading={loading} />
|
|
||||||
</>
|
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue