// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import { PermissionsAndroid, StyleSheet, ToastAndroid, TouchableOpacity, View, } from 'react-native'; import RNFetchBlob from 'rn-fetch-blob'; import {intlShape} from 'react-intl'; import {Client4} from 'mattermost-redux/client'; import {DeviceTypes} from 'app/constants/'; import FormattedText from 'app/components/formatted_text'; import {getLocalFilePathFromFile, isDocument, isVideo} from 'app/utils/file'; import {emptyFunction} from 'app/utils/general'; const {DOCUMENTS_PATH, VIDEOS_PATH} = DeviceTypes; const EXTERNAL_STORAGE_PERMISSION = 'android.permission.WRITE_EXTERNAL_STORAGE'; const HEADER_HEIGHT = 46; const OPTION_LIST_HEIGHT = 39; export default class Downloader extends PureComponent { static propTypes = { file: PropTypes.object.isRequired, onDownloadCancel: PropTypes.func, onDownloadStart: PropTypes.func, onDownloadSuccess: PropTypes.func, show: PropTypes.bool, }; static defaultProps = { onCancelPress: emptyFunction, onDownloadStart: emptyFunction, onDownloadSuccess: emptyFunction, show: false, }; static contextTypes = { intl: intlShape, }; checkForPermissions = async () => { const canWriteToStorage = await PermissionsAndroid.check(EXTERNAL_STORAGE_PERMISSION); if (!canWriteToStorage) { const {intl} = this.context; const description = intl.formatMessage({ id: 'mobile.downloader.android_permission', defaultMessage: 'We need access to the downloads folder to save files.', }); const permissionRequest = await PermissionsAndroid.request(EXTERNAL_STORAGE_PERMISSION, description); return permissionRequest === 'granted'; } return true; }; handleDownload = async () => { const {file, onDownloadCancel, onDownloadStart, onDownloadSuccess} = this.props; const {intl} = this.context; const {data} = file; const canWriteToStorage = await this.checkForPermissions(); if (!canWriteToStorage) { onDownloadCancel(); return; } try { const started = intl.formatMessage({ id: 'mobile.downloader.android_started', defaultMessage: 'Download started', }); const title = intl.formatMessage({ id: 'mobile.downloader.android_success', defaultMessage: 'download successful', }); const complete = intl.formatMessage({ id: 'mobile.downloader.android_complete', defaultMessage: 'Download complete', }); ToastAndroid.show(started, ToastAndroid.SHORT); onDownloadStart(); let dest = `${RNFetchBlob.fs.dirs.DownloadDir}/${data.id}-${file.caption}`; let downloadFile = true; if (data.localPath) { const exists = await RNFetchBlob.fs.exists(data.localPath); if (exists) { downloadFile = false; await RNFetchBlob.fs.cp(data.localPath, dest); } } else if (isVideo(data)) { const path = getLocalFilePathFromFile(VIDEOS_PATH, file); const exists = await RNFetchBlob.fs.exists(path); if (exists) { downloadFile = false; dest = getLocalFilePathFromFile(RNFetchBlob.fs.dirs.DownloadDir, file); await RNFetchBlob.fs.cp(path, dest); } } else if (isDocument(data)) { const path = getLocalFilePathFromFile(DOCUMENTS_PATH, file); const exists = await RNFetchBlob.fs.exists(path); if (exists) { downloadFile = false; await RNFetchBlob.fs.cp(path, dest); } } if (downloadFile) { const imageUrl = Client4.getFileUrl(data.id); const task = RNFetchBlob.config({ fileCache: true, addAndroidDownloads: { useDownloadManager: true, notification: true, path: dest, title: `${file.caption} ${title}`, mime: data.mime_type, description: data.name, mediaScannable: true, }, }).fetch('GET', imageUrl, { Authorization: `Bearer ${Client4.token}`, 'X-Requested-With': 'XMLHttpRequest', }); await task; } ToastAndroid.show(complete, ToastAndroid.SHORT); onDownloadSuccess(); } catch (error) { const failed = intl.formatMessage({ id: 'mobile.downloader.android_failed', defaultMessage: 'Download failed', }); ToastAndroid.show(failed, ToastAndroid.SHORT); onDownloadCancel(); } }; render() { const {show} = this.props; if (!show) { return null; } return ( ); } } const styles = StyleSheet.create({ downloadButton: { flex: 1, justifyContent: 'center', }, downloadButtonText: { color: 'white', fontSize: 15, paddingLeft: 15, }, wrapper: { position: 'absolute', backgroundColor: '#575757', height: OPTION_LIST_HEIGHT, top: HEADER_HEIGHT, right: 0, width: 150, marginRight: 5, }, });