Chat.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. 'use strict';
  2. const React = require('react/addons');
  3. const ChatStore = require('../stores/ChatStore');
  4. const ChatActions = require('../actions/ChatActions');
  5. const Chat = React.createClass({
  6. propTypes: {
  7. io: React.PropTypes.object.isRequired,
  8. token: React.PropTypes.string.isRequired,
  9. color: React.PropTypes.oneOf(['white', 'black']).isRequired,
  10. soundsEnabled: React.PropTypes.bool.isRequired,
  11. isOpponentAvailable: React.PropTypes.bool.isRequired,
  12. openModal: React.PropTypes.func.isRequired
  13. },
  14. mixins: [React.addons.PureRenderMixin],
  15. getInitialState() {
  16. const state = ChatStore.getState();
  17. return {
  18. isChatHidden: state.isChatHidden,
  19. messages: state.messages,
  20. message: '',
  21. };
  22. },
  23. componentDidMount() {
  24. this.props.io.on('receive-message', data => {
  25. ChatActions.submitMessage(data.message, data.color + ' left', true);
  26. this._maybePlaySound();
  27. });
  28. ChatStore.on('change', this._onChatStoreChange);
  29. if (window.innerWidth > 1399) ChatActions.toggleVisibility();
  30. },
  31. componentWillUnmount() {
  32. ChatStore.off('change', this._onChatStoreChange);
  33. },
  34. render() {
  35. return (
  36. <div id="chat-wrapper"
  37. style={this.state.isChatHidden ? {display: 'none'} : null}>
  38. <h4>Chat</h4>
  39. <a className="close"
  40. onClick={ChatActions.toggleVisibility}>
  41. x
  42. </a>
  43. <audio preload="auto" ref="msgSnd">
  44. <source src="/snd/message.mp3" />
  45. </audio>
  46. <ul id="chat-list" ref="chat">
  47. {this.state.messages.map((message, i) => (
  48. <li key={i} className={message.get('className')}>
  49. {message.get('message')}
  50. </li>
  51. )).toArray()}
  52. </ul>
  53. <span>Write your message:</span>
  54. <form id="chat-form"
  55. onSubmit={this._submitMessage}>
  56. <input type="text"
  57. ref="message"
  58. className={this.props.color}
  59. required
  60. value={this.state.message}
  61. onChange={this._onChangeMessage} />
  62. </form>
  63. </div>
  64. );
  65. },
  66. _onChatStoreChange() {
  67. this.setState(ChatStore.getState(), this._scrollChat);
  68. },
  69. _onChangeMessage(e) {
  70. this.setState({message: e.target.value});
  71. },
  72. _submitMessage(e) {
  73. e.preventDefault();
  74. const {io, token, color, isOpponentAvailable} = this.props;
  75. const message = this.state.message;
  76. if (!isOpponentAvailable) {
  77. this.refs.message.getDOMNode().blur();
  78. this.props.openModal('info', 'Sorry, your opponent is not connected. ' +
  79. 'You can‘t send messages.');
  80. return;
  81. }
  82. ChatActions.submitMessage(message, color + ' right', false);
  83. this.setState({message: ''});
  84. io.emit('send-message', {
  85. message: message,
  86. color: color,
  87. token: token
  88. });
  89. },
  90. _scrollChat() {
  91. const chatNode = this.refs.chat.getDOMNode();
  92. chatNode.scrollTop = chatNode.scrollHeight;
  93. },
  94. _maybePlaySound() {
  95. if (this.props.soundsEnabled) {
  96. this.refs.msgSnd.getDOMNode().play();
  97. }
  98. }
  99. });
  100. module.exports = Chat;