Fix broken chat button, remove refs
This commit is contained in:
parent
329108185d
commit
ec31ea2a6b
@ -1,10 +1,10 @@
|
|||||||
import Alerts, { AlertPropType } from './Alerts.js'
|
|
||||||
import * as constants from '../constants.js'
|
import * as constants from '../constants.js'
|
||||||
import Toolbar from './Toolbar.js'
|
import Alerts, { AlertPropType } from './Alerts.js'
|
||||||
import Notifications, { NotificationPropTypes } from './Notifications.js'
|
|
||||||
import Chat, { MessagePropTypes } from './Chat.js'
|
import Chat, { MessagePropTypes } from './Chat.js'
|
||||||
|
import Notifications, { NotificationPropTypes } from './Notifications.js'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import Toolbar from './Toolbar.js'
|
||||||
import Video, { StreamPropType } from './Video.js'
|
import Video, { StreamPropType } from './Video.js'
|
||||||
import _ from 'underscore'
|
import _ from 'underscore'
|
||||||
|
|
||||||
@ -25,10 +25,24 @@ export default class App extends React.PureComponent {
|
|||||||
constructor () {
|
constructor () {
|
||||||
super()
|
super()
|
||||||
this.state = {
|
this.state = {
|
||||||
videos: {}
|
videos: {},
|
||||||
|
chatVisible: false
|
||||||
}
|
}
|
||||||
this.chatRef = React.createRef()
|
}
|
||||||
this.toolbarRef = React.createRef()
|
handleShowChat = () => {
|
||||||
|
this.setState({
|
||||||
|
chatVisible: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
handleHideChat = () => {
|
||||||
|
this.setState({
|
||||||
|
chatVisible: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
handleToggleChat = () => {
|
||||||
|
return this.state.chatVisible
|
||||||
|
? this.handleHideChat()
|
||||||
|
: this.handleShowChat()
|
||||||
}
|
}
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { init } = this.props
|
const { init } = this.props
|
||||||
@ -53,22 +67,21 @@ export default class App extends React.PureComponent {
|
|||||||
return (
|
return (
|
||||||
<div className="app">
|
<div className="app">
|
||||||
<Toolbar
|
<Toolbar
|
||||||
chatRef={this.chatRef}
|
chatVisible={this.state.chatVisible}
|
||||||
messages={messages}
|
messages={messages}
|
||||||
|
onToggleChat={this.handleToggleChat}
|
||||||
stream={streams[constants.ME]}
|
stream={streams[constants.ME]}
|
||||||
ref={this.toolbarRef}
|
|
||||||
/>
|
/>
|
||||||
<Alerts alerts={alerts} dismiss={dismissAlert} />
|
<Alerts alerts={alerts} dismiss={dismissAlert} />
|
||||||
<Notifications notifications={notifications} />
|
<Notifications notifications={notifications} />
|
||||||
<div className="chat-container" ref={this.chatRef}>
|
|
||||||
<Chat
|
<Chat
|
||||||
messages={messages}
|
messages={messages}
|
||||||
videos={videos}
|
|
||||||
notify={notify}
|
notify={notify}
|
||||||
|
onClose={this.handleHideChat}
|
||||||
sendMessage={sendMessage}
|
sendMessage={sendMessage}
|
||||||
toolbarRef={this.toolbarRef}
|
videos={videos}
|
||||||
|
visible={this.state.chatVisible}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div className="videos">
|
<div className="videos">
|
||||||
<Video
|
<Video
|
||||||
videos={videos}
|
videos={videos}
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
|
import Input from './Input.js'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import classnames from 'classnames'
|
||||||
import socket from '../socket.js'
|
import socket from '../socket.js'
|
||||||
import Input from './Input.js'
|
|
||||||
|
|
||||||
export const MessagePropTypes = PropTypes.shape({
|
export const MessagePropTypes = PropTypes.shape({
|
||||||
userId: PropTypes.string.isRequired,
|
userId: PropTypes.string.isRequired,
|
||||||
@ -12,18 +13,20 @@ export const MessagePropTypes = PropTypes.shape({
|
|||||||
|
|
||||||
export default class Chat extends React.PureComponent {
|
export default class Chat extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
visible: PropTypes.bool.isRequired,
|
||||||
messages: PropTypes.arrayOf(MessagePropTypes).isRequired,
|
messages: PropTypes.arrayOf(MessagePropTypes).isRequired,
|
||||||
videos: PropTypes.object.isRequired,
|
|
||||||
notify: PropTypes.func.isRequired,
|
notify: PropTypes.func.isRequired,
|
||||||
|
onClose: PropTypes.func.isRequired,
|
||||||
sendMessage: PropTypes.func.isRequired,
|
sendMessage: PropTypes.func.isRequired,
|
||||||
toolbarRef: PropTypes.object.isRequired
|
videos: PropTypes.object.isRequired
|
||||||
}
|
}
|
||||||
handleCloseChat = e => {
|
constructor () {
|
||||||
const { toolbarRef } = this.props
|
super()
|
||||||
toolbarRef.chatButton.click()
|
this.chatHistoryRef = React.createRef()
|
||||||
}
|
}
|
||||||
scrollToBottom = () => {
|
scrollToBottom = () => {
|
||||||
this.chatScroll.scrollTop = this.chatScroll.scrollHeight
|
const chatHistoryRef = this.chatHistoryRef.current
|
||||||
|
chatHistoryRef.scrollTop = chatHistoryRef.scrollHeight
|
||||||
}
|
}
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
this.scrollToBottom()
|
this.scrollToBottom()
|
||||||
@ -34,16 +37,18 @@ export default class Chat extends React.PureComponent {
|
|||||||
render () {
|
render () {
|
||||||
const { messages, videos, notify, sendMessage } = this.props
|
const { messages, videos, notify, sendMessage } = this.props
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={classnames('chat-container', {
|
||||||
|
show: this.props.visible
|
||||||
|
})}>
|
||||||
<div className="chat-header">
|
<div className="chat-header">
|
||||||
<div className="chat-close" onClick={this.handleCloseChat}>
|
<div className="chat-close" onClick={this.props.onClose}>
|
||||||
<div className="button button-icon">
|
<div className="button button-icon">
|
||||||
<span className="icon icon-arrow_forward" />
|
<span className="icon icon-arrow_forward" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="chat-title">Chat</div>
|
<div className="chat-title">Chat</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="chat-history" ref={div => { this.chatScroll = div }}>
|
<div className="chat-history" ref={this.chatHistoryRef}>
|
||||||
|
|
||||||
{messages.length ? (
|
{messages.length ? (
|
||||||
messages.map((message, i) => (
|
messages.map((message, i) => (
|
||||||
|
|||||||
@ -1,30 +1,16 @@
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import classnames from 'classnames'
|
||||||
import screenfull from 'screenfull'
|
import screenfull from 'screenfull'
|
||||||
import { MessagePropTypes } from './Chat.js'
|
import { MessagePropTypes } from './Chat.js'
|
||||||
import { StreamPropType } from './Video.js'
|
import { StreamPropType } from './Video.js'
|
||||||
|
|
||||||
export default class Toolbar extends React.PureComponent {
|
export default class Toolbar extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
chatRef: PropTypes.object.isRequired,
|
|
||||||
messages: PropTypes.arrayOf(MessagePropTypes).isRequired,
|
messages: PropTypes.arrayOf(MessagePropTypes).isRequired,
|
||||||
stream: StreamPropType
|
stream: StreamPropType,
|
||||||
}
|
onToggleChat: PropTypes.func.isRequired,
|
||||||
constructor () {
|
chatVisible: PropTypes.bool.isRequired
|
||||||
super()
|
|
||||||
this.state = {
|
|
||||||
isChatOpen: false,
|
|
||||||
totalMessages: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handleChatClick = () => {
|
|
||||||
const { chatRef, messages } = this.props
|
|
||||||
chatRef.classList.toggle('show')
|
|
||||||
this.chatButton.classList.toggle('on')
|
|
||||||
this.setState({
|
|
||||||
isChatOpen: chatRef.classList.contains('show'),
|
|
||||||
totalMessages: messages.length
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
handleMicClick = () => {
|
handleMicClick = () => {
|
||||||
const { stream } = this.props
|
const { stream } = this.props
|
||||||
@ -51,14 +37,14 @@ export default class Toolbar extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
render () {
|
render () {
|
||||||
const { messages, stream } = this.props
|
const { messages, stream } = this.props
|
||||||
const { isChatOpen, totalMessages } = this.state
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="toolbar active">
|
<div className="toolbar active">
|
||||||
<div onClick={this.handleChatClick}
|
<div onClick={this.props.onToggleChat}
|
||||||
ref={node => { this.chatButton = node }}
|
className={classnames('button chat', {
|
||||||
className="button chat"
|
on: this.props.chatVisible
|
||||||
data-blink={messages.length !== totalMessages && !isChatOpen}
|
})}
|
||||||
|
data-blink={this.props.chatVisible && messages.length}
|
||||||
title="Chat"
|
title="Chat"
|
||||||
>
|
>
|
||||||
<span className="icon icon-question_answer" />
|
<span className="icon icon-question_answer" />
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import TestUtils from 'react-dom/test-utils'
|
|||||||
import Toolbar from '../Toolbar.js'
|
import Toolbar from '../Toolbar.js'
|
||||||
import { MediaStream } from '../../window.js'
|
import { MediaStream } from '../../window.js'
|
||||||
|
|
||||||
describe('components/Video', () => {
|
describe('components/Toolbar', () => {
|
||||||
|
|
||||||
class ToolbarWrapper extends React.PureComponent {
|
class ToolbarWrapper extends React.PureComponent {
|
||||||
static propTypes = Toolbar.propTypes
|
static propTypes = Toolbar.propTypes
|
||||||
@ -15,22 +15,22 @@ describe('components/Video', () => {
|
|||||||
}
|
}
|
||||||
render () {
|
render () {
|
||||||
return <Toolbar
|
return <Toolbar
|
||||||
chatRef={this.props.chatRef}
|
chatVisible={this.props.chatVisible}
|
||||||
|
onToggleChat={this.props.onToggleChat}
|
||||||
messages={this.props.messages}
|
messages={this.props.messages}
|
||||||
stream={this.state.stream || this.props.stream}
|
stream={this.state.stream || this.props.stream}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let component, node, chatRef, mediaStream, url
|
let component, node, mediaStream, url, onToggleChat
|
||||||
function render () {
|
function render () {
|
||||||
mediaStream = new MediaStream()
|
mediaStream = new MediaStream()
|
||||||
chatRef = ReactDOM.findDOMNode(
|
onToggleChat = jest.fn()
|
||||||
TestUtils.renderIntoDocument(<div />)
|
|
||||||
)
|
|
||||||
component = TestUtils.renderIntoDocument(
|
component = TestUtils.renderIntoDocument(
|
||||||
<ToolbarWrapper
|
<ToolbarWrapper
|
||||||
chatRef={chatRef}
|
chatVisible
|
||||||
|
onToggleChat={onToggleChat}
|
||||||
messages={[]}
|
messages={[]}
|
||||||
stream={{ mediaStream, url }}
|
stream={{ mediaStream, url }}
|
||||||
/>
|
/>
|
||||||
@ -46,9 +46,10 @@ describe('components/Video', () => {
|
|||||||
|
|
||||||
describe('handleChatClick', () => {
|
describe('handleChatClick', () => {
|
||||||
it('toggle chat', () => {
|
it('toggle chat', () => {
|
||||||
|
expect(onToggleChat.mock.calls.length).toBe(0)
|
||||||
const button = node.querySelector('.chat')
|
const button = node.querySelector('.chat')
|
||||||
TestUtils.Simulate.click(button)
|
TestUtils.Simulate.click(button)
|
||||||
expect(button.classList.contains('on')).toBe(true)
|
expect(onToggleChat.mock.calls.length).toBe(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user