From 5ec7cdfe6a22cc4c05a7865c96664ac885f2fec7 Mon Sep 17 00:00:00 2001 From: OtavioStasiak Date: Wed, 2 Oct 2024 17:59:01 -0300 Subject: [PATCH 1/6] feat: created thumbnail using expo-video-thumbnail --- .../Components/Attachments/Thumbnail.tsx | 86 +++++++++++++++++++ .../message/Components/Attachments/Video.tsx | 36 +------- 2 files changed, 89 insertions(+), 33 deletions(-) create mode 100644 app/containers/message/Components/Attachments/Thumbnail.tsx diff --git a/app/containers/message/Components/Attachments/Thumbnail.tsx b/app/containers/message/Components/Attachments/Thumbnail.tsx new file mode 100644 index 0000000000..e7054b9d93 --- /dev/null +++ b/app/containers/message/Components/Attachments/Thumbnail.tsx @@ -0,0 +1,86 @@ +import React, { useEffect, useState } from 'react'; +import { StyleSheet, View } from 'react-native'; + +import { getThumbnailAsync } from 'expo-video-thumbnails'; +import FastImage from 'react-native-fast-image'; + +import { CustomIcon } from '../../../CustomIcon'; +import OverlayComponent from '../OverlayComponent'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center' + }, + overlay: { + flex: 1 + }, + image: { + width: '100%', + height: '100%' + }, + playerIcon: { + position: 'absolute', + shadowColor: '#000', + shadowOpacity: 0.3, + shadowOffset: { + width: 1, + height: 1 + } + } +}); + +type Image = { + loading: boolean; + uri: string | null; +}; + +type ThumbnailProps = { + url: string; + encrypted?: boolean; +}; + +const Thumbnail = ({ url, encrypted = false }: ThumbnailProps) => { + const icon = encrypted ? 'encrypted' : 'play-filled'; + + const [image, setImage] = useState({ + loading: true, + uri: null + }); + + const generateThumbnail = async () => { + try { + if (!url) return; + + const { uri } = await getThumbnailAsync(url, { + time: 1 + }); + setImage({ + loading: false, + uri + }); + } catch (e) { + console.warn(e); + } + }; + + useEffect(() => { + generateThumbnail(); + }, [url]); + + return ( + + {image.loading || !image.uri ? ( + + ) : ( + <> + + + + )} + + ); +}; + +export default Thumbnail; diff --git a/app/containers/message/Components/Attachments/Video.tsx b/app/containers/message/Components/Attachments/Video.tsx index 23b72e6e46..42cdced03d 100644 --- a/app/containers/message/Components/Attachments/Video.tsx +++ b/app/containers/message/Components/Attachments/Video.tsx @@ -1,5 +1,5 @@ import React, { useContext } from 'react'; -import { StyleProp, StyleSheet, Text, TextStyle, View } from 'react-native'; +import { StyleProp, StyleSheet, TextStyle } from 'react-native'; import { IUserMessage } from '../../../../definitions'; import { IAttachment } from '../../../../definitions/IAttachment'; @@ -9,15 +9,13 @@ import { fileDownload, isIOS } from '../../../../lib/methods/helpers'; import EventEmitter from '../../../../lib/methods/helpers/events'; import { useTheme } from '../../../../theme'; import sharedStyles from '../../../../views/Styles'; -import { TIconsName } from '../../../CustomIcon'; import { LISTENER } from '../../../Toast'; import Markdown from '../../../markdown'; import MessageContext from '../../Context'; import Touchable from '../../Touchable'; import { useMediaAutoDownload } from '../../hooks/useMediaAutoDownload'; -import BlurComponent from '../OverlayComponent'; -import { TDownloadState } from '../../../../lib/methods/handleMediaDownload'; import messageStyles from '../../styles'; +import Thumbnail from './Thumbnail'; const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(isIOS ? [] : ['video/3gp', 'video/mkv'])]; const isTypeSupported = (type: string) => SUPPORTED_TYPES.indexOf(type) !== -1; @@ -44,34 +42,6 @@ interface IMessageVideo { msg?: string; } -const CancelIndicator = () => { - const { colors } = useTheme(); - return ( - - {I18n.t('Cancel')} - - ); -}; - -const Thumbnail = ({ status, encrypted = false }: { status: TDownloadState; encrypted: boolean }) => { - const { colors } = useTheme(); - let icon: TIconsName = status === 'downloaded' ? 'play-filled' : 'arrow-down-circle'; - if (encrypted && status === 'downloaded') { - icon = 'encrypted'; - } - - return ( - <> - - {status === 'loading' ? : null} - - ); -}; - const Video = ({ file, showAttachment, @@ -112,7 +82,7 @@ const Video = ({ <> - + ); From 8c752c1e588869e6db4eed08d479767a6cc5d501 Mon Sep 17 00:00:00 2001 From: OtavioStasiak Date: Thu, 3 Oct 2024 13:28:31 -0300 Subject: [PATCH 2/6] fix: moved Thumbnail component to Video.tsx --- .../Components/Attachments/Thumbnail.tsx | 86 ------------------ .../message/Components/Attachments/Video.tsx | 87 ++++++++++++++++--- 2 files changed, 77 insertions(+), 96 deletions(-) delete mode 100644 app/containers/message/Components/Attachments/Thumbnail.tsx diff --git a/app/containers/message/Components/Attachments/Thumbnail.tsx b/app/containers/message/Components/Attachments/Thumbnail.tsx deleted file mode 100644 index e7054b9d93..0000000000 --- a/app/containers/message/Components/Attachments/Thumbnail.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { StyleSheet, View } from 'react-native'; - -import { getThumbnailAsync } from 'expo-video-thumbnails'; -import FastImage from 'react-native-fast-image'; - -import { CustomIcon } from '../../../CustomIcon'; -import OverlayComponent from '../OverlayComponent'; - -const styles = StyleSheet.create({ - container: { - flex: 1, - alignItems: 'center', - justifyContent: 'center' - }, - overlay: { - flex: 1 - }, - image: { - width: '100%', - height: '100%' - }, - playerIcon: { - position: 'absolute', - shadowColor: '#000', - shadowOpacity: 0.3, - shadowOffset: { - width: 1, - height: 1 - } - } -}); - -type Image = { - loading: boolean; - uri: string | null; -}; - -type ThumbnailProps = { - url: string; - encrypted?: boolean; -}; - -const Thumbnail = ({ url, encrypted = false }: ThumbnailProps) => { - const icon = encrypted ? 'encrypted' : 'play-filled'; - - const [image, setImage] = useState({ - loading: true, - uri: null - }); - - const generateThumbnail = async () => { - try { - if (!url) return; - - const { uri } = await getThumbnailAsync(url, { - time: 1 - }); - setImage({ - loading: false, - uri - }); - } catch (e) { - console.warn(e); - } - }; - - useEffect(() => { - generateThumbnail(); - }, [url]); - - return ( - - {image.loading || !image.uri ? ( - - ) : ( - <> - - - - )} - - ); -}; - -export default Thumbnail; diff --git a/app/containers/message/Components/Attachments/Video.tsx b/app/containers/message/Components/Attachments/Video.tsx index 42cdced03d..c867fe638e 100644 --- a/app/containers/message/Components/Attachments/Video.tsx +++ b/app/containers/message/Components/Attachments/Video.tsx @@ -1,5 +1,5 @@ -import React, { useContext } from 'react'; -import { StyleProp, StyleSheet, TextStyle } from 'react-native'; +import React, { useContext, useEffect, useState } from 'react'; +import { StyleProp, StyleSheet, TextStyle, View } from 'react-native'; import { IUserMessage } from '../../../../definitions'; import { IAttachment } from '../../../../definitions/IAttachment'; @@ -15,23 +15,90 @@ import MessageContext from '../../Context'; import Touchable from '../../Touchable'; import { useMediaAutoDownload } from '../../hooks/useMediaAutoDownload'; import messageStyles from '../../styles'; -import Thumbnail from './Thumbnail'; +import { getThumbnailAsync } from 'expo-video-thumbnails'; +import OverlayComponent from '../OverlayComponent'; +import FastImage from 'react-native-fast-image'; +import { CustomIcon } from '../../../CustomIcon'; const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(isIOS ? [] : ['video/3gp', 'video/mkv'])]; const isTypeSupported = (type: string) => SUPPORTED_TYPES.indexOf(type) !== -1; const styles = StyleSheet.create({ - cancelContainer: { - position: 'absolute', - top: 8, - right: 8 + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center' + }, + overlay: { + flex: 1 + }, + image: { + width: '100%', + height: '100%' }, - text: { - ...sharedStyles.textRegular, - fontSize: 12 + playerIcon: { + position: 'absolute', + shadowColor: '#000', + shadowOpacity: 0.3, + shadowOffset: { + width: 1, + height: 1 + } } }); +type Image = { + loading: boolean; + uri: string | null; +}; + +type ThumbnailProps = { + url: string; + encrypted?: boolean; +}; + +const Thumbnail = ({ url, encrypted = false }: ThumbnailProps) => { + const icon = encrypted ? 'encrypted' : 'play-filled'; + + const [image, setImage] = useState({ + loading: true, + uri: null + }); + + const generateThumbnail = async () => { + try { + if (!url) return; + + const { uri } = await getThumbnailAsync(url, { + time: 1 + }); + setImage({ + loading: false, + uri + }); + } catch (e) { + console.warn(e); + } + }; + + useEffect(() => { + generateThumbnail(); + }, [url]); + + return ( + + {image.loading || !image.uri ? ( + + ) : ( + <> + + + + )} + + ); +}; + interface IMessageVideo { file: IAttachment; showAttachment?: (file: IAttachment) => void; From 1ef73f30ad9a48373a0338188d1b95392e5f599f Mon Sep 17 00:00:00 2001 From: OtavioStasiak Date: Thu, 10 Oct 2024 17:55:21 -0300 Subject: [PATCH 3/6] minor changes --- .../message/Components/Attachments/Video.tsx | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/app/containers/message/Components/Attachments/Video.tsx b/app/containers/message/Components/Attachments/Video.tsx index c867fe638e..e410672ca8 100644 --- a/app/containers/message/Components/Attachments/Video.tsx +++ b/app/containers/message/Components/Attachments/Video.tsx @@ -1,5 +1,7 @@ import React, { useContext, useEffect, useState } from 'react'; import { StyleProp, StyleSheet, TextStyle, View } from 'react-native'; +import FastImage from 'react-native-fast-image'; +import { getThumbnailAsync } from 'expo-video-thumbnails'; import { IUserMessage } from '../../../../definitions'; import { IAttachment } from '../../../../definitions/IAttachment'; @@ -8,17 +10,16 @@ import I18n from '../../../../i18n'; import { fileDownload, isIOS } from '../../../../lib/methods/helpers'; import EventEmitter from '../../../../lib/methods/helpers/events'; import { useTheme } from '../../../../theme'; -import sharedStyles from '../../../../views/Styles'; import { LISTENER } from '../../../Toast'; import Markdown from '../../../markdown'; import MessageContext from '../../Context'; import Touchable from '../../Touchable'; import { useMediaAutoDownload } from '../../hooks/useMediaAutoDownload'; import messageStyles from '../../styles'; -import { getThumbnailAsync } from 'expo-video-thumbnails'; import OverlayComponent from '../OverlayComponent'; -import FastImage from 'react-native-fast-image'; -import { CustomIcon } from '../../../CustomIcon'; +import { CustomIcon, TIconsName } from '../../../CustomIcon'; +import { themes } from '../../../../lib/constants'; +import { TDownloadState } from '../../../../lib/methods/handleMediaDownload'; const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(isIOS ? [] : ['video/3gp', 'video/mkv'])]; const isTypeSupported = (type: string) => SUPPORTED_TYPES.indexOf(type) !== -1; @@ -38,7 +39,7 @@ const styles = StyleSheet.create({ }, playerIcon: { position: 'absolute', - shadowColor: '#000', + shadowColor: themes.light.backdropColor, shadowOpacity: 0.3, shadowOffset: { width: 1, @@ -47,23 +48,23 @@ const styles = StyleSheet.create({ } }); -type Image = { - loading: boolean; - uri: string | null; -}; +type Image = string | null; type ThumbnailProps = { url: string; + status: TDownloadState; encrypted?: boolean; }; -const Thumbnail = ({ url, encrypted = false }: ThumbnailProps) => { - const icon = encrypted ? 'encrypted' : 'play-filled'; +const Thumbnail = ({ url, status, encrypted = false }: ThumbnailProps) => { + const { theme } = useTheme(); + + let icon: TIconsName = status === 'downloaded' ? 'play-filled' : 'arrow-down-circle'; + if (encrypted && status === 'downloaded') { + icon = 'encrypted'; + } - const [image, setImage] = useState({ - loading: true, - uri: null - }); + const [image, setImage] = useState(null); const generateThumbnail = async () => { try { @@ -72,10 +73,7 @@ const Thumbnail = ({ url, encrypted = false }: ThumbnailProps) => { const { uri } = await getThumbnailAsync(url, { time: 1 }); - setImage({ - loading: false, - uri - }); + setImage(uri); } catch (e) { console.warn(e); } @@ -87,12 +85,17 @@ const Thumbnail = ({ url, encrypted = false }: ThumbnailProps) => { return ( - {image.loading || !image.uri ? ( - + {status === 'loading' || !image || encrypted ? ( + ) : ( <> - - + + )} @@ -149,7 +152,7 @@ const Video = ({ <> - + ); From 411d7fffee464347f2c0237bd8a88c10788088e7 Mon Sep 17 00:00:00 2001 From: OtavioStasiak Date: Wed, 16 Oct 2024 12:07:57 -0300 Subject: [PATCH 4/6] fix: useTheme and renamed type --- .../message/Components/Attachments/Video.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/containers/message/Components/Attachments/Video.tsx b/app/containers/message/Components/Attachments/Video.tsx index e410672ca8..a4b8ea6e95 100644 --- a/app/containers/message/Components/Attachments/Video.tsx +++ b/app/containers/message/Components/Attachments/Video.tsx @@ -39,8 +39,6 @@ const styles = StyleSheet.create({ }, playerIcon: { position: 'absolute', - shadowColor: themes.light.backdropColor, - shadowOpacity: 0.3, shadowOffset: { width: 1, height: 1 @@ -48,7 +46,7 @@ const styles = StyleSheet.create({ } }); -type Image = string | null; +type TThumbnailImage = string | null; type ThumbnailProps = { url: string; @@ -64,7 +62,7 @@ const Thumbnail = ({ url, status, encrypted = false }: ThumbnailProps) => { icon = 'encrypted'; } - const [image, setImage] = useState(null); + const [image, setImage] = useState(null); const generateThumbnail = async () => { try { @@ -94,7 +92,10 @@ const Thumbnail = ({ url, status, encrypted = false }: ThumbnailProps) => { name={icon} size={54} color={themes[theme].fontPureWhite} - style={[styles.playerIcon, { shadowColor: themes[theme].backdropColor }]} + style={[ + styles.playerIcon, + { shadowColor: themes[theme].backdropColor, shadowOpacity: themes[theme].backdropOpacity } + ]} /> )} From 78ebf3857ede29ae2a7c04d3ef5f5d8ef3c4f4d0 Mon Sep 17 00:00:00 2001 From: OtavioStasiak Date: Tue, 22 Oct 2024 19:14:12 -0300 Subject: [PATCH 5/6] fix: added elevation in Thumbnail PlayerIcon --- app/containers/message/Components/Attachments/Video.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/containers/message/Components/Attachments/Video.tsx b/app/containers/message/Components/Attachments/Video.tsx index a4b8ea6e95..d68c112c6f 100644 --- a/app/containers/message/Components/Attachments/Video.tsx +++ b/app/containers/message/Components/Attachments/Video.tsx @@ -39,6 +39,7 @@ const styles = StyleSheet.create({ }, playerIcon: { position: 'absolute', + elevation: 4, shadowOffset: { width: 1, height: 1 From 73719091521cdee130a9e28d8780829025d8af96 Mon Sep 17 00:00:00 2001 From: OtavioStasiak Date: Wed, 23 Oct 2024 00:24:41 -0300 Subject: [PATCH 6/6] fix: changed shadow and elevation to textShadow --- .../message/Components/Attachments/Video.tsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/app/containers/message/Components/Attachments/Video.tsx b/app/containers/message/Components/Attachments/Video.tsx index d68c112c6f..201c9b617a 100644 --- a/app/containers/message/Components/Attachments/Video.tsx +++ b/app/containers/message/Components/Attachments/Video.tsx @@ -39,10 +39,10 @@ const styles = StyleSheet.create({ }, playerIcon: { position: 'absolute', - elevation: 4, - shadowOffset: { - width: 1, - height: 1 + textShadowRadius: 3, + textShadowOffset: { + width: 0.5, + height: 0.5 } } }); @@ -93,10 +93,7 @@ const Thumbnail = ({ url, status, encrypted = false }: ThumbnailProps) => { name={icon} size={54} color={themes[theme].fontPureWhite} - style={[ - styles.playerIcon, - { shadowColor: themes[theme].backdropColor, shadowOpacity: themes[theme].backdropOpacity } - ]} + style={[styles.playerIcon, { textShadowColor: themes[theme].backdropColor }]} /> )}