diff options
Diffstat (limited to 'webapp/components/file_attachment.jsx')
-rw-r--r-- | webapp/components/file_attachment.jsx | 251 |
1 files changed, 83 insertions, 168 deletions
diff --git a/webapp/components/file_attachment.jsx b/webapp/components/file_attachment.jsx index cba9d8288..23d8d2446 100644 --- a/webapp/components/file_attachment.jsx +++ b/webapp/components/file_attachment.jsx @@ -1,204 +1,111 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import $ from 'jquery'; -import ReactDOM from 'react-dom'; -import * as utils from 'utils/utils.jsx'; -import Client from 'client/web_client.jsx'; import Constants from 'utils/constants.jsx'; +import FileStore from 'stores/file_store.jsx'; +import * as Utils from 'utils/utils.jsx'; -import {intlShape, injectIntl, defineMessages} from 'react-intl'; import {Tooltip, OverlayTrigger} from 'react-bootstrap'; -const holders = defineMessages({ - download: { - id: 'file_attachment.download', - defaultMessage: 'Download' - } -}); - import React from 'react'; -class FileAttachment extends React.Component { +export default class FileAttachment extends React.Component { constructor(props) { super(props); this.loadFiles = this.loadFiles.bind(this); - this.addBackgroundImage = this.addBackgroundImage.bind(this); this.onAttachmentClick = this.onAttachmentClick.bind(this); - this.canSetState = false; - this.state = {fileSize: -1}; + this.state = { + loaded: Utils.getFileType(props.fileInfo.extension) !== 'image' + }; } + componentDidMount() { this.loadFiles(); } - componentDidUpdate(prevProps) { - if (this.props.filename !== prevProps.filename) { - this.loadFiles(); - } - } - loadFiles() { - this.canSetState = true; - - var filename = this.props.filename; - - if (filename) { - var fileInfo = this.getFileInfoFromName(filename); - var type = utils.getFileType(fileInfo.ext); - - if (type === 'image') { - var self = this; // Need this reference since we use the given "this" - $('<img/>').attr('src', fileInfo.path + '_thumb.jpg').on('load', (function loadWrapper(path, name) { - return function loader() { - $(this).remove(); - if (name in self.refs) { - var imgDiv = ReactDOM.findDOMNode(self.refs[name]); - - $(imgDiv).removeClass('post-image__load'); - $(imgDiv).addClass('post-image'); - - var width = this.width || $(this).width(); - var height = this.height || $(this).height(); - - if (width < Constants.THUMBNAIL_WIDTH && - height < Constants.THUMBNAIL_HEIGHT) { - $(imgDiv).addClass('small'); - } else { - $(imgDiv).addClass('normal'); - } - self.addBackgroundImage(name, path); - } - }; - }(fileInfo.path, filename))); - } + componentWillReceiveProps(nextProps) { + if (nextProps.fileInfo.id !== this.props.fileInfo.id) { + this.setState({ + loaded: Utils.getFileType(nextProps.fileInfo.extension) !== 'image' + }); } } - componentWillUnmount() { - // keep track of when this component is mounted so that we can asynchronously change state without worrying about whether or not we're mounted - this.canSetState = false; - } - shouldComponentUpdate(nextProps, nextState) { - if (!utils.areObjectsEqual(nextProps, this.props)) { - return true; - } - - // the only time this object should update is when it receives an updated file size which we can usually handle without re-rendering - if (nextState.fileSize !== this.state.fileSize) { - if (this.refs.fileSize) { - // update the UI element to display the file size without re-rendering the whole component - ReactDOM.findDOMNode(this.refs.fileSize).innerHTML = utils.fileSizeToString(nextState.fileSize); - return false; - } - - // we can't find the element that should hold the file size so we must not have rendered yet - return true; + componentDidUpdate(prevProps) { + if (!this.state.loaded && this.props.fileInfo.id !== prevProps.fileInfo.id) { + this.loadFiles(); } - - return true; - } - getFileInfoFromName(name) { - var fileInfo = utils.splitFileLocation(name); - - fileInfo.path = Client.getFilesRoute() + '/get' + fileInfo.path; - - return fileInfo; } - addBackgroundImage(name, path) { - var fileUrl = path; - if (name in this.refs) { - if (!path) { - fileUrl = this.getFileInfoFromName(name).path; - } + loadFiles() { + const fileInfo = this.props.fileInfo; + const fileType = Utils.getFileType(fileInfo.extension); - var imgDiv = ReactDOM.findDOMNode(this.refs[name]); - var re1 = new RegExp(' ', 'g'); - var re2 = new RegExp('\\(', 'g'); - var re3 = new RegExp('\\)', 'g'); - var url = fileUrl.replace(re1, '%20').replace(re2, '%28').replace(re3, '%29'); + if (fileType === 'image') { + const thumbnailUrl = FileStore.getFileThumbnailUrl(fileInfo.id); - $(imgDiv).css('background-image', 'url(' + url + '_thumb.jpg)'); - } - } - removeBackgroundImage(name) { - if (name in this.refs) { - $(ReactDOM.findDOMNode(this.refs[name])).css('background-image', 'initial'); + const img = new Image(); + img.onload = () => { + this.setState({loaded: true}); + }; + img.load(thumbnailUrl); } } + onAttachmentClick(e) { e.preventDefault(); this.props.handleImageClick(this.props.index); } + render() { - var filename = this.props.filename; + const fileInfo = this.props.fileInfo; + const fileName = fileInfo.name; + const fileUrl = FileStore.getFileUrl(fileInfo.id); - var fileInfo = utils.splitFileLocation(filename); - var fileUrl = utils.getFileUrl(filename); - var type = utils.getFileType(fileInfo.ext); + let thumbnail; + if (this.state.loaded) { + const type = Utils.getFileType(fileInfo.extension); - var thumbnail; - if (type === 'image') { - thumbnail = ( - <div - ref={filename} - className='post-image__load' - /> - ); - } else { - thumbnail = <div className={'file-icon ' + utils.getIconClassName(type)}/>; - } + if (type === 'image') { + let className = 'post-image'; - var fileSizeString = ''; - if (this.state.fileSize < 0) { - Client.getFileInfo( - filename, - (data) => { - if (this.canSetState) { - this.setState({fileSize: parseInt(data.size, 10)}); - } - }, - () => { - // Do nothing + if (fileInfo.width < Constants.THUMBNAIL_WIDTH && fileInfo.height < Constants.THUMBNAIL_HEIGHT) { + className += ' small'; + } else { + className += ' normal'; } - ); + + thumbnail = ( + <div + className={className} + style={{ + backgroundImage: `url(${FileStore.getFileThumbnailUrl(fileInfo.id)})` + }} + /> + ); + } else { + thumbnail = <div className={'file-icon ' + Utils.getIconClassName(type)}/>; + } } else { - fileSizeString = utils.fileSizeToString(this.state.fileSize); + thumbnail = <div className='post-image__load'/>; } - var filenameString = decodeURIComponent(utils.getFileName(filename)); - var trimmedFilename; - if (filenameString.length > 35) { - trimmedFilename = filenameString.substring(0, Math.min(35, filenameString.length)) + '...'; + let trimmedFilename; + if (fileName.length > 35) { + trimmedFilename = fileName.substring(0, Math.min(35, fileName.length)) + '...'; } else { - trimmedFilename = filenameString; + trimmedFilename = fileName; } - var filenameOverlay = ( - <OverlayTrigger - delayShow={1000} - placement='top' - overlay={<Tooltip id='file-name__tooltip'>{this.props.intl.formatMessage(holders.download) + ' "' + filenameString + '"'}</Tooltip>} - > - <a - href={fileUrl} - download={filenameString} - className='post-image__name' - target='_blank' - rel='noopener noreferrer' - > - {trimmedFilename} - </a> - </OverlayTrigger> - ); + let filenameOverlay; if (this.props.compactDisplay) { filenameOverlay = ( <OverlayTrigger delayShow={1000} placement='top' - overlay={<Tooltip id='file-name__tooltip'>{filenameString}</Tooltip>} + overlay={<Tooltip id='file-name__tooltip'>{fileName}</Tooltip>} > <a href='#' @@ -214,13 +121,28 @@ class FileAttachment extends React.Component { </a> </OverlayTrigger> ); + } else { + filenameOverlay = ( + <OverlayTrigger + delayShow={1000} + placement='top' + overlay={<Tooltip id='file-name__tooltip'>{Utils.localizeMessage('file_attachment.download', 'Download') + ' "' + fileName + '"'}</Tooltip>} + > + <a + href={fileUrl} + download={fileName} + className='post-image__name' + target='_blank' + rel='noopener noreferrer' + > + {trimmedFilename} + </a> + </OverlayTrigger> + ); } return ( - <div - className='post-image__column' - key={filename} - > + <div className='post-image__column'> <a className='post-image__thumbnail' href='#' @@ -233,17 +155,15 @@ class FileAttachment extends React.Component { <div> <a href={fileUrl} - download={filenameString} + download={fileName} className='post-image__download' target='_blank' rel='noopener noreferrer' > - <span - className='fa fa-download' - /> + <span className='fa fa-download'/> </a> - <span className='post-image__type'>{fileInfo.ext.toUpperCase()}</span> - <span className='post-image__size'>{fileSizeString}</span> + <span className='post-image__type'>{fileInfo.extension.toUpperCase()}</span> + <span className='post-image__size'>{Utils.fileSizeToString(fileInfo.size)}</span> </div> </div> </div> @@ -252,10 +172,7 @@ class FileAttachment extends React.Component { } FileAttachment.propTypes = { - intl: intlShape.isRequired, - - // a list of file pathes displayed by the parent FileAttachmentList - filename: React.PropTypes.string.isRequired, + fileInfo: React.PropTypes.object.isRequired, // the index of this attachment preview in the parent FileAttachmentList index: React.PropTypes.number.isRequired, @@ -264,6 +181,4 @@ FileAttachment.propTypes = { handleImageClick: React.PropTypes.func, compactDisplay: React.PropTypes.bool -}; - -export default injectIntl(FileAttachment); +};
\ No newline at end of file |