|
|
|
import React from 'react';
|
|
|
|
import { connect } from 'react-redux';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { withRoomContext } from '../RoomContext';
|
|
|
|
import * as requestActions from '../redux/requestActions';
|
|
|
|
|
|
|
|
const BotMessageRegex = new RegExp('^@bot (.*)');
|
|
|
|
|
|
|
|
class ChatInput extends React.Component {
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.state =
|
|
|
|
{
|
|
|
|
text: ''
|
|
|
|
};
|
|
|
|
|
|
|
|
// TextArea element got via React ref.
|
|
|
|
// @type {HTMLElement}
|
|
|
|
this._textareaElem = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const {
|
|
|
|
connected,
|
|
|
|
chatDataProducer,
|
|
|
|
botDataProducer,
|
|
|
|
sendUserInfo
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
const { text } = this.state;
|
|
|
|
|
|
|
|
const disabled = !connected || (!chatDataProducer && !botDataProducer);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div data-component='ChatInput'>
|
|
|
|
<textarea
|
|
|
|
ref={(elem) => { this._textareaElem = elem; }}
|
|
|
|
placeholder={disabled ? '当前聊天不可用' : '说点什么...'}
|
|
|
|
dir='auto'
|
|
|
|
autoComplete='off'
|
|
|
|
disabled={disabled}
|
|
|
|
value={text || ''}
|
|
|
|
onChange={this.handleChange.bind(this)}
|
|
|
|
onKeyPress={this.handleKeyPress.bind(this, sendUserInfo)}
|
|
|
|
/>
|
|
|
|
<div className='sendOut' onClick={() => {
|
|
|
|
this.sendOut(sendUserInfo);
|
|
|
|
}}>发送</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
handleChange(event) {
|
|
|
|
const text = event.target.value;
|
|
|
|
|
|
|
|
this.setState({ text });
|
|
|
|
}
|
|
|
|
|
|
|
|
handleKeyPress(sendUserInfo, event) {
|
|
|
|
|
|
|
|
// If Shift + Enter do nothing.
|
|
|
|
if (event.key !== 'Enter' || (event.shiftKey || event.ctrlKey))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Don't add the sending Enter into the value.
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
this.sendOut(sendUserInfo)
|
|
|
|
}
|
|
|
|
|
|
|
|
sendOut(sendUserInfo) {
|
|
|
|
let text = this.state.text.trim();
|
|
|
|
|
|
|
|
this.setState({ text: '' });
|
|
|
|
|
|
|
|
if (text) {
|
|
|
|
const { roomClient } = this.props;
|
|
|
|
const match = BotMessageRegex.exec(text);
|
|
|
|
|
|
|
|
// Chat message.
|
|
|
|
if (!match) {
|
|
|
|
text = text.trim();
|
|
|
|
roomClient.sendChatMessage(text);
|
|
|
|
sendUserInfo(text);
|
|
|
|
}
|
|
|
|
// Message to the bot.
|
|
|
|
else {
|
|
|
|
text = match[1].trim();
|
|
|
|
|
|
|
|
roomClient.sendBotMessage(text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ChatInput.propTypes =
|
|
|
|
{
|
|
|
|
roomClient: PropTypes.any.isRequired,
|
|
|
|
connected: PropTypes.bool.isRequired,
|
|
|
|
chatDataProducer: PropTypes.any,
|
|
|
|
botDataProducer: PropTypes.any
|
|
|
|
};
|
|
|
|
|
|
|
|
const mapStateToProps = (state) => {
|
|
|
|
const dataProducersArray = Object.values(state.dataProducers);
|
|
|
|
const chatDataProducer = dataProducersArray
|
|
|
|
.find((dataProducer) => dataProducer.label === 'chat');
|
|
|
|
const botDataProducer = dataProducersArray
|
|
|
|
.find((dataProducer) => dataProducer.label === 'bot');
|
|
|
|
|
|
|
|
return {
|
|
|
|
connected: state.room.state === 'connected',
|
|
|
|
chatDataProducer,
|
|
|
|
botDataProducer
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const mapDispatchToProps = (dispatch) => {
|
|
|
|
return {
|
|
|
|
sendUserInfo: (text) => {
|
|
|
|
dispatch(requestActions.notify({
|
|
|
|
type: 'userMessage',
|
|
|
|
isMe: true,
|
|
|
|
text: text,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const ChatInputContainer = withRoomContext(connect(
|
|
|
|
mapStateToProps,
|
|
|
|
mapDispatchToProps,
|
|
|
|
)(ChatInput));
|
|
|
|
|
|
|
|
export default ChatInputContainer;
|