// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import CommandList from './command_list.jsx'; import AtMentionProvider from './at_mention_provider.jsx'; import SuggestionList from './suggestion_list.jsx'; import SuggestionBox from './suggestion_box.jsx'; import ErrorStore from '../stores/error_store.jsx'; import * as TextFormatting from '../utils/text_formatting.jsx'; import * as Utils from '../utils/utils.jsx'; import Constants from '../utils/constants.jsx'; const KeyCodes = Constants.KeyCodes; const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES; export default class Textbox extends React.Component { constructor(props) { super(props); this.getStateFromStores = this.getStateFromStores.bind(this); this.onRecievedError = this.onRecievedError.bind(this); this.handleKeyPress = this.handleKeyPress.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.handleBackspace = this.handleBackspace.bind(this); this.addCommand = this.addCommand.bind(this); this.resize = this.resize.bind(this); this.handleFocus = this.handleFocus.bind(this); this.handleBlur = this.handleBlur.bind(this); this.showPreview = this.showPreview.bind(this); this.state = { connection: '' }; this.caret = -1; this.suggestionProviders = [new AtMentionProvider()]; } getStateFromStores() { const error = ErrorStore.getLastError(); if (error) { return {message: error.message}; } return {message: null}; } componentDidMount() { ErrorStore.addChangeListener(this.onRecievedError); this.resize(); } componentWillUnmount() { ErrorStore.removeChangeListener(this.onRecievedError); } onRecievedError() { const errorState = ErrorStore.getLastError(); if (errorState && errorState.connErrorCount > 0) { this.setState({connection: 'bad-connection'}); } else { this.setState({connection: ''}); } } componentDidUpdate() { if (this.caret >= 0) { Utils.setCaretPosition(this.refs.message.getTextbox(), this.caret); this.caret = -1; } this.resize(); } componentWillReceiveProps(nextProps) { this.refs.commands.getSuggestedCommands(nextProps.messageText); } handleKeyPress(e) { const text = this.refs.message.getTextbox().value; if (!this.refs.commands.isEmpty() && text.indexOf('/') === 0 && e.which === KeyCodes.ENTER) { this.refs.commands.addFirstCommand(); e.preventDefault(); return; } this.props.onKeyPress(e); } handleKeyDown(e) { if (e.keyCode === KeyCodes.BACKSPACE) { this.handleBackspace(e); } else if (this.props.onKeyDown) { this.props.onKeyDown(e); } } handleBackspace() { const text = this.refs.message.getTextbox().value; if (text.indexOf('/') === 0) { this.refs.commands.getSuggestedCommands(text.substring(0, text.length - 1)); } } addCommand(cmd) { this.props.onUserInput(cmd); } resize() { const e = this.refs.message.getTextbox(); const w = ReactDOM.findDOMNode(this.refs.wrapper); const prevHeight = $(e).height(); const lht = parseInt($(e).css('lineHeight'), 10); const lines = e.scrollHeight / lht; let mod = 15; if (lines < 2.5 || this.props.messageText === '') { mod = 30; } if (e.scrollHeight - mod < 167) { $(e).css({height: 'auto', 'overflow-y': 'hidden'}).height(e.scrollHeight - mod); $(w).css({height: 'auto'}).height(e.scrollHeight + 2); $(w).closest('.post-body__cell').removeClass('scroll'); if (this.state.preview) { $(ReactDOM.findDOMNode(this.refs.preview)).css({height: 'auto', 'overflow-y': 'auto'}).height(e.scrollHeight - mod); } } else { $(e).css({height: 'auto', 'overflow-y': 'scroll'}).height(167 - mod); $(w).css({height: 'auto'}).height(163); $(w).closest('.post-body__cell').addClass('scroll'); if (this.state.preview) { $(ReactDOM.findDOMNode(this.refs.preview)).css({height: 'auto', 'overflow-y': 'scroll'}).height(163); } } if (prevHeight !== $(e).height() && this.props.onHeightChange) { this.props.onHeightChange(); } } handleFocus() { const elm = this.refs.message.getTextbox(); if (elm.title === elm.value) { elm.value = ''; } } handleBlur() { const elm = this.refs.message.getTextbox(); if (elm.value === '') { elm.value = elm.title; } } showPreview(e) { e.preventDefault(); e.target.blur(); this.setState({preview: !this.state.preview}); this.resize(); } showHelp(e) { e.preventDefault(); e.target.blur(); global.window.open('/docs/Messaging'); } render() { let previewLink = null; if (Utils.isFeatureEnabled(PreReleaseFeatures.MARKDOWN_PREVIEW)) { const previewLinkVisible = this.props.messageText.length > 0; previewLink = ( {this.state.preview ? 'Edit message' : 'Preview'} ); } return (
); } } Textbox.propTypes = { id: React.PropTypes.string.isRequired, channelId: React.PropTypes.string, messageText: React.PropTypes.string.isRequired, onUserInput: React.PropTypes.func.isRequired, onKeyPress: React.PropTypes.func.isRequired, onHeightChange: React.PropTypes.func, createMessage: React.PropTypes.string.isRequired, onKeyDown: React.PropTypes.func };