diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 8caa4b2997c4..f38f281b8939 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -98,6 +98,7 @@ export default { POLICY: 'policy_', REPORT_IS_COMPOSER_FULL_SIZE: 'reportIsComposerFullSize_', POLICY_MEMBER_LIST: 'policyMemberList_', + DOWNLOAD: 'download_', }, // Indicates which locale should be used diff --git a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js index a1abfb0326f3..69e428405d6c 100644 --- a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js +++ b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js @@ -1,11 +1,14 @@ import React from 'react'; import {Pressable} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; import { propTypes as anchorForAttachmentsOnlyPropTypes, defaultProps as anchorForAttachmentsOnlyDefaultProps, } from './anchorForAttachmentsOnlyPropTypes'; +import ONYXKEYS from '../../ONYXKEYS'; import AttachmentView from '../AttachmentView'; +import * as Download from '../../libs/actions/Download'; import fileDownload from '../../libs/fileDownload'; import addEncryptedAuthTokenToURL from '../../libs/addEncryptedAuthTokenToURL'; import {ShowContextMenuContext, showContextMenuForReport} from '../ShowContextMenuContext'; @@ -27,28 +30,13 @@ const defaultProps = { }; class BaseAnchorForAttachmentsOnly extends React.Component { - constructor(props) { - super(props); - - this.state = { - isDownloading: false, - }; - this.processDownload = this.processDownload.bind(this); - } - - /** - * Initiate file downloading and update downloading flags - * - * @param {String} href - * @param {String} fileName - */ - processDownload(href, fileName) { - this.setState({isDownloading: true}); - fileDownload(href, fileName).then(() => this.setState({isDownloading: false})); - } - render() { - const source = addEncryptedAuthTokenToURL(this.props.source); + const sourceURL = this.props.source; + const sourceURLWithAuth = addEncryptedAuthTokenToURL(sourceURL); + const sourceID = (sourceURL.match(/chat-attachments\/(\d+)/) || [])[1]; + const fileName = this.props.displayName; + + const isDownloading = this.props.download && this.props.download.isDownloading; return ( @@ -61,10 +49,11 @@ class BaseAnchorForAttachmentsOnly extends React.Component { { - if (this.state.isDownloading) { + if (isDownloading) { return; } - this.processDownload(source, this.props.displayName); + Download.setDownload(sourceID, true); + fileDownload(sourceURLWithAuth, fileName).then(() => Download.setDownload(sourceID, false)); }} onPressIn={this.props.onPressIn} onPressOut={this.props.onPressOut} @@ -77,10 +66,10 @@ class BaseAnchorForAttachmentsOnly extends React.Component { )} > )} @@ -92,4 +81,11 @@ class BaseAnchorForAttachmentsOnly extends React.Component { BaseAnchorForAttachmentsOnly.propTypes = propTypes; BaseAnchorForAttachmentsOnly.defaultProps = defaultProps; -export default BaseAnchorForAttachmentsOnly; +export default withOnyx({ + download: { + key: ({source}) => { + const sourceID = (source.match(/chat-attachments\/(\d+)/) || [])[1]; + return `${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`; + }, + }, +})(BaseAnchorForAttachmentsOnly); diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 1a6e8d0f5547..aa8f2d58f07a 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -102,6 +102,7 @@ class AuthScreens extends React.Component { App.openApp(); App.setUpPoliciesAndNavigate(this.props.session); + App.clearDownloads(); Timing.end(CONST.TIMING.HOMEPAGE_INITIAL_RENDER); const searchShortcutConfig = CONST.KEYBOARD_SHORTCUTS.SEARCH; diff --git a/src/libs/actions/App.js b/src/libs/actions/App.js index 874b45f1fc57..10d56c5d3bb3 100644 --- a/src/libs/actions/App.js +++ b/src/libs/actions/App.js @@ -168,6 +168,22 @@ function reconnectApp() { }); } +/** + * Clear downloads + */ +function clearDownloads() { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.DOWNLOAD, + waitForCollectionCallback: true, + callback: (records) => { + Onyx.disconnect(connectionID); + const downloads = {}; + _.each(_.keys(records), recordKey => downloads[recordKey] = null); + Onyx.multiSet(downloads); + }, + }); +} + /** * This action runs when the Navigator is ready and the current route changes * @@ -277,4 +293,5 @@ export { openProfile, openApp, reconnectApp, + clearDownloads, }; diff --git a/src/libs/actions/Download.js b/src/libs/actions/Download.js new file mode 100644 index 000000000000..83406e417cbe --- /dev/null +++ b/src/libs/actions/Download.js @@ -0,0 +1,18 @@ +import Onyx from 'react-native-onyx'; +import ONYXKEYS from '../../ONYXKEYS'; + +/** + * Immediate indication whether the an attachment is being downloaded. + * + * @param {String} sourceID + * @param {Boolean} isDownloading + * @returns {Promise} + */ +function setDownload(sourceID, isDownloading) { + return Onyx.merge(`${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`, {isDownloading}); +} + +export { + // eslint-disable-next-line import/prefer-default-export + setDownload, +}; diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js index 9dc44986b595..2b00bc105340 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.js +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js @@ -4,6 +4,7 @@ import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import * as Expensicons from '../../../../components/Icon/Expensicons'; import * as Report from '../../../../libs/actions/Report'; +import * as Download from '../../../../libs/actions/Download'; import Clipboard from '../../../../libs/Clipboard'; import * as ReportUtils from '../../../../libs/ReportUtils'; import ReportActionComposeFocusManager from '../../../../libs/ReportActionComposeFocusManager'; @@ -50,10 +51,11 @@ export default [ const message = _.last(lodashGet(reportAction, 'message', [{}])); const html = lodashGet(message, 'html', ''); const attachmentDetails = getAttachmentDetails(html); - const {originalFileName} = attachmentDetails; - let {sourceURL} = attachmentDetails; - sourceURL = addEncryptedAuthTokenToURL(sourceURL); - fileDownload(sourceURL, originalFileName); + const {originalFileName, sourceURL} = attachmentDetails; + const sourceURLWithAuth = addEncryptedAuthTokenToURL(sourceURL); + const sourceID = (sourceURL.match(/chat-attachments\/(\d+)/) || [])[1]; + Download.setDownload(sourceID, true); + fileDownload(sourceURLWithAuth, originalFileName).then(() => Download.setDownload(sourceID, false)); if (closePopover) { hideContextMenu(true, ReportActionComposeFocusManager.focus); }