You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ChatInput.web.js 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { connect } from 'react-redux';
  4. import { sendMessage } from '../actions';
  5. import SmileysPanel from './SmileysPanel';
  6. /**
  7. * The type of the React {@code Component} props of {@link ChatInput}.
  8. */
  9. type Props = {
  10. /**
  11. * Invoked to send chat messages.
  12. */
  13. dispatch: Dispatch<*>,
  14. /**
  15. * Optional callback to get a reference to the chat input element.
  16. */
  17. getChatInputRef?: Function
  18. };
  19. /**
  20. * The type of the React {@code Component} state of {@link ChatInput}.
  21. */
  22. type State = {
  23. /**
  24. * User provided nickname when the input text is provided in the view.
  25. */
  26. message: string,
  27. /**
  28. * Whether or not the smiley selector is visible.
  29. */
  30. showSmileysPanel: boolean
  31. };
  32. /**
  33. * Implements a React Component for drafting and submitting a chat message.
  34. *
  35. * @extends Component
  36. */
  37. class ChatInput extends Component<Props, State> {
  38. _textArea: ?HTMLTextAreaElement;
  39. state = {
  40. message: '',
  41. showSmileysPanel: false
  42. };
  43. /**
  44. * Initializes a new {@code ChatInput} instance.
  45. *
  46. * @param {Object} props - The read-only properties with which the new
  47. * instance is to be initialized.
  48. */
  49. constructor(props: Props) {
  50. super(props);
  51. this._textArea = null;
  52. // Bind event handlers so they are only bound once for every instance.
  53. this._onDetectSubmit = this._onDetectSubmit.bind(this);
  54. this._onMessageChange = this._onMessageChange.bind(this);
  55. this._onSmileySelect = this._onSmileySelect.bind(this);
  56. this._onToggleSmileysPanel = this._onToggleSmileysPanel.bind(this);
  57. this._setTextAreaRef = this._setTextAreaRef.bind(this);
  58. }
  59. /**
  60. * Implements React's {@link Component#componentDidMount()}.
  61. *
  62. * @inheritdoc
  63. */
  64. componentDidMount() {
  65. /**
  66. * HTML Textareas do not support autofocus. Simulate autofocus by
  67. * manually focusing.
  68. */
  69. this.focus();
  70. }
  71. /**
  72. * Implements React's {@link Component#render()}.
  73. *
  74. * @inheritdoc
  75. * @returns {ReactElement}
  76. */
  77. render() {
  78. const smileysPanelClassName = `${this.state.showSmileysPanel
  79. ? 'show-smileys' : 'hide-smileys'} smileys-panel`;
  80. return (
  81. <div id = 'chat-input' >
  82. <div className = 'smiley-input'>
  83. <div id = 'smileysarea'>
  84. <div id = 'smileys'>
  85. <img
  86. onClick = { this._onToggleSmileysPanel }
  87. src = '../../../../images/smile.svg' />
  88. </div>
  89. </div>
  90. <div className = { smileysPanelClassName }>
  91. <SmileysPanel
  92. onSmileySelect = { this._onSmileySelect } />
  93. </div>
  94. </div>
  95. <div className = 'usrmsg-form'>
  96. <textarea
  97. data-i18n = '[placeholder]chat.messagebox'
  98. id = 'usermsg'
  99. onChange = { this._onMessageChange }
  100. onKeyDown = { this._onDetectSubmit }
  101. placeholder = { 'Enter Text...' }
  102. ref = { this._setTextAreaRef }
  103. value = { this.state.message } />
  104. </div>
  105. </div>
  106. );
  107. }
  108. /**
  109. * Removes cursor focus on this component's text area.
  110. *
  111. * @returns {void}
  112. */
  113. blur() {
  114. this._textArea && this._textArea.blur();
  115. }
  116. /**
  117. * Place cursor focus on this component's text area.
  118. *
  119. * @returns {void}
  120. */
  121. focus() {
  122. this._textArea && this._textArea.focus();
  123. }
  124. _onDetectSubmit: (Object) => void;
  125. /**
  126. * Detects if enter has been pressed. If so, submit the message in the chat
  127. * window.
  128. *
  129. * @param {string} event - Keyboard event.
  130. * @private
  131. * @returns {void}
  132. */
  133. _onDetectSubmit(event) {
  134. if (event.keyCode === 13
  135. && event.shiftKey === false) {
  136. event.preventDefault();
  137. this.props.dispatch(sendMessage(this.state.message));
  138. this.setState({ message: '' });
  139. }
  140. }
  141. _onMessageChange: (Object) => void;
  142. /**
  143. * Updates the known message the user is drafting.
  144. *
  145. * @param {string} event - Keyboard event.
  146. * @private
  147. * @returns {void}
  148. */
  149. _onMessageChange(event) {
  150. this.setState({ message: event.target.value });
  151. }
  152. _onSmileySelect: (string) => void;
  153. /**
  154. * Appends a selected smileys to the chat message draft.
  155. *
  156. * @param {string} smileyText - The value of the smiley to append to the
  157. * chat message.
  158. * @private
  159. * @returns {void}
  160. */
  161. _onSmileySelect(smileyText) {
  162. this.setState({
  163. message: `${this.state.message} ${smileyText}`,
  164. showSmileysPanel: false
  165. });
  166. this.focus();
  167. }
  168. _onToggleSmileysPanel: () => void;
  169. /**
  170. * Callback invoked to hide or show the smileys selector.
  171. *
  172. * @private
  173. * @returns {void}
  174. */
  175. _onToggleSmileysPanel() {
  176. this.setState({ showSmileysPanel: !this.state.showSmileysPanel });
  177. this.focus();
  178. }
  179. _setTextAreaRef: (?HTMLTextAreaElement) => void;
  180. /**
  181. * Sets the reference to the HTML TextArea.
  182. *
  183. * @param {HTMLAudioElement} textAreaElement - The HTML text area element.
  184. * @private
  185. * @returns {void}
  186. */
  187. _setTextAreaRef(textAreaElement: ?HTMLTextAreaElement) {
  188. this._textArea = textAreaElement;
  189. if (this.props.getChatInputRef) {
  190. this.props.getChatInputRef(textAreaElement);
  191. }
  192. }
  193. }
  194. export default connect()(ChatInput);