diff options
Diffstat (limited to 'web')
-rw-r--r-- | web/react/components/view_image.jsx | 223 |
1 files changed, 124 insertions, 99 deletions
diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx index 4b2f8f650..dc85b53e5 100644 --- a/web/react/components/view_image.jsx +++ b/web/react/components/view_image.jsx @@ -5,113 +5,143 @@ var Client = require('../utils/client.jsx'); var utils = require('../utils/utils.jsx'); module.exports = React.createClass({ - displayName: "ViewImageModal", + displayName: 'ViewImageModal', canSetState: false, handleNext: function() { var id = this.state.imgId + 1; - if (id > this.props.filenames.length-1) { + if (id > this.props.filenames.length - 1) { id = 0; } - this.setState({ imgId: id }); + this.setState({imgId: id}); this.loadImage(id); }, handlePrev: function() { var id = this.state.imgId - 1; if (id < 0) { - id = this.props.filenames.length-1; + id = this.props.filenames.length - 1; } - this.setState({ imgId: id }); + this.setState({imgId: id}); this.loadImage(id); }, + handleKeyPress: function handleKeyPress(e) { + if (!e) { + return; + } else if (e.keyCode === 39) { + this.handleNext(); + } else if (e.keyCode === 37) { + this.handlePrev(); + } + }, componentWillReceiveProps: function(nextProps) { - this.setState({ imgId: nextProps.startId }); + this.setState({imgId: nextProps.startId}); }, loadImage: function(id) { - var imgHeight = $(window).height()-100; - if (this.state.loaded[id] || this.state.images[id]){ - $('.modal .modal-image .image-wrapper img').css("max-height",imgHeight); + var imgHeight = $(window).height() - 100; + if (this.state.loaded[id] || this.state.images[id]) { + $('.modal .modal-image .image-wrapper img').css('max-height', imgHeight); return; - }; + } var filename = this.props.filenames[id]; var fileInfo = utils.splitFileLocation(filename); var fileType = utils.getFileType(fileInfo.ext); - if (fileType === "image") { + if (fileType === 'image') { var self = this; var img = new Image(); img.load(this.getPreviewImagePath(filename), - function(){ + function() { var progress = self.state.progress; progress[id] = img.completedPercentage; - self.setState({ progress: progress }); - }); + self.setState({progress: progress}); + }); img.onload = function(imgid) { return function() { var loaded = self.state.loaded; loaded[imgid] = true; - self.setState({ loaded: loaded }); - $(self.refs.image.getDOMNode()).css("max-height",imgHeight); + self.setState({loaded: loaded}); + $(self.refs.image.getDOMNode()).css('max-height', imgHeight); }; }(id); var images = this.state.images; images[id] = img; - this.setState({ images: images }); + this.setState({images: images}); } else { // there's nothing to load for non-image files var loaded = this.state.loaded; loaded[id] = true; - this.setState({ loaded: loaded }); + this.setState({loaded: loaded}); } }, componentDidUpdate: function() { if (this.state.loaded[this.state.imgId]) { if (this.refs.imageWrap) { - $(this.refs.imageWrap.getDOMNode()).removeClass("default"); + $(this.refs.imageWrap.getDOMNode()).removeClass('default'); } } }, componentDidMount: function() { var self = this; - $("#"+this.props.modalId).on('shown.bs.modal', function() { - self.setState({ viewed: true }); + $('#' + this.props.modalId).on('shown.bs.modal', function() { + self.setState({viewed: true}); self.loadImage(self.state.imgId); - }) + }); - $(this.refs.modal.getDOMNode()).click(function(e){ - if (e.target == this || e.target == self.refs.imageBody.getDOMNode()) { + $(this.refs.modal.getDOMNode()).click(function(e) { + if (e.target === this || e.target === self.refs.imageBody.getDOMNode()) { $('.image_modal').modal('hide'); } }); $(this.refs.imageWrap.getDOMNode()).hover( function() { - $(self.refs.imageFooter.getDOMNode()).addClass("footer--show"); + $(self.refs.imageFooter.getDOMNode()).addClass('footer--show'); }, function() { - $(self.refs.imageFooter.getDOMNode()).removeClass("footer--show"); + $(self.refs.imageFooter.getDOMNode()).removeClass('footer--show'); } ); + $(window).on('keyup', this.handleKeyPress); + // keep track of whether or not this component is mounted so we can safely set the state asynchronously this.canSetState = true; }, componentWillUnmount: function() { this.canSetState = false; + $(window).off('keyup', this.handleKeyPress); }, - getPublicLink: function(e) { - data = {}; - data["channel_id"] = this.props.channelId; - data["user_id"] = this.props.userId; - data["filename"] = this.props.filenames[this.state.imgId]; + getPublicLink: function() { + var data = {}; + data.channel_id = this.props.channelId; + data.user_id = this.props.userId; + data.filename = this.props.filenames[this.state.imgId]; Client.getPublicLink(data, - function(data) { - window.open(data["public_link"]); - }.bind(this), - function(err) { - }.bind(this) + function(serverData) { + window.open(serverData.public_link); + }, + function() { + } ); }, + getPreviewImagePath: function(filename) { + // Returns the path to a preview image that can be used to represent a file. + var fileInfo = utils.splitFileLocation(filename); + var fileType = utils.getFileType(fileInfo.ext); + + if (fileType === 'image') { + // 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.path + '_preview.jpg'; + } + + // only images have proper previews, so just use a placeholder icon for non-images + return utils.getPreviewImagePathForFileType(fileType); + }, getInitialState: function() { var loaded = []; var progress = []; @@ -119,10 +149,10 @@ module.exports = React.createClass({ loaded.push(false); progress.push(0); } - return { imgId: this.props.startId, viewed: false, loaded: loaded, progress: progress, images: {}, fileSizes: {} }; + return {imgId: this.props.startId, viewed: false, loaded: loaded, progress: progress, images: {}, fileSizes: {}}; }, render: function() { - if (this.props.filenames.length < 1 || this.props.filenames.length-1 < this.state.imgId) { + if (this.props.filenames.length < 1 || this.props.filenames.length - 1 < this.state.imgId) { return <div/>; } @@ -132,34 +162,34 @@ module.exports = React.createClass({ var name = decodeURIComponent(utils.getFileName(filename)); var content; - var bgClass = ""; + var bgClass = ''; if (this.state.loaded[this.state.imgId]) { var fileInfo = utils.splitFileLocation(filename); var fileType = utils.getFileType(fileInfo.ext); - if (fileType === "image") { + if (fileType === 'image') { // image files just show a preview of the file content = ( - <a href={fileUrl} target="_blank"> - <img ref="image" src={this.getPreviewImagePath(filename)}/> + <a href={fileUrl} target='_blank'> + <img ref='image' src={this.getPreviewImagePath(filename)}/> </a> ); } else { // non-image files include a section providing details about the file - var infoString = "File type " + fileInfo.ext.toUpperCase(); + var infoString = 'File type ' + fileInfo.ext.toUpperCase(); if (this.state.fileSizes[filename] && this.state.fileSizes[filename] >= 0) { - infoString += ", Size " + utils.fileSizeToString(this.state.fileSizes[filename]); + infoString += ', Size ' + utils.fileSizeToString(this.state.fileSizes[filename]); } content = ( - <div className="file-details__container"> - <a className={"file-details__preview"} href={fileUrl} target="_blank"> - <span className="file-details__preview-helper" /> - <img ref="image" src={this.getPreviewImagePath(filename)} /> + <div className='file-details__container'> + <a className={'file-details__preview'} href={fileUrl} target='_blank'> + <span className='file-details__preview-helper' /> + <img ref='image' src={this.getPreviewImagePath(filename)} /> </a> - <div className="file-details"> - <div className="file-details__name">{name}</div> - <div className="file-details__info">{infoString}</div> + <div className='file-details'> + <div className='file-details__name'>{name}</div> + <div className='file-details__info'>{infoString}</div> </div> </div> ); @@ -182,68 +212,63 @@ module.exports = React.createClass({ var percentage = Math.floor(this.state.progress[this.state.imgId]); content = ( <div> - <img className="loader-image" src="/static/images/load.gif" /> + <img className='loader-image' src='/static/images/load.gif' /> { percentage > 0 ? - <span className="loader-percent" >{"Previewing " + percentage + "%"}</span> - : ""} + <span className='loader-percent' >{'Previewing ' + percentage + '%'}</span> + : ''} + </div> + ); + bgClass = 'black-bg'; + } + + var publicLink = ''; + if (config.AllowPublicLink) { + publicLink = ( + <div> + <a href='#' className='public-link text' data-title='Public Image' onClick={this.getPublicLink}>Get Public Link</a> + <span className='text'> | </span> </div> ); - bgClass = "black-bg"; + } + + var leftArrow = ''; + var rightArrow = ''; + if (this.props.filenames.length > 1) { + leftArrow = ( + <a className='modal-prev-bar' href='#' onClick={this.handlePrev}> + <i className='image-control image-prev'/> + </a> + ); + + rightArrow = ( + <a className='modal-next-bar' href='#' onClick={this.handleNext}> + <i className='image-control image-next'/> + </a> + ); } return ( - <div className="modal fade image_modal" ref="modal" id={this.props.modalId} tabIndex="-1" role="dialog" aria-hidden="true"> - <div className="modal-dialog modal-image"> - <div className="modal-content image-content"> - <div ref="imageBody" className="modal-body image-body"> - <div ref="imageWrap" className={"image-wrapper default " + bgClass}> - <div className="modal-close" data-dismiss="modal"></div> + <div className='modal fade image_modal' ref='modal' id={this.props.modalId} tabIndex='-1' role='dialog' aria-hidden='true'> + <div className='modal-dialog modal-image'> + <div className='modal-content image-content'> + <div ref='imageBody' className='modal-body image-body'> + <div ref='imageWrap' className={'image-wrapper default ' + bgClass}> + <div className='modal-close' data-dismiss='modal'></div> {content} - <div ref="imageFooter" className="modal-button-bar"> - <span className="pull-left text">{"Image "+(this.state.imgId+1)+" of "+this.props.filenames.length}</span> - <div className="image-links"> - { config.AllowPublicLink ? - <div> - <a href="#" className="public-link text" data-title="Public Image" onClick={this.getPublicLink}>Get Public Link</a> - <span className="text"> | </span> - </div> - : "" } - <a href={fileUrl} download={name} className="text">Download</a> + <div ref='imageFooter' className='modal-button-bar'> + <span className='pull-left text'>{'Image ' + (this.state.imgId + 1) + ' of ' + this.props.filenames.length}</span> + <div className='image-links'> + {publicLink} + <a href={fileUrl} download={name} className='text'>Download</a> </div> </div> </div> - { this.props.filenames.length > 1 ? - <a className="modal-prev-bar" href="#" onClick={this.handlePrev}> - <i className="image-control image-prev"/> - </a> - : "" } - { this.props.filenames.length > 1 ? - <a className="modal-next-bar" href="#" onClick={this.handleNext}> - <i className="image-control image-next"/> - </a> - : "" } + {leftArrow} + {rightArrow} </div> </div> </div> </div> ); - }, - // Returns the path to a preview image that can be used to represent a file. - getPreviewImagePath: function(filename) { - var fileInfo = utils.splitFileLocation(filename); - var fileType = utils.getFileType(fileInfo.ext); - - if (fileType === "image") { - // 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.path + '_preview.jpg'; - } else { - // only images have proper previews, so just use a placeholder icon for non-images - return utils.getPreviewImagePathForFileType(fileType); - } } }); |