From 165ad0d4f791f8ae2109472d8a626d911fa368e0 Mon Sep 17 00:00:00 2001
From: Harrison Healey <harrisonmhealey@gmail.com>
Date: Wed, 30 Nov 2016 13:55:49 -0500
Subject: PLT-1378 Initial version of emoji reactions (#4520)

* Refactored emoji.json to support multiple aliases and emoji categories

* Added custom category to emoji.jsx and stabilized all fields

* Removed conflicting aliases for :mattermost: and :ca:

* fixup after store changes

* Added emoji reactions

* Removed reactions for an emoji when that emoji is deleted

* Fixed incorrect test case

* Renamed ReactionList to ReactionListView

* Fixed :+1: and :-1: not showing up as possible reactions

* Removed text emoticons from emoji reaction autocomplete

* Changed emoji reactions to be sorted by the order that they were first created

* Set a maximum number of listeners for the ReactionStore

* Removed unused code from Textbox component

* Fixed reaction permissions

* Changed error code when trying to modify reactions for another user

* Fixed merge conflicts

* Properly applied theme colours to reactions

* Fixed ESLint and gofmt errors

* Fixed ReactionListContainer to properly update when its post prop changes

* Removed unnecessary escape characters from reaction regexes

* Shared reaction message pattern between CreatePost and CreateComment

* Removed an unnecessary select query when saving a reaction

* Changed reactions route to be under /reactions

* Fixed copyright dates on newly added files

* Removed debug code that prevented all unit tests from being ran

* Cleaned up unnecessary code for reactions

* Renamed ReactionStore.List to ReactionStore.GetForPost
---
 webapp/components/create_comment.jsx | 74 ++++++++++++++++++++++++++----------
 1 file changed, 53 insertions(+), 21 deletions(-)

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

diff --git a/webapp/components/create_comment.jsx b/webapp/components/create_comment.jsx
index 2aa85265a..a0a4ddcd2 100644
--- a/webapp/components/create_comment.jsx
+++ b/webapp/components/create_comment.jsx
@@ -5,6 +5,7 @@ import $ from 'jquery';
 import ReactDOM from 'react-dom';
 import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
 import Client from 'client/web_client.jsx';
+import EmojiStore from 'stores/emoji_store.jsx';
 import UserStore from 'stores/user_store.jsx';
 import PostDeletedModal from './post_deleted_modal.jsx';
 import PostStore from 'stores/post_store.jsx';
@@ -17,6 +18,7 @@ import FilePreview from './file_preview.jsx';
 import * as Utils from 'utils/utils.jsx';
 import * as UserAgent from 'utils/user_agent.jsx';
 import * as GlobalActions from 'actions/global_actions.jsx';
+import * as PostActions from 'actions/post_actions.jsx';
 
 import Constants from 'utils/constants.jsx';
 
@@ -25,6 +27,8 @@ import {FormattedMessage} from 'react-intl';
 const ActionTypes = Constants.ActionTypes;
 const KeyCodes = Constants.KeyCodes;
 
+import {REACTION_PATTERN} from './create_post.jsx';
+
 import React from 'react';
 
 export default class CreateComment extends React.Component {
@@ -34,6 +38,8 @@ export default class CreateComment extends React.Component {
         this.lastTime = 0;
 
         this.handleSubmit = this.handleSubmit.bind(this);
+        this.handleSubmitPost = this.handleSubmitPost.bind(this);
+        this.handleSubmitReaction = this.handleSubmitReaction.bind(this);
         this.commentMsgKeyPress = this.commentMsgKeyPress.bind(this);
         this.handleChange = this.handleChange.bind(this);
         this.handleKeyDown = this.handleKeyDown.bind(this);
@@ -100,15 +106,9 @@ export default class CreateComment extends React.Component {
             return;
         }
 
-        const post = {};
-        post.file_ids = [];
-        post.message = this.state.message;
-
-        if (post.message.trim().length === 0 && this.state.fileInfos.length === 0) {
-            return;
-        }
+        const message = this.state.message;
 
-        if (post.message.length > Constants.CHARACTER_LIMIT) {
+        if (message.length > Constants.CHARACTER_LIMIT) {
             this.setState({
                 postError: (
                     <FormattedMessage
@@ -121,15 +121,43 @@ export default class CreateComment extends React.Component {
             return;
         }
 
-        MessageHistoryStore.storeMessageInHistory(this.state.message);
+        MessageHistoryStore.storeMessageInHistory(message);
+
+        if (message.trim().length === 0 && this.state.previews.length === 0) {
+            return;
+        }
+
+        const isReaction = REACTION_PATTERN.exec(message);
+        if (isReaction && EmojiStore.has(isReaction[2])) {
+            this.handleSubmitReaction(isReaction);
+        } else {
+            this.handleSubmitPost(message);
+        }
+
+        this.setState({
+            message: '',
+            submitting: false,
+            postError: null,
+            fileInfos: [],
+            serverError: null
+        });
 
+        const fasterThanHumanWillClick = 150;
+        const forceFocus = (Date.now() - this.state.lastBlurAt < fasterThanHumanWillClick);
+        this.focusTextbox(forceFocus);
+    }
+
+    handleSubmitPost(message) {
         const userId = UserStore.getCurrentId();
+        const time = Utils.getTimestamp();
 
+        const post = {};
+        post.file_ids = [];
+        post.message = message;
         post.channel_id = this.props.channelId;
         post.root_id = this.props.rootId;
         post.parent_id = this.props.rootId;
         post.file_ids = this.state.fileInfos.map((info) => info.id);
-        const time = Utils.getTimestamp();
         post.pending_post_id = `${userId}:${time}`;
         post.user_id = userId;
         post.create_at = time;
@@ -160,18 +188,21 @@ export default class CreateComment extends React.Component {
                 });
             }
         );
+    }
 
-        this.setState({
-            message: '',
-            submitting: false,
-            postError: null,
-            fileInfos: [],
-            serverError: null
-        });
+    handleSubmitReaction(isReaction) {
+        const action = isReaction[1];
 
-        const fasterThanHumanWillClick = 150;
-        const forceFocus = (Date.now() - this.state.lastBlurAt < fasterThanHumanWillClick);
-        this.focusTextbox(forceFocus);
+        const emojiName = isReaction[2];
+        const postId = this.props.latestPostId;
+
+        if (action === '+') {
+            PostActions.addReaction(this.props.channelId, postId, emojiName);
+        } else if (action === '-') {
+            PostActions.removeReaction(this.props.channelId, postId, emojiName);
+        }
+
+        PostStore.storeCommentDraft(this.props.rootId, null);
     }
 
     commentMsgKeyPress(e) {
@@ -455,5 +486,6 @@ export default class CreateComment extends React.Component {
 
 CreateComment.propTypes = {
     channelId: React.PropTypes.string.isRequired,
-    rootId: React.PropTypes.string.isRequired
+    rootId: React.PropTypes.string.isRequired,
+    latestPostId: React.PropTypes.string.isRequired
 };
-- 
cgit v1.2.3-1-g7c22

