// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. var utils = require('../utils/utils.jsx'); var Client = require('../utils/client.jsx'); var Constants = require('../utils/constants.jsx'); export default class FileAttachment extends React.Component { constructor(props) { super(props); this.loadFiles = this.loadFiles.bind(this); this.playGif = this.playGif.bind(this); this.stopGif = this.stopGif.bind(this); this.addBackgroundImage = this.addBackgroundImage.bind(this); this.canSetState = false; this.state = {fileSize: -1, mime: '', playing: false, loading: false, format: ''}; } 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" $('').attr('src', fileInfo.path + '_thumb.jpg?' + utils.getSessionIndex()).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__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)); } } } 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.areStatesEqual(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; } return true; } playGif(e, filename) { var img = new Image(); var fileUrl = utils.getFileUrl(filename); this.setState({loading: true}); img.load(fileUrl); img.onload = () => { var state = {playing: true, loading: false}; switch (true) { case img.width > img.height: state.format = 'landscape'; break; case img.height > img.width: state.format = 'portrait'; break; default: state.format = 'quadrat'; break; } this.setState(state); // keep displaying background image for a short moment while browser is // loading gif, to prevent white background flashing through setTimeout(() => this.removeBackgroundImage.bind(this)(filename), 100); }; img.onError = () => this.setState({loading: false}); e.stopPropagation(); } stopGif(e, filename) { this.setState({playing: false}); this.addBackgroundImage(filename); e.stopPropagation(); } getFileInfoFromName(name) { var fileInfo = utils.splitFileLocation(name); // This is a temporary patch to fix issue with old files using absolute paths if (fileInfo.path.indexOf('/api/v1/files/get') !== -1) { fileInfo.path = fileInfo.path.split('/api/v1/files/get')[1]; } fileInfo.path = utils.getWindowLocationOrigin() + '/api/v1/files/get' + fileInfo.path; return fileInfo; } addBackgroundImage(name, path) { var fileUrl = path; if (name in this.refs) { if (!path) { fileUrl = this.getFileInfoFromName(name).path; } 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'); $(imgDiv).css('background-image', 'url(' + url + '_thumb.jpg?' + utils.getSessionIndex() + ')'); } } removeBackgroundImage(name) { if (name in this.refs) { $(ReactDOM.findDOMNode(this.refs[name])).css('background-image', 'initial'); } } render() { var filename = this.props.filename; var fileInfo = utils.splitFileLocation(filename); var fileUrl = utils.getFileUrl(filename); var type = utils.getFileType(fileInfo.ext); var playbackControls = ''; var loadedFile = ''; var loadingIndicator = ''; if (this.state.mime === 'image/gif') { playbackControls = (