GameInterface.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. 'use strict';
  2. const React = require('react/addons');
  3. const GameHeader = require('./GameHeader');
  4. const Chat = require('./Chat');
  5. const Modal = require('./Modal');
  6. const GameActions = require('../actions/GameActions');
  7. const GameStore = require('../stores/GameStore');
  8. const ChessboardInterface = require('./ChessboardInterface');
  9. const Immutable = require('immutable');
  10. const {Map} = Immutable;
  11. const GameInterface = React.createClass({
  12. propTypes: {
  13. io: React.PropTypes.object.isRequired,
  14. params: React.PropTypes.array.isRequired
  15. },
  16. getInitialState() {
  17. return {
  18. color: 'white',
  19. modal: Map({
  20. open: false,
  21. message: '',
  22. type: 'info',
  23. callbacks: {
  24. hide: this._hideModal,
  25. accept: this._acceptRematch,
  26. decline: this._declineRematch
  27. }
  28. }),
  29. soundsEnabled: false,
  30. gameOver: GameStore.getState().gameOver
  31. };
  32. },
  33. componentDidMount() {
  34. const {io, params} = this.props;
  35. io.emit('join', {
  36. token: params[0],
  37. time: params[1] * 60,
  38. inc: params[2]
  39. });
  40. io.on('token-invalid', () => this.setState({
  41. modal: this.state.modal
  42. .set('open', true)
  43. .set('message', 'Game link is invalid or has expired')
  44. .set('type', 'info')
  45. }));
  46. io.on('joined', data => {
  47. if (data.color === 'white') {
  48. io.emit('timer-white', {
  49. token: params[0]
  50. });
  51. } else {
  52. this.setState({color: 'black'});
  53. }
  54. });
  55. io.on('full', () => {
  56. window.alert(
  57. 'This game already has two players. You have to create a new one.');
  58. window.location = '/';
  59. });
  60. io.on('player-resigned', data => {
  61. const winner = data.color === 'black' ? 'White' : 'Black';
  62. const loser = winner === 'Black' ? 'White' : 'Black';
  63. GameActions.gameOver({
  64. type: 'resign',
  65. winner: winner
  66. });
  67. this._openModal('info', `${loser} has resigned. ${winner} wins!`);
  68. });
  69. io.on('rematch-offered', () => {
  70. this._openModal('offer', 'Your opponent has sent you a rematch offer.');
  71. });
  72. io.on('rematch-declined', () => {
  73. this._openModal('info', 'Rematch offer has been declined.');
  74. });
  75. io.on('rematch-confirmed', data => {
  76. GameActions.rematch();
  77. this.setState({
  78. color: this.state.color === 'white' ? 'black' : 'white',
  79. modal: this.state.modal.set('open', false)
  80. }, () => {
  81. if (this.state.color === 'white') {
  82. io.emit('timer-white', {
  83. token: this.props.params[0]
  84. });
  85. }
  86. });
  87. });
  88. GameStore.on('change', this._onGameChange);
  89. },
  90. componentWillUnmount() {
  91. GameStore.off('change', this._onGameChange);
  92. },
  93. render() {
  94. const {io, params} = this.props;
  95. const {color, soundsEnabled, gameOver} = this.state;
  96. return (
  97. <div>
  98. <GameHeader
  99. io={io}
  100. params={params}
  101. color={color}
  102. openModal={this._openModal}
  103. gameOver={gameOver.get('status')} />
  104. <label id="sounds-label">
  105. <input type="checkbox"
  106. checked={soundsEnabled}
  107. onChange={this._toggleSounds} />
  108. <span> Enable sounds</span>
  109. </label>
  110. <Chat
  111. io={io}
  112. token={params[0]}
  113. color={color}
  114. soundsEnabled={soundsEnabled} />
  115. <ChessboardInterface
  116. io={io}
  117. soundsEnabled={soundsEnabled} />
  118. <Modal data={this.state.modal} />
  119. </div>
  120. );
  121. },
  122. _onGameChange() {
  123. this.setState({gameOver: GameStore.getState().gameOver});
  124. },
  125. _openModal(type, message) {
  126. this.setState({
  127. modal: this.state.modal
  128. .set('open', true)
  129. .set('message', message)
  130. .set('type', type)
  131. });
  132. },
  133. _hideModal() {
  134. this.setState({modal: this.state.modal.set('open', false)});
  135. },
  136. _acceptRematch() {
  137. const {io, params} = this.props;
  138. io.emit('rematch-confirm', {
  139. token: params[0],
  140. time: params[1] * 60,
  141. inc: params[2]
  142. });
  143. this._hideModal();
  144. },
  145. _declineRematch() {
  146. const {io, params} = this.props;
  147. io.emit('rematch-decline', {
  148. token: params[0]
  149. });
  150. this._hideModal();
  151. },
  152. _toggleSounds(e) {
  153. this.setState({
  154. soundsEnabled: !this.state.soundsEnabled
  155. });
  156. },
  157. });
  158. module.exports = GameInterface;