From 6c49c570464c1247a5cf5e5f72a11a716290cc1f Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Mon, 15 May 2023 23:10:14 -0300 Subject: [PATCH] video download and auto download, also keeped the behavior to download unsuportted videos to the gallery --- .../message/Components/BlurComponent.tsx | 9 +- app/containers/message/Image.tsx | 6 +- app/containers/message/Video.tsx | 95 +++++++++++++++++-- app/views/SettingsView/index.tsx | 1 + 4 files changed, 96 insertions(+), 15 deletions(-) diff --git a/app/containers/message/Components/BlurComponent.tsx b/app/containers/message/Components/BlurComponent.tsx index 2683c7549..2f430ed17 100644 --- a/app/containers/message/Components/BlurComponent.tsx +++ b/app/containers/message/Components/BlurComponent.tsx @@ -1,24 +1,23 @@ import React from 'react'; import { BlurView } from '@react-native-community/blur'; -import { View } from 'react-native'; +import { View, ViewStyle } from 'react-native'; -import styles from '../styles'; import RCActivityIndicator from '../../ActivityIndicator'; import { CustomIcon } from '../../CustomIcon'; import { useTheme } from '../../../theme'; -const BlurComponent = ({ loading = false }: { loading: boolean }) => { +const BlurComponent = ({ loading = false, style }: { loading: boolean; style: ViewStyle }) => { const { theme, colors } = useTheme(); return ( <> - + {loading ? : } diff --git a/app/containers/message/Image.tsx b/app/containers/message/Image.tsx index 4344e32e4..1bbf55753 100644 --- a/app/containers/message/Image.tsx +++ b/app/containers/message/Image.tsx @@ -65,7 +65,7 @@ export const MessageImage = React.memo( color: colors.actionTintColor }} /> - {toDownload ? : null} + {toDownload ? : null} ); } @@ -127,8 +127,8 @@ const ImageContainer = React.memo( }; const onPress = () => { - if (loading) { - return downloadResumable.current?.cancelAsync(); + if (loading && downloadResumable.current) { + return downloadResumable.current.cancelAsync(); } if (toDownload && !loading) { diff --git a/app/containers/message/Video.tsx b/app/containers/message/Video.tsx index 2cbdc53a8..31164ba26 100644 --- a/app/containers/message/Video.tsx +++ b/app/containers/message/Video.tsx @@ -1,6 +1,7 @@ -import React, { useContext, useState } from 'react'; -import { StyleProp, StyleSheet, TextStyle } from 'react-native'; +import React, { useContext, useLayoutEffect, useRef, useState } from 'react'; +import { StyleProp, StyleSheet, TextStyle, View, Text } from 'react-native'; import { dequal } from 'dequal'; +import * as FileSystem from 'expo-file-system'; import Touchable from './Touchable'; import Markdown from '../markdown'; @@ -17,6 +18,9 @@ import RCActivityIndicator from '../ActivityIndicator'; import { TGetCustomEmoji } from '../../definitions/IEmoji'; import { useTheme } from '../../theme'; import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl'; +import { MediaTypes, downloadMediaFile, searchMediaFileAsync } from '../../lib/methods/handleMediaDownload'; +import { isAutoDownloadEnabled } from './helpers/mediaDownload/autoDownloadPreference'; +import sharedStyles from '../../views/Styles'; const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(isIOS ? [] : ['video/3gp', 'video/mkv'])]; const isTypeSupported = (type: string) => SUPPORTED_TYPES.indexOf(type) !== -1; @@ -29,6 +33,15 @@ const styles = StyleSheet.create({ marginBottom: 6, alignItems: 'center', justifyContent: 'center' + }, + cancelContainer: { + position: 'absolute', + top: 8, + right: 8 + }, + text: { + ...sharedStyles.textRegular, + fontSize: 12 } }); @@ -38,31 +51,95 @@ interface IMessageVideo { getCustomEmoji: TGetCustomEmoji; style?: StyleProp[]; isReply?: boolean; + messageId: string; } +const DownloadIndicator = ({ handleCancelDownload }: { handleCancelDownload(): void }) => { + const { colors } = useTheme(); + + return ( + <> + + + {I18n.t('Cancel')} + + + + + ); +}; + const Video = React.memo( - ({ file, showAttachment, getCustomEmoji, style, isReply }: IMessageVideo) => { - const { baseUrl, user } = useContext(MessageContext); + ({ file, showAttachment, getCustomEmoji, style, isReply, messageId }: IMessageVideo) => { const [loading, setLoading] = useState(false); + const { baseUrl, user } = useContext(MessageContext); const { theme } = useTheme(); + const filePath = useRef(''); + const downloadResumable = useRef(null); + const video = formatAttachmentUrl(file.video_url, user.id, user.token, baseUrl); + + useLayoutEffect(() => { + const handleAutoDownload = async () => { + if (video) { + const searchImageBestQuality = await searchMediaFileAsync({ + type: MediaTypes.video, + mimeType: file.video_type, + messageId + }); + filePath.current = searchImageBestQuality.filePath; + if (searchImageBestQuality.file?.exists) { + file.video_url = searchImageBestQuality.file.uri; + return; + } + + // We don't pass the author to avoid auto-download what the user sent + const autoDownload = await isAutoDownloadEnabled('imagesPreferenceDownload', { user }); + if (autoDownload) { + await handleDownload(); + } + } + }; + handleAutoDownload(); + }, []); if (!baseUrl) { return null; } + const handleDownload = async () => { + setLoading(true); + downloadResumable.current = FileSystem.createDownloadResumable(video, filePath.current); + const videoUri = await downloadMediaFile({ + url: video, + filePath: filePath.current, + downloadResumable: downloadResumable.current + }); + if (videoUri) { + file.video_url = videoUri; + } + setLoading(false); + }; + const onPress = async () => { if (file.video_type && isTypeSupported(file.video_type) && showAttachment) { + // Keep the video downloading while showing the video buffering + handleDownload(); return showAttachment(file); } if (!isIOS && file.video_url) { - const uri = formatAttachmentUrl(file.video_url, user.id, user.token, baseUrl); - await downloadVideo(uri); + await downloadVideo(video); return; } EventEmitter.emit(LISTENER, { message: I18n.t('Unsupported_format') }); }; + const handleCancelDownload = () => { + if (loading && downloadResumable.current) { + return downloadResumable.current.cancelAsync(); + } + }; + const downloadVideo = async (uri: string) => { setLoading(true); const fileDownloaded = await fileDownload(uri, file); @@ -90,7 +167,11 @@ const Video = React.memo( style={[styles.button, { backgroundColor: themes[theme].videoBackground }]} background={Touchable.Ripple(themes[theme].bannerBackground)} > - {loading ? : } + {loading ? ( + + ) : ( + + )} ); diff --git a/app/views/SettingsView/index.tsx b/app/views/SettingsView/index.tsx index 5f2f9e57d..2ac645cbd 100644 --- a/app/views/SettingsView/index.tsx +++ b/app/views/SettingsView/index.tsx @@ -101,6 +101,7 @@ const SettingsView = (): React.ReactElement => { dispatch(appStart({ root: RootEnum.ROOT_LOADING, text: I18n.t('Clear_cache_loading') })); await deleteAllSpecificMediaFiles(MediaTypes.image, server); await deleteAllSpecificMediaFiles(MediaTypes.audio, server); + await deleteAllSpecificMediaFiles(MediaTypes.video, server); await clearCache({ server }); await FastImage.clearMemoryCache(); await FastImage.clearDiskCache();