diff --git a/app/externalModules.d.ts b/app/externalModules.d.ts index 2634708cb..deee355a7 100644 --- a/app/externalModules.d.ts +++ b/app/externalModules.d.ts @@ -9,5 +9,6 @@ declare module '@rocket.chat/ui-kit'; declare module '@rocket.chat/sdk'; declare module 'react-native-config-reader'; declare module 'react-native-keycommands'; +declare module 'react-native-mime-types'; declare module 'react-native-restart'; declare module 'react-native-prompt-android'; diff --git a/app/presentation/ImageViewer/ImageComponent.ts b/app/presentation/ImageViewer/ImageComponent.ts index 47249811f..68d575775 100644 --- a/app/presentation/ImageViewer/ImageComponent.ts +++ b/app/presentation/ImageViewer/ImageComponent.ts @@ -1,6 +1,10 @@ +import React from 'react'; +import { Image } from 'react-native'; +import { FastImageProps } from '@rocket.chat/react-native-fast-image'; + import { types } from './types'; -export const ImageComponent = (type: string) => { +export const ImageComponent = (type?: string): React.ComponentType | FastImageProps> => { let Component; if (type === types.REACT_NATIVE_IMAGE) { const { Image } = require('react-native'); diff --git a/app/presentation/ImageViewer/ImageViewer.tsx b/app/presentation/ImageViewer/ImageViewer.tsx index a666ee38a..117bf95dd 100644 --- a/app/presentation/ImageViewer/ImageViewer.tsx +++ b/app/presentation/ImageViewer/ImageViewer.tsx @@ -16,13 +16,14 @@ const styles = StyleSheet.create({ interface IImageViewer { uri: string; - imageComponentType: string; + imageComponentType?: string; width: number; height: number; theme: string; + onLoadEnd?: () => void; } -export const ImageViewer = ({ uri, imageComponentType, theme, width, height, ...props }: IImageViewer) => { +export const ImageViewer = ({ uri, imageComponentType, theme, width, height, ...props }: IImageViewer): JSX.Element => { const backgroundColor = themes[theme].previewBackground; const Component = ImageComponent(imageComponentType); return ( diff --git a/app/views/AttachmentView.js b/app/views/AttachmentView.tsx similarity index 76% rename from app/views/AttachmentView.js rename to app/views/AttachmentView.tsx index 8f199b237..90adf8b42 100644 --- a/app/views/AttachmentView.js +++ b/app/views/AttachmentView.tsx @@ -1,12 +1,13 @@ import React from 'react'; import { PermissionsAndroid, StyleSheet, View } from 'react-native'; import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; +import { StackNavigationProp } from '@react-navigation/stack'; +import { RouteProp } from '@react-navigation/native'; import CameraRoll from '@react-native-community/cameraroll'; import * as mime from 'react-native-mime-types'; import RNFetchBlob from 'rn-fetch-blob'; import { Video } from 'expo-av'; -import SHA256 from 'js-sha256'; +import { sha256 } from 'js-sha256'; import { withSafeAreaInsets } from 'react-native-safe-area-context'; import { LISTENER } from '../containers/Toast'; @@ -30,23 +31,41 @@ const styles = StyleSheet.create({ } }); -class AttachmentView extends React.Component { - static propTypes = { - navigation: PropTypes.object, - route: PropTypes.object, - theme: PropTypes.string, - baseUrl: PropTypes.string, - width: PropTypes.number, - height: PropTypes.number, - insets: PropTypes.object, - user: PropTypes.shape({ - id: PropTypes.string, - token: PropTypes.string - }), - Allow_Save_Media_to_Gallery: PropTypes.bool - }; +// TODO: refactor when react-navigation is done +export interface IAttachment { + title: string; + title_link?: string; + image_url?: string; + image_type?: string; + video_url?: string; + video_type?: string; +} - constructor(props) { +interface IAttachmentViewState { + attachment: IAttachment; + loading: boolean; +} + +interface IAttachmentViewProps { + navigation: StackNavigationProp; + route: RouteProp<{ AttachmentView: { attachment: IAttachment } }, 'AttachmentView'>; + theme: string; + baseUrl: string; + width: number; + height: number; + insets: { left: number; bottom: number; right: number; top: number }; + user: { + id: string; + token: string; + }; + Allow_Save_Media_to_Gallery: boolean; +} + +class AttachmentView extends React.Component { + private unsubscribeBlur: (() => void) | undefined; + private videoRef: any; + + constructor(props: IAttachmentViewProps) { super(props); const attachment = props.route.params?.attachment; this.state = { attachment, loading: true }; @@ -79,21 +98,9 @@ class AttachmentView extends React.Component { } const options = { title, - headerLeft: () => ( - - ), + headerLeft: () => , headerRight: () => - Allow_Save_Media_to_Gallery ? ( - - ) : null, + Allow_Save_Media_to_Gallery ? : null, headerBackground: () => , headerTintColor: themes[theme].previewTintColor, headerTitleStyle: { color: themes[theme].previewTintColor, marginHorizontal: 10 } @@ -101,7 +108,7 @@ class AttachmentView extends React.Component { navigation.setOptions(options); }; - getVideoRef = ref => (this.videoRef = ref); + getVideoRef = (ref: Video) => (this.videoRef = ref); handleSave = async () => { const { attachment } = this.state; @@ -113,7 +120,8 @@ class AttachmentView extends React.Component { if (isAndroid) { const rationale = { title: I18n.t('Write_External_Permission'), - message: I18n.t('Write_External_Permission_Message') + message: I18n.t('Write_External_Permission_Message'), + buttonPositive: 'Ok' }; const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, rationale); if (!(result || result === PermissionsAndroid.RESULTS.GRANTED)) { @@ -125,7 +133,7 @@ class AttachmentView extends React.Component { try { const extension = image_url ? `.${mime.extension(image_type) || 'jpg'}` : `.${mime.extension(video_type) || 'mp4'}`; const documentDir = `${RNFetchBlob.fs.dirs.DocumentDir}/`; - const path = `${documentDir + SHA256(url) + extension}`; + const path = `${documentDir + sha256(url!) + extension}`; const file = await RNFetchBlob.config({ path }).fetch('GET', mediaAttachment); await CameraRoll.save(path, { album: 'Rocket.Chat' }); await file.flush(); @@ -136,7 +144,7 @@ class AttachmentView extends React.Component { this.setState({ loading: false }); }; - renderImage = uri => { + renderImage = (uri: string) => { const { theme, width, height, insets } = this.props; const headerHeight = getHeaderHeight(width > height); return ( @@ -150,7 +158,7 @@ class AttachmentView extends React.Component { ); }; - renderVideo = uri => ( + renderVideo = (uri: string) => (