// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ReactDOM from 'react-dom';
import MsgTyping from './msg_typing.jsx';
import Textbox from './textbox.jsx';
import FileUpload from './file_upload.jsx';
import FilePreview from './file_preview.jsx';
import PostDeletedModal from './post_deleted_modal.jsx';
import TutorialTip from './tutorial/tutorial_tip.jsx';
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
import * as Utils from 'utils/utils.jsx';
import * as UserAgent from 'utils/user_agent.jsx';
import * as ChannelActions from 'actions/channel_actions.jsx';
import * as PostActions from 'actions/post_actions.jsx';
import ChannelStore from 'stores/channel_store.jsx';
import EmojiStore from 'stores/emoji_store.jsx';
import PostStore from 'stores/post_store.jsx';
import MessageHistoryStore from 'stores/message_history_store.jsx';
import UserStore from 'stores/user_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import Constants from 'utils/constants.jsx';
import {FormattedHTMLMessage, FormattedMessage} from 'react-intl';
import {browserHistory} from 'react-router/es6';
const Preferences = Constants.Preferences;
const TutorialSteps = Constants.TutorialSteps;
const ActionTypes = Constants.ActionTypes;
const KeyCodes = Constants.KeyCodes;
import React from 'react';
export const REACTION_PATTERN = /^(\+|-):([^:\s]+):\s*$/;
export default class CreatePost extends React.Component {
constructor(props) {
super(props);
this.lastTime = 0;
this.handleSubmit = this.handleSubmit.bind(this);
this.postMsgKeyPress = this.postMsgKeyPress.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleUploadClick = this.handleUploadClick.bind(this);
this.handleUploadStart = this.handleUploadStart.bind(this);
this.handleFileUploadComplete = this.handleFileUploadComplete.bind(this);
this.handleUploadError = this.handleUploadError.bind(this);
this.removePreview = this.removePreview.bind(this);
this.onChange = this.onChange.bind(this);
this.onPreferenceChange = this.onPreferenceChange.bind(this);
this.getFileCount = this.getFileCount.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.sendMessage = this.sendMessage.bind(this);
this.focusTextbox = this.focusTextbox.bind(this);
this.showPostDeletedModal = this.showPostDeletedModal.bind(this);
this.hidePostDeletedModal = this.hidePostDeletedModal.bind(this);
this.showShortcuts = this.showShortcuts.bind(this);
PostStore.clearDraftUploads();
const draft = PostStore.getCurrentDraft();
this.state = {
channelId: ChannelStore.getCurrentId(),
message: draft.message,
uploadsInProgress: draft.uploadsInProgress,
fileInfos: draft.fileInfos,
submitting: false,
ctrlSend: PreferenceStore.getBool(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter'),
fullWidthTextBox: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT) === Preferences.CHANNEL_DISPLAY_MODE_FULL_SCREEN,
showTutorialTip: false,
showPostDeletedModal: false,
lastBlurAt: 0
};
}
handleSubmit(e) {
e.preventDefault();
if (this.state.uploadsInProgress.length > 0 || this.state.submitting) {
return;
}
const post = {};
post.file_ids = [];
post.message = this.state.message;
if (post.message.trim().length === 0 && this.state.fileInfos.length === 0) {
return;
}
if (this.state.postError) {
this.setState({errorClass: 'animation--highlight'});
setTimeout(() => {
this.setState({errorClass: null});
}, 1000);
return;
}
MessageHistoryStore.storeMessageInHistory(this.state.message);
this.setState({submitting: true, serverError: null});
const isReaction = REACTION_PATTERN.exec(post.message);
if (post.message.indexOf('/') === 0) {
PostStore.storeDraft(this.state.channelId, null);
this.setState({message: '', postError: null, fileInfos: []});
const args = {};
args.channel_id = this.state.channelId;
ChannelActions.executeCommand(
post.message,
args,
(data) => {
this.setState({submitting: false});
if (data.goto_location && data.goto_location.length > 0) {
browserHistory.push(data.goto_location);
}
},
(err) => {
if (err.sendMessage) {
this.sendMessage(post);
} else {
const state = {};
state.serverError = err.message;
state.submitting = false;
this.setState({state});
}
}
);
} else if (isReaction && EmojiStore.has(isReaction[2])) {
this.sendReaction(isReaction);
} else {
this.sendMessage(post);
}
this.setState({message: '', submitting: false, postError: null, fileInfos: [], serverError: null});
const fasterThanHumanWillClick = 150;
const forceFocus = (Date.now() - this.state.lastBlurAt < fasterThanHumanWillClick);
this.focusTextbox(forceFocus);
}
sendMessage(post) {
post.channel_id = this.state.channelId;
post.file_ids = this.state.fileInfos.map((info) => info.id);
const time = Utils.getTimestamp();
const userId = UserStore.getCurrentId();
post.pending_post_id = `${userId}:${time}`;
post.user_id = userId;
post.create_at = time;
post.parent_id = this.state.parentId;
GlobalActions.emitUserPostedEvent(post);
PostActions.queuePost(post, false, null,
(err) => {
if (err.id === 'api.post.create_post.root_id.app_error') {
// this should never actually happen since you can't reply from this textbox
this.showPostDeletedModal();
} else {
this.forceUpdate();
}
this.setState({
submitting: false
});
}
);
}
sendReaction(isReaction) {
const action = isReaction[1];
const emojiName = isReaction[2];
const postId = PostStore.getLatestPost(this.state.channelId).id;
if (action === '+') {
PostActions.addReaction(this.state.channelId, postId, emojiName);
} else if (action === '-') {
PostActions.removeReaction(this.state.channelId, postId, emojiName);
}
PostStore.storeCurrentDraft(null);
}
focusTextbox(keepFocus = false) {
if (keepFocus || !Utils.isMobile()) {
this.refs.textbox.focus();
}
}
postMsgKeyPress(e) {
if (!UserAgent.isMobile() && ((this.state.ctrlSend && e.ctrlKey) || !this.state.ctrlSend)) {
if (e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) {
e.preventDefault();
ReactDOM.findDOMNode(this.refs.textbox).blur();
this.handleSubmit(e);
}
}
GlobalActions.emitLocalUserTypingEvent(this.state.channelId, '');
}
handleChange(e) {
const message = e.target.value;
this.setState({message});
const draft = PostStore.getCurrentDraft();
draft.message = message;
PostStore.storeCurrentDraft(draft);
if (message.length > Constants.CHARACTER_LIMIT) {
const errorMessage = (