done for image and audio

This commit is contained in:
Reinaldo Neto 2023-05-19 02:42:21 -03:00
parent aa2c2886a0
commit 02ba6e9961
3 changed files with 102 additions and 58 deletions

View File

@ -124,11 +124,12 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
static contextType = MessageContext; static contextType = MessageContext;
private sound: Sound; private sound: Sound;
private filePath?: string;
constructor(props: IMessageAudioProps) { constructor(props: IMessageAudioProps) {
super(props); super(props);
this.state = { this.state = {
loading: false, loading: true,
currentTime: 0, currentTime: 0,
duration: 0, duration: 0,
paused: true, paused: true,
@ -145,7 +146,29 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
}; };
async componentDidMount() { async componentDidMount() {
this.setState({ loading: true }); const { messageId, file } = this.props;
const fileSearch = await searchMediaFileAsync({
type: MediaTypes.audio,
mimeType: file.audio_type,
messageId
});
this.filePath = fileSearch.filePath;
if (fileSearch?.file?.exists) {
console.log(
'🚀 ~ file: Audio.tsx:157 ~ MessageAudio ~ componentDidMount ~ fileSearch?.file?.exists:',
fileSearch?.file?.exists
);
console.log('🚀 ~ file: Audio.tsx:163 ~ MessageAudio ~ componentDidMount ~ fileSearch.file.uri:', fileSearch.file.uri);
await this.sound
.loadAsync({ uri: fileSearch.file.uri })
.then(value => {
console.log('🚀 ~ file: Audio.tsx:162 ~ MessageAudio ~ awaitthis.sound.loadAsync ~ value:', value);
})
.catch(er => {
console.log('🚀 ~ file: Audio.tsx:158 ~ MessageAudio ~ awaitthis.sound.loadAsync ~ er:', er);
});
return this.setState({ loading: false });
}
await this.handleAutoDownload(); await this.handleAutoDownload();
} }
@ -161,24 +184,14 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
}; };
handleAutoDownload = async () => { handleAutoDownload = async () => {
const { messageId, author, file } = this.props; const { author } = this.props;
const { user } = this.context; const { user } = this.context;
const url = this.getUrl(); const url = this.getUrl();
try { try {
if (url) { if (url) {
const fileSearch = await searchMediaFileAsync({
type: MediaTypes.audio,
mimeType: file.audio_type,
messageId
});
if (fileSearch?.file?.exists) {
await this.sound.loadAsync({ uri: fileSearch.file.uri });
return this.setState({ loading: false });
}
const autoDownload = await isAutoDownloadEnabled('audioPreferenceDownload', { author, user }); const autoDownload = await isAutoDownloadEnabled('audioPreferenceDownload', { author, user });
if (autoDownload) { if (autoDownload) {
await this.startDownload(); return await this.startDownload();
} }
// MediaDownloadOption.NEVER or MediaDownloadOption.WIFI and the mobile is using mobile data // MediaDownloadOption.NEVER or MediaDownloadOption.WIFI and the mobile is using mobile data
@ -190,7 +203,7 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
}; };
shouldComponentUpdate(nextProps: IMessageAudioProps, nextState: IMessageAudioState) { shouldComponentUpdate(nextProps: IMessageAudioProps, nextState: IMessageAudioState) {
const { currentTime, duration, paused, loading } = this.state; const { currentTime, duration, paused, loading, toDownload } = this.state;
const { file, theme } = this.props; const { file, theme } = this.props;
if (nextProps.theme !== theme) { if (nextProps.theme !== theme) {
return true; return true;
@ -210,6 +223,9 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
if (nextState.loading !== loading) { if (nextState.loading !== loading) {
return true; return true;
} }
if (nextState.toDownload !== toDownload) {
return true;
}
return false; return false;
} }
@ -281,23 +297,21 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
}; };
startDownload = async () => { startDownload = async () => {
const { messageId, file } = this.props; const { messageId } = this.props;
const { user } = this.context; const { user } = this.context;
this.setState({ loading: true }); this.setState({ loading: true });
const url = this.getUrl(); const url = this.getUrl();
if (url && this.filePath) {
if (url) {
const fileSearch = await searchMediaFileAsync({
type: MediaTypes.audio,
mimeType: file.audio_type,
messageId
});
const audio = await downloadMediaFile({ const audio = await downloadMediaFile({
url: `${url}?rc_uid=${user.id}&rc_token=${user.token}`, downloadUrl: `${url}?rc_uid=${user.id}&rc_token=${user.token}`,
filePath: fileSearch.filePath mediaType: MediaTypes.audio,
messageId,
path: this.filePath
}); });
await this.sound.loadAsync({ uri: audio }); if (!audio) {
return this.setState({ loading: false, toDownload: true });
}
await this.sound.loadAsync({ uri: this.filePath });
return this.setState({ loading: false, toDownload: false }); return this.setState({ loading: false, toDownload: false });
} }
}; };

View File

@ -4,7 +4,6 @@ import FastImage from 'react-native-fast-image';
import { dequal } from 'dequal'; import { dequal } from 'dequal';
import { createImageProgress } from 'react-native-image-progress'; import { createImageProgress } from 'react-native-image-progress';
import * as Progress from 'react-native-progress'; import * as Progress from 'react-native-progress';
import * as FileSystem from 'expo-file-system';
import { BlurView } from '@react-native-community/blur'; import { BlurView } from '@react-native-community/blur';
import Touchable from './Touchable'; import Touchable from './Touchable';
@ -16,7 +15,13 @@ import { TGetCustomEmoji } from '../../definitions/IEmoji';
import { IAttachment, IUserMessage } from '../../definitions'; import { IAttachment, IUserMessage } from '../../definitions';
import { TSupportedThemes, useTheme } from '../../theme'; import { TSupportedThemes, useTheme } from '../../theme';
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl'; import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
import { MediaTypes, downloadMediaFile, searchMediaFileAsync } from '../../lib/methods/handleMediaDownload'; import {
MediaTypes,
cancelDownload,
downloadMediaFile,
isDownloadActive,
searchMediaFileAsync
} from '../../lib/methods/handleMediaDownload';
import { isAutoDownloadEnabled } from './helpers/mediaDownload/autoDownloadPreference'; import { isAutoDownloadEnabled } from './helpers/mediaDownload/autoDownloadPreference';
import RCActivityIndicator from '../ActivityIndicator'; import RCActivityIndicator from '../ActivityIndicator';
import { CustomIcon } from '../CustomIcon'; import { CustomIcon } from '../CustomIcon';
@ -93,28 +98,35 @@ export const MessageImage = React.memo(
const ImageContainer = React.memo( const ImageContainer = React.memo(
({ file, imageUrl, showAttachment, getCustomEmoji, style, isReply, author, messageId }: IMessageImage) => { ({ file, imageUrl, showAttachment, getCustomEmoji, style, isReply, author, messageId }: IMessageImage) => {
const [newFile, setNewFile] = useState(file);
const [toDownload, setToDownload] = useState(true); const [toDownload, setToDownload] = useState(true);
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 img = imageUrl || formatAttachmentUrl(newFile.image_url, user.id, user.token, baseUrl);
const filePath = useRef(''); const filePath = useRef('');
const downloadResumable = useRef<FileSystem.DownloadResumable | null>(null);
useLayoutEffect(() => { useLayoutEffect(() => {
const handleAutoDownload = async () => { const handleAutoDownload = async () => {
if (img) { if (img) {
const searchImageBestQuality = await searchMediaFileAsync({ const searchImageCached = await searchMediaFileAsync({
type: MediaTypes.image, type: MediaTypes.image,
mimeType: file.image_type, mimeType: newFile.image_type,
messageId messageId
}); });
filePath.current = searchImageBestQuality.filePath; filePath.current = searchImageCached.filePath;
if (searchImageBestQuality.file?.exists) { if (searchImageCached.file?.exists) {
file.title_link = searchImageBestQuality.file.uri; setNewFile(prev => ({
...prev,
title_link: searchImageCached.file?.uri
}));
return setToDownload(false); return setToDownload(false);
} }
if (isDownloadActive(MediaTypes.image, messageId)) {
return setLoading(true);
}
const autoDownload = await isAutoDownloadEnabled('imagesPreferenceDownload', { user, author }); const autoDownload = await isAutoDownloadEnabled('imagesPreferenceDownload', { user, author });
if (autoDownload) { if (autoDownload) {
await handleDownload(); await handleDownload();
@ -130,25 +142,32 @@ const ImageContainer = React.memo(
const handleDownload = async () => { const handleDownload = async () => {
setLoading(true); setLoading(true);
const imgUrl = imageUrl || formatAttachmentUrl(file.title_link || file.image_url, user.id, user.token, baseUrl); // The param file.title_link is the one that point to image with best quality, however we still need to test the imageUrl
downloadResumable.current = FileSystem.createDownloadResumable(imgUrl, filePath.current); // And we don't have sure that 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({
url: imgUrl, downloadUrl: imgUrl,
filePath: filePath.current, mediaType: MediaTypes.image,
downloadResumable: downloadResumable.current messageId,
path: filePath.current
}); });
if (!imageUri) { if (!imageUri) {
setLoading(false); setLoading(false);
return setToDownload(true); return setToDownload(true);
} }
file.title_link = imageUri; setNewFile(prev => ({
...prev,
title_link: filePath.current
}));
setToDownload(false); setToDownload(false);
setLoading(false); setLoading(false);
}; };
const onPress = () => { const onPress = () => {
if (loading && downloadResumable.current) { if (loading && isDownloadActive(MediaTypes.image, messageId)) {
return downloadResumable.current.cancelAsync(); cancelDownload(MediaTypes.image, messageId);
setLoading(false);
return setToDownload(true);
} }
if (toDownload && !loading) { if (toDownload && !loading) {
@ -159,15 +178,15 @@ const ImageContainer = React.memo(
return; return;
} }
return showAttachment(file); return showAttachment(newFile);
}; };
if (file.description) { if (newFile.description) {
return ( return (
<Button disabled={isReply} theme={theme} onPress={onPress}> <Button disabled={isReply} theme={theme} onPress={onPress}>
<View> <View>
<Markdown <Markdown
msg={file.description} msg={newFile.description}
style={[isReply && style]} style={[isReply && style]}
username={user.username} username={user.username}
getCustomEmoji={getCustomEmoji} getCustomEmoji={getCustomEmoji}

View File

@ -56,7 +56,7 @@ export function downloadMediaFile({
messageId: string; messageId: string;
downloadUrl: string; downloadUrl: string;
path: string; path: string;
}): Promise<string | null> { }): Promise<string | void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const downloadKey = mediaDownloadKey(mediaType, messageId); const downloadKey = mediaDownloadKey(mediaType, messageId);
const options = { const options = {
@ -70,20 +70,21 @@ export function downloadMediaFile({
if (response.respInfo.status >= 200 && response.respInfo.status < 400) { if (response.respInfo.status >= 200 && response.respInfo.status < 400) {
// If response is all good... // If response is all good...
try { try {
console.log('🚀 ~ file: handleMediaDownload.ts:71 ~ returnnewPromise ~ response:', response, response.path()); resolve(path);
resolve(response.data);
delete downloadQueue[downloadKey];
} catch (e) { } catch (e) {
reject();
log(e); log(e);
} finally {
delete downloadQueue[downloadKey];
} }
} else { } else {
reject(null); delete downloadQueue[downloadKey];
reject();
} }
}); });
downloadQueue[downloadKey].catch(error => { downloadQueue[downloadKey].catch(() => {
console.log('🚀 ~ file: handleMediaDownload.ts:82 ~ returnnewPromise ~ error:', error);
delete downloadQueue[downloadKey]; delete downloadQueue[downloadKey];
reject(null); reject();
}); });
}); });
} }
@ -96,9 +97,19 @@ const getExtension = (type: MediaTypes, mimeType?: string) => {
if (!mimeType) { if (!mimeType) {
return defaultType[type]; return defaultType[type];
} }
// The library is returning mpag instead of mp3 for audio/mpeg const extensionFromMime = () => {
const extensionFromMime = mimeType === 'audio/mpeg' ? 'mp3' : mime.extension(mimeType); // The library is returning mpag instead of mp3 for audio/mpeg
return extensionFromMime; if (mimeType === 'audio/mpeg') {
return 'mp3';
}
const extension = mime.extension(mimeType);
// The mime.extension can return false when there aren't any extension
if (!extension) {
return defaultType[type];
}
return extension;
};
return extensionFromMime();
}; };
const ensureDirAsync = async (dir: string, intermediates = true): Promise<void> => { const ensureDirAsync = async (dir: string, intermediates = true): Promise<void> => {