From d167e18f0048344c54685a08c19113a84a995ed9 Mon Sep 17 00:00:00 2001
From: Florian Orben <florian.orben@gmail.com>
Date: Sat, 17 Oct 2015 01:58:34 +0200
Subject: PLT-616: Enable playing of animated GIF in thumbnails and preview

---
 web/react/components/file_attachment.jsx | 53 ++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 3 deletions(-)

(limited to 'web/react/components/file_attachment.jsx')

diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx
index c6dff6550..817834334 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 = (
+                <div
+                    className='file-play-button'
+                    onClick={(e) => this.playGif(e, fileUrl)}
+                >
+                    {"►"}
+                </div>
+            );
+        }
+        if (this.state.playing) {
+            loadedFile = (
+                <img
+                    className='file__loaded'
+                    src={fileUrl}
+                />
+            );
+            playButton = '';
+        }
+        if (this.state.loading) {
+            loadingIndicator = (
+                <img
+                    className='spinner file__loading'
+                    src='/static/images/load.gif'
+                />
+            );
+            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}
+                </div>
             );
         } else {
             thumbnail = <div className={'file-icon ' + utils.getIconClassName(type)}/>;
@@ -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() {}
-- 
cgit v1.2.3-1-g7c22


From 420c754ca300d6f089adc9f22d34a8acb00a571e Mon Sep 17 00:00:00 2001
From: Florian Orben <florian.orben@gmail.com>
Date: Mon, 19 Oct 2015 21:15:10 +0200
Subject: Horizontally align images if image height > image width

---
 web/react/components/file_attachment.jsx | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

(limited to 'web/react/components/file_attachment.jsx')

diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx
index 817834334..afd4e32fe 100644
--- a/web/react/components/file_attachment.jsx
+++ b/web/react/components/file_attachment.jsx
@@ -94,16 +94,28 @@ export default class FileAttachment extends React.Component {
 
         return true;
     }
-    playGif(e, fileUrl) {
+    playGif(e, filename) {
         var img = new Image();
+        var fileUrl = utils.getFileUrl(filename);
 
         this.setState({loading: true});
         img.load(fileUrl);
-        img.onload = () => this.setState({playing: true, loading: false});
+        img.onload = () => {
+            this.setState({playing: true, loading: false});
+
+            // 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();
     }
+    removeBackgroundImage(name) {
+        if (name in this.refs) {
+            $(ReactDOM.findDOMNode(this.refs[name])).css('background-image', 'initial');
+        }
+    }
     render() {
         var filename = this.props.filename;
 
@@ -118,7 +130,7 @@ export default class FileAttachment extends React.Component {
             playButton = (
                 <div
                     className='file-play-button'
-                    onClick={(e) => this.playGif(e, fileUrl)}
+                    onClick={(e) => this.playGif(e, filename)}
                 >
                     {"►"}
                 </div>
-- 
cgit v1.2.3-1-g7c22


From cd5df514c7d3130c9765a8160dfd31abccb8b741 Mon Sep 17 00:00:00 2001
From: Florian Orben <florian.orben@gmail.com>
Date: Mon, 19 Oct 2015 22:30:00 +0200
Subject: Add stop button to stop animated gifs

---
 web/react/components/file_attachment.jsx | 101 ++++++++++++++++++++++---------
 1 file changed, 73 insertions(+), 28 deletions(-)

(limited to 'web/react/components/file_attachment.jsx')

diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx
index afd4e32fe..a88731ca9 100644
--- a/web/react/components/file_attachment.jsx
+++ b/web/react/components/file_attachment.jsx
@@ -11,6 +11,8 @@ export default class FileAttachment extends React.Component {
 
         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};
@@ -29,15 +31,9 @@ export default class FileAttachment extends React.Component {
         var filename = this.props.filename;
 
         if (filename) {
-            var fileInfo = utils.splitFileLocation(filename);
+            var fileInfo = this.getFileInfoFromName(filename);
             var type = utils.getFileType(fileInfo.ext);
 
-            // 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;
-
             if (type === 'image') {
                 var self = this; // Need this reference since we use the given "this"
                 $('<img/>').attr('src', fileInfo.path + '_thumb.jpg').load(function loadWrapper(path, name) {
@@ -59,11 +55,7 @@ export default class FileAttachment extends React.Component {
                                 $(imgDiv).addClass('normal');
                             }
 
-                            var re1 = new RegExp(' ', 'g');
-                            var re2 = new RegExp('\\(', 'g');
-                            var re3 = new RegExp('\\)', 'g');
-                            var url = path.replace(re1, '%20').replace(re2, '%28').replace(re3, '%29');
-                            $(imgDiv).css('background-image', 'url(' + url + '_thumb.jpg)');
+                            self.addBackgroundImage(name, path);
                         }
                     };
                 }(fileInfo.path, filename));
@@ -111,6 +103,39 @@ export default class FileAttachment extends React.Component {
 
         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)');
+        }
+    }
     removeBackgroundImage(name) {
         if (name in this.refs) {
             $(ReactDOM.findDOMNode(this.refs[name])).css('background-image', 'initial');
@@ -123,13 +148,13 @@ export default class FileAttachment extends React.Component {
         var fileUrl = utils.getFileUrl(filename);
         var type = utils.getFileType(fileInfo.ext);
 
-        var playButton = '';
+        var playbackControls = '';
         var loadedFile = '';
         var loadingIndicator = '';
         if (this.state.mime === 'image/gif') {
-            playButton = (
+            playbackControls = (
                 <div
-                    className='file-play-button'
+                    className='file-playback-controls play'
                     onClick={(e) => this.playGif(e, filename)}
                 >
                     {"►"}
@@ -143,7 +168,14 @@ export default class FileAttachment extends React.Component {
                     src={fileUrl}
                 />
             );
-            playButton = '';
+            playbackControls = (
+                <div
+                    className='file-playback-controls stop'
+                    onClick={(e) => this.stopGif(e, filename)}
+                >
+                    {"◼"}
+                </div>
+            );
         }
         if (this.state.loading) {
             loadingIndicator = (
@@ -152,22 +184,35 @@ export default class FileAttachment extends React.Component {
                     src='/static/images/load.gif'
                 />
             );
-            playButton = '';
+            playbackControls = '';
         }
 
         var thumbnail;
         if (type === 'image') {
-            thumbnail = (
-                <div
-                    ref={filename}
-                    className='post__load'
-                    style={{backgroundImage: 'url(/static/images/load.gif)'}}
-                >
-                    {loadingIndicator}
-                    {playButton}
-                    {loadedFile}
-                </div>
-            );
+            if (this.state.playing) {
+                thumbnail = (
+                    <div
+                        ref={filename}
+                        className='post__load'
+                        style={{backgroundImage: 'url(/static/images/load.gif)'}}
+                    >
+                        {playbackControls}
+                        {loadedFile}
+                    </div>
+                );
+            } else {
+                thumbnail = (
+                    <div
+                        ref={filename}
+                        className='post__load'
+                        style={{backgroundImage: 'url(/static/images/load.gif)'}}
+                    >
+                        {loadingIndicator}
+                        {playbackControls}
+                        {loadedFile}
+                    </div>
+                );
+            }
         } else {
             thumbnail = <div className={'file-icon ' + utils.getIconClassName(type)}/>;
         }
-- 
cgit v1.2.3-1-g7c22


From b00697a5009b30eea7e34f340dfdf6b691c4087b Mon Sep 17 00:00:00 2001
From: Florian Orben <florian.orben@gmail.com>
Date: Tue, 20 Oct 2015 20:42:02 +0200
Subject: apply portrait/landscape/quadrat format to playing gif to always
 display it in best possible way

---
 web/react/components/file_attachment.jsx | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

(limited to 'web/react/components/file_attachment.jsx')

diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx
index a88731ca9..a6957b06b 100644
--- a/web/react/components/file_attachment.jsx
+++ b/web/react/components/file_attachment.jsx
@@ -15,7 +15,7 @@ export default class FileAttachment extends React.Component {
         this.addBackgroundImage = this.addBackgroundImage.bind(this);
 
         this.canSetState = false;
-        this.state = {fileSize: -1, mime: '', playing: false, loading: false};
+        this.state = {fileSize: -1, mime: '', playing: false, loading: false, format: ''};
     }
     componentDidMount() {
         this.loadFiles();
@@ -93,7 +93,21 @@ export default class FileAttachment extends React.Component {
         this.setState({loading: true});
         img.load(fileUrl);
         img.onload = () => {
-            this.setState({playing: true, loading: false});
+            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
@@ -164,7 +178,7 @@ export default class FileAttachment extends React.Component {
         if (this.state.playing) {
             loadedFile = (
                 <img
-                    className='file__loaded'
+                    className={'file__loaded ' + this.state.format}
                     src={fileUrl}
                 />
             );
-- 
cgit v1.2.3-1-g7c22


From b9c637ec82d28684029573af119606575f4978d0 Mon Sep 17 00:00:00 2001
From: Florian Orben <florian.orben@gmail.com>
Date: Wed, 21 Oct 2015 18:15:04 +0200
Subject: Change stop symbol to another one since chrome-win can't display it

---
 web/react/components/file_attachment.jsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'web/react/components/file_attachment.jsx')

diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx
index a6957b06b..57cccc4e0 100644
--- a/web/react/components/file_attachment.jsx
+++ b/web/react/components/file_attachment.jsx
@@ -187,7 +187,7 @@ export default class FileAttachment extends React.Component {
                     className='file-playback-controls stop'
                     onClick={(e) => this.stopGif(e, filename)}
                 >
-                    {"◼"}
+                    {"■"}
                 </div>
             );
         }
-- 
cgit v1.2.3-1-g7c22

