123 lines
3.9 KiB
TypeScript
123 lines
3.9 KiB
TypeScript
import classnames from 'classnames'
|
|
import React from 'react'
|
|
import { Message as ChatMessage } from '../actions/ChatActions'
|
|
import { Message } from '../actions/PeerActions'
|
|
import { Nicknames } from '../reducers/nicknames'
|
|
import Input from './Input'
|
|
import { ME } from '../constants'
|
|
import { getNickname } from '../nickname'
|
|
|
|
export interface MessageProps {
|
|
message: ChatMessage
|
|
}
|
|
|
|
function MessageEntry (props: MessageProps) {
|
|
const { message } = props
|
|
return (
|
|
<p className="message-text">
|
|
{message.image && (
|
|
<img src={message.image} width="100%" />
|
|
)}
|
|
{message.message}
|
|
</p>
|
|
)
|
|
}
|
|
|
|
export interface ChatProps {
|
|
visible: boolean
|
|
messages: ChatMessage[]
|
|
nicknames: Nicknames
|
|
onClose: () => void
|
|
sendMessage: (message: Message) => void
|
|
}
|
|
|
|
export default class Chat extends React.PureComponent<ChatProps> {
|
|
chatHistoryRef = React.createRef<HTMLDivElement>()
|
|
inputRef = React.createRef<Input>()
|
|
|
|
scrollToBottom = () => {
|
|
const chatHistoryRef = this.chatHistoryRef.current!
|
|
chatHistoryRef.scrollTop = chatHistoryRef.scrollHeight
|
|
}
|
|
componentDidMount () {
|
|
this.scrollToBottom()
|
|
this.focus()
|
|
}
|
|
componentDidUpdate () {
|
|
this.scrollToBottom()
|
|
this.focus()
|
|
}
|
|
focus() {
|
|
if (this.props.visible) {
|
|
this.inputRef.current?.textArea.current?.focus()
|
|
}
|
|
}
|
|
render () {
|
|
const { messages, sendMessage } = this.props
|
|
return (
|
|
<div className={classnames('chat-container', {
|
|
show: this.props.visible,
|
|
})}>
|
|
<div className="chat-header">
|
|
<div className="chat-close" onClick={this.props.onClose}>
|
|
<div className="button button-icon">
|
|
<span className="icon icon-arrow_forward" />
|
|
</div>
|
|
</div>
|
|
<div className="chat-title">Chat</div>
|
|
</div>
|
|
<div className="chat-history" ref={this.chatHistoryRef}>
|
|
|
|
{messages.length ? (
|
|
messages.map((message, i) => (
|
|
<div key={i}>
|
|
{message.userId === ME ? (
|
|
<div className="chat-item chat-item-me">
|
|
<div className="message">
|
|
<span className="message-user-name">
|
|
{getNickname(this.props.nicknames, message.userId)}
|
|
</span>
|
|
<span className="icon icon-schedule" />
|
|
<time className="message-time">{message.timestamp}</time>
|
|
<MessageEntry message={message} />
|
|
</div>
|
|
{message.image ? (
|
|
<img className="chat-item-img" src={message.image} />
|
|
) : (
|
|
<span className="chat-item-img icon icon-face" />
|
|
)}
|
|
</div>
|
|
) : (
|
|
<div className="chat-item chat-item-other">
|
|
{message.image ? (
|
|
<img className="chat-item-img" src={message.image} />
|
|
) : (
|
|
<span className="chat-item-img icon icon-face" />
|
|
)}
|
|
<div className="message">
|
|
<span className="message-user-name">
|
|
{getNickname(this.props.nicknames, message.userId)}
|
|
</span>
|
|
<span className="icon icon-schedule" />
|
|
<time className="message-time">{message.timestamp}</time>
|
|
<MessageEntry message={message} />
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
))
|
|
) : (
|
|
<div className="chat-empty">
|
|
<span className="chat-empty-icon icon icon-question_answer" />
|
|
<div className="chat-empty-message">No Notifications</div>
|
|
</div>
|
|
)}
|
|
|
|
</div>
|
|
|
|
<Input ref={this.inputRef} sendMessage={sendMessage} />
|
|
</div>
|
|
)
|
|
}
|
|
}
|