node-red-contrib-chatbot
Version:
REDBot a Chat bot for a full featured chat bot for Telegram, Facebook Messenger and Slack. Almost no coding skills required
161 lines (132 loc) • 3.64 kB
JavaScript
import React, { useEffect, useRef, Fragment } from 'react';
import _ from 'lodash';
import PropTypes from 'prop-types';
import Showdown from 'showdown';
import { typeMessage } from '../../types';
import { Message, PhotoContent, Metadata, MessageDate, MessageUser, UserStatus } from './views/generic';
import Content from './views/content';
import MessageComposer from './views/message-composer';
import './chat.scss';
const Messages = ({ children }) => {
const messagesEndRef = useRef(null);
useEffect(() => {
const el = messagesEndRef.current;
el.scrollTo(0, el.scrollHeight);
}, [children]);
return (
<div className="ui-chat-messages chat-history" ref={messagesEndRef}>
<ul>
{children}
</ul>
</div>
);
};
Messages.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
])
};
const ChatWindow = ({ children, width = '100%', style }) => {
return (
<div className="ui-chat-window chat" style={{ width: _.isNumber(width) ? `${width}px` : width, ...style }}>{children}</div>
);
};
ChatWindow.propTypes = {
width: PropTypes.string,
style: PropTypes.object,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
])
};
const MessageFrame = ({ children, ...props }) => {
const { message, inbound } = props;
return (
<Message {...props}>
<Metadata>
{inbound && (
<Fragment>
<MessageDate date={message.ts}/>
<MessageUser>{message.username}</MessageUser>
<UserStatus />
</Fragment>
)}
{!inbound && (
<Fragment>
<UserStatus />
<MessageUser>{message.username}</MessageUser>
<MessageDate date={message.ts}/>
</Fragment>
)}
</Metadata>
{children}
</Message>
);
};
MessageFrame.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
message: typeMessage,
inbound: PropTypes.bool
};
const MessageText = props => {
const { message, markdown = false, position, beak } = props;
let html = message.content;
if (markdown) {
const converter = new Showdown.Converter({ openLinksInNewWindow: true });
html = converter.makeHtml(message.content);
}
return (
<Content text={html} position={position} beak={beak}/>
);
};
MessageText.propTypes = {
message: typeMessage,
markdown: PropTypes.bool,
position: PropTypes.oneOf(['first', 'middle', 'last']),
beak: PropTypes.bool
};
class MessagePhoto extends React.Component {
// TODO username
// use func and state
// inbound msg too
render() {
const { message, position, beak } = this.props;
const arrayBufferView = new Uint8Array(message.content.data);
const blob = new Blob([arrayBufferView], { type: 'image/jpeg' });
const urlCreator = window.URL || window.webkitURL;
const imageUrl = urlCreator.createObjectURL(blob);
return (
<PhotoContent position={position} beak={beak} url={imageUrl} />
);
}
}
MessagePhoto.propTypes = {
message: typeMessage,
position: PropTypes.oneOf(['first', 'middle', 'last']),
beak: PropTypes.bool
};
import MessageButtons from './views/message-buttons';
import MessageQuickReplies from './views/message-quick-replies';
export {
Message,
Messages,
Content,
Metadata,
ChatWindow,
MessageFrame,
MessageComposer,
MessageDate,
MessageUser,
UserStatus,
MessageText,
MessageButtons,
MessagePhoto,
MessageQuickReplies
};