// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import AtMentionProvider from './suggestion/at_mention_provider.jsx'; import CommandProvider from './suggestion/command_provider.jsx'; import EmoticonProvider from './suggestion/emoticon_provider.jsx'; import SuggestionList from './suggestion/suggestion_list.jsx'; import SuggestionBox from './suggestion/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'; import {FormattedMessage} from 'mm-intl'; const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES; export default class Textbox extends React.Component { constructor(props) { super(props); this.focus = this.focus.bind(this); 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.resize = this.resize.bind(this); this.showPreview = this.showPreview.bind(this); this.state = { connection: '' }; this.suggestionProviders = [new AtMentionProvider(), new EmoticonProvider()]; if (props.supportsCommands) { this.suggestionProviders.push(new CommandProvider()); } } 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 errorCount = ErrorStore.getConnectionErrorCount(); if (errorCount > 0) { this.setState({connection: 'bad-connection'}); } else { this.setState({connection: ''}); } } componentDidUpdate() { this.resize(); } handleKeyPress(e) { this.props.onKeyPress(e); } handleKeyDown(e) { if (this.props.onKeyDown) { this.props.onKeyDown(e); } } focus() { this.refs.message.getTextbox().focus(); } resize() { const textbox = this.refs.message.getTextbox(); const $textbox = $(textbox); const $wrapper = $(ReactDOM.findDOMNode(this.refs.wrapper)); const padding = parseInt($textbox.css('padding-bottom'), 10) + parseInt($textbox.css('padding-top'), 10); const borders = parseInt($textbox.css('border-bottom-width'), 10) + parseInt($textbox.css('border-top-width'), 10); const maxHeight = parseInt($textbox.css('max-height'), 10) - borders; // set the height to auto and remove the scrollbar so we can get the actual size of the contents $textbox.css('height', 'auto').css('overflow-y', 'hidden'); let height = textbox.scrollHeight - padding; if (height + padding > maxHeight) { height = maxHeight - padding; // turn scrollbar on and move over attachment icon to compensate for that $textbox.css('overflow-y', 'scroll'); $wrapper.closest('.post-body__cell').addClass('scroll'); } else { $wrapper.closest('.post-body__cell').removeClass('scroll'); } // set the textarea to be the proper height $textbox.height(height); // set the wrapper height to match the height of the textbox including padding and borders $wrapper.height(height + padding + borders); if (this.state.preview) { $(ReactDOM.findDOMNode(this.refs.preview)).height(height + borders); } } showPreview(e) { e.preventDefault(); e.target.blur(); this.setState({preview: !this.state.preview}); this.resize(); } render() { const hasText = this.props.messageText.length > 0; let previewLink = null; if (Utils.isFeatureEnabled(PreReleaseFeatures.MARKDOWN_PREVIEW)) { previewLink = ( {this.state.preview ? ( ) : ( )} ); } let helpText = (
~~ ~~
); return (
{helpText}
{previewLink}
); } } Textbox.defaultProps = { supportsCommands: true }; 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, createMessage: React.PropTypes.string.isRequired, onKeyDown: React.PropTypes.func, supportsCommands: React.PropTypes.bool.isRequired };