diff --git a/api/file.go b/api/file.go index 142ef7ac77..94eea516ad 100644 --- a/api/file.go +++ b/api/file.go @@ -23,6 +23,7 @@ import ( "image/jpeg" "io" "io/ioutil" + "mime" "net/http" "net/url" "os" @@ -331,9 +332,18 @@ func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) { w.Header().Set("Cache-Control", "max-age=2592000, public") + var mimeType string + ext := filepath.Ext(filename) + if model.IsFileExtImage(ext) { + mimeType = model.GetImageMimeType(ext) + } else { + mimeType = mime.TypeByExtension(ext) + } + result := make(map[string]string) result["filename"] = filename result["size"] = size + result["mime"] = mimeType w.Write([]byte(model.MapToJson(result))) } diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index c6dff65507..8178343340 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -10,9 +10,10 @@ export default class FileAttachment extends React.Component { super(props); this.loadFiles = this.loadFiles.bind(this); + this.playGif = this.playGif.bind(this); this.canSetState = false; - this.state = {fileSize: -1}; + this.state = {fileSize: -1, mime: '', playing: false, loading: false}; } componentDidMount() { this.loadFiles(); @@ -93,6 +94,16 @@ export default class FileAttachment extends React.Component { return true; } + playGif(e, fileUrl) { + var img = new Image(); + + this.setState({loading: true}); + img.load(fileUrl); + img.onload = () => this.setState({playing: true, loading: false}); + img.onError = () => this.setState({loading: false}); + + e.stopPropagation(); + } render() { var filename = this.props.filename; @@ -100,6 +111,38 @@ export default class FileAttachment extends React.Component { var fileUrl = utils.getFileUrl(filename); var type = utils.getFileType(fileInfo.ext); + var playButton = ''; + var loadedFile = ''; + var loadingIndicator = ''; + if (this.state.mime === 'image/gif') { + playButton = ( +
+ );
+ playButton = '';
+ }
+
var thumbnail;
if (type === 'image') {
thumbnail = (
@@ -107,7 +150,11 @@ export default class FileAttachment extends React.Component {
ref={filename}
className='post__load'
style={{backgroundImage: 'url(/static/images/load.gif)'}}
- />
+ >
+ {loadingIndicator}
+ {playButton}
+ {loadedFile}
+
);
} else {
thumbnail = ;
@@ -119,7 +166,7 @@ export default class FileAttachment extends React.Component {
filename,
function success(data) {
if (this.canSetState) {
- this.setState({fileSize: parseInt(data.size, 10)});
+ this.setState({fileSize: parseInt(data.size, 10), mime: data.mime});
}
}.bind(this),
function error() {}
diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx
index 322e68c173..c8356b2fa3 100644
--- a/web/react/components/view_image.jsx
+++ b/web/react/components/view_image.jsx
@@ -38,7 +38,10 @@ export default class ViewImageModal extends React.Component {
progress: progress,
images: {},
fileSizes: {},
- showFooter: false
+ fileMimes: {},
+ showFooter: false,
+ isPlaying: {},
+ isLoading: {}
};
}
handleNext(e) {
@@ -122,6 +125,28 @@ export default class ViewImageModal extends React.Component {
this.setState({loaded});
}
}
+ playGif(e, filename, fileUrl) {
+ var isLoading = this.state.isLoading;
+ var isPlaying = this.state.isPlaying;
+
+ isLoading[filename] = fileUrl;
+ this.setState({isLoading});
+
+ var img = new Image();
+ img.load(fileUrl);
+ img.onload = () => {
+ delete isLoading[filename];
+ isPlaying[filename] = fileUrl;
+ this.setState({isPlaying, isLoading});
+ };
+ img.onError = () => {
+ delete isLoading[filename];
+ this.setState({isLoading});
+ };
+
+ e.stopPropagation();
+ e.preventDefault();
+ }
componentDidMount() {
$(window).on('keyup', this.handleKeyPress);
@@ -154,6 +179,10 @@ export default class ViewImageModal extends React.Component {
var fileType = Utils.getFileType(fileInfo.ext);
if (fileType === 'image') {
+ if (typeof this.state.isPlaying[filename] !== 'undefined') {
+ return this.state.isPlaying[filename];
+ }
+
// 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];
@@ -189,12 +218,51 @@ export default class ViewImageModal extends React.Component {
var fileType = Utils.getFileType(fileInfo.ext);
if (fileType === 'image') {
+ if (!(filename in this.state.fileMimes)) {
+ Client.getFileInfo(
+ filename,
+ (data) => {
+ if (this.canSetState) {
+ var fileMimes = this.state.fileMimes;
+ fileMimes[filename] = data.mime;
+ this.setState(fileMimes);
+ }
+ },
+ () => {}
+ );
+ }
+
+ var playButton = '';
+ if (this.state.fileMimes[filename] === 'image/gif' && !(filename in this.state.isLoading) && !(filename in this.state.isPlaying)) {
+ playButton = (
+
+ );
+ playButton = '';
+ }
+
// image files just show a preview of the file
content = (
+ {loadingIndicator}
+ {playButton}