From c3d095b465ed87c086409992ef78b62a06c09909 Mon Sep 17 00:00:00 2001
From: bonespiked <dngreene@gmail.com>
Date: Sat, 1 Apr 2017 17:00:30 -0400
Subject: Add reaction picker (#5904)

---
 webapp/components/rhs_comment.jsx | 92 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 86 insertions(+), 6 deletions(-)

(limited to 'webapp/components/rhs_comment.jsx')

diff --git a/webapp/components/rhs_comment.jsx b/webapp/components/rhs_comment.jsx
index 278163bf7..fe0f139fa 100644
--- a/webapp/components/rhs_comment.jsx
+++ b/webapp/components/rhs_comment.jsx
@@ -10,7 +10,7 @@ import ReactionListContainer from 'components/post_view/components/reaction_list
 import RhsDropdown from 'components/rhs_dropdown.jsx';
 
 import * as GlobalActions from 'actions/global_actions.jsx';
-import {flagPost, unflagPost, pinPost, unpinPost} from 'actions/post_actions.jsx';
+import {flagPost, unflagPost, pinPost, unpinPost, addReaction} from 'actions/post_actions.jsx';
 
 import TeamStore from 'stores/team_store.jsx';
 
@@ -19,10 +19,13 @@ import * as PostUtils from 'utils/post_utils.jsx';
 
 import Constants from 'utils/constants.jsx';
 import DelayedAction from 'utils/delayed_action.jsx';
-import {Tooltip, OverlayTrigger} from 'react-bootstrap';
+import {Tooltip, OverlayTrigger, Overlay} from 'react-bootstrap';
 
 import {FormattedMessage} from 'react-intl';
 
+import EmojiPicker from 'components/emoji_picker/emoji_picker.jsx';
+import ReactDOM from 'react-dom';
+
 import loadingGif from 'images/load.gif';
 
 import React from 'react';
@@ -38,6 +41,8 @@ export default class RhsComment extends React.Component {
         this.unflagPost = this.unflagPost.bind(this);
         this.pinPost = this.pinPost.bind(this);
         this.unpinPost = this.unpinPost.bind(this);
+        this.reactEmojiClick = this.reactEmojiClick.bind(this);
+        this.emojiPickerClick = this.emojiPickerClick.bind(this);
 
         this.canEdit = false;
         this.canDelete = false;
@@ -46,7 +51,9 @@ export default class RhsComment extends React.Component {
         this.state = {
             currentTeamDisplayName: TeamStore.getCurrent().name,
             width: '',
-            height: ''
+            height: '',
+            showReactEmojiPicker: false,
+            reactPickerOffset: 15
         };
     }
 
@@ -88,7 +95,7 @@ export default class RhsComment extends React.Component {
         );
     }
 
-    shouldComponentUpdate(nextProps) {
+    shouldComponentUpdate(nextProps, nextState) {
         if (nextProps.status !== this.props.status) {
             return true;
         }
@@ -117,6 +124,10 @@ export default class RhsComment extends React.Component {
             return true;
         }
 
+        if (this.state.showReactEmojiPicker !== nextState.showReactEmojiPicker) {
+            return true;
+        }
+
         return false;
     }
 
@@ -327,11 +338,39 @@ export default class RhsComment extends React.Component {
             );
     }
 
+    emojiPickerClick() {
+        // set default offset
+        let reactOffset = 15;
+        const reactSelectorHeight = 360;
+        const reactionIconY = ReactDOM.findDOMNode(this).getBoundingClientRect().top;
+        const rhsMinHeight = 700;
+
+        const spaceAvail = rhsMinHeight - reactionIconY;
+        if (spaceAvail < reactSelectorHeight) {
+            reactOffset = (spaceAvail - reactSelectorHeight);
+        }
+        this.setState({showReactEmojiPicker: !this.state.showReactEmojiPicker, reactPickerOffset: reactOffset});
+    }
+
+    reactEmojiClick(emoji) {
+        this.setState({showReactEmojiPicker: false});
+        const emojiName = emoji.name || emoji.aliases[0];
+        addReaction(this.props.post.channel_id, this.props.post.id, emojiName);
+    }
+
     render() {
         const post = this.props.post;
         const flagIcon = Constants.FLAG_ICON_SVG;
         const mattermostLogo = Constants.MATTERMOST_ICON_SVG;
         const isSystemMessage = PostUtils.isSystemMessage(post);
+        let canReact = false;
+
+        if (post.state !== Constants.POST_FAILED &&
+            post.state !== Constants.POST_LOADING &&
+            !Utils.isPostEphemeral(post) &&
+            Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMOJI_PICKER_PREVIEW)) {
+            canReact = true;
+        }
 
         var currentUserCss = '';
         if (this.props.currentUser.id === post.user_id) {
@@ -536,6 +575,42 @@ export default class RhsComment extends React.Component {
             );
         }
 
+        let react;
+        let reactOverlay;
+
+        if (canReact) {
+            react = (
+                <span>
+                    <a
+                        href='#'
+                        className='reacticon__container reaction'
+                        onClick={this.emojiPickerClick}
+                        ref={'rhs_reacticon_' + post.id}
+                    ><i className='fa fa-smile-o'/>
+                    </a>
+                </span>
+
+            );
+            reactOverlay = (
+                <Overlay
+                    id={'rhs_react_overlay_' + post.id}
+                    show={this.state.showReactEmojiPicker}
+                    placement='top'
+                    rootClose={true}
+                    container={this.refs['post_body_' + post.id]}
+                    onHide={() => this.setState({showReactEmojiPicker: false})}
+                    target={() => ReactDOM.findDOMNode(this.refs['rhs_reacticon_' + post.id])}
+
+                >
+                    <EmojiPicker
+                        onEmojiClick={this.reactEmojiClick}
+                        pickerLocation='react-rhs-comment'
+                        emojiOffset={this.state.reactPickerOffset}
+                    />
+                </Overlay>
+            );
+        }
+
         let options;
         if (Utils.isPostEphemeral(post)) {
             options = (
@@ -546,7 +621,9 @@ export default class RhsComment extends React.Component {
         } else if (!PostUtils.isSystemMessage(post)) {
             options = (
                 <li className='col col__reply'>
+                    {reactOverlay}
                     {this.createDropdown()}
+                    {react}
                 </li>
             );
         }
@@ -570,7 +647,10 @@ export default class RhsComment extends React.Component {
         };
 
         return (
-            <div className={'post post--thread ' + currentUserCss + ' ' + compactClass + ' ' + systemMessageClass}>
+            <div
+                ref={'post_body_' + post.id}
+                className={'post post--thread ' + currentUserCss + ' ' + compactClass + ' ' + systemMessageClass}
+            >
                 <div className='post__content'>
                     {profilePicContainer}
                     <div>
@@ -586,7 +666,7 @@ export default class RhsComment extends React.Component {
                             </li>
                             {options}
                         </ul>
-                        <div className='post__body'>
+                        <div className='post__body' >
                             <div className={postClass}>
                                 {loading}
                                 <PostMessageContainer post={post}/>
-- 
cgit v1.2.3-1-g7c22

