153 lines
4.1 KiB
TypeScript
153 lines
4.1 KiB
TypeScript
import classnames from 'classnames'
|
|
import map from 'lodash/map'
|
|
import React from 'react'
|
|
import Peer from 'simple-peer'
|
|
import { Message } from '../actions/ChatActions'
|
|
import { dismissNotification, Notification } from '../actions/NotifyActions'
|
|
import { TextMessage } from '../actions/PeerActions'
|
|
import { AddStreamPayload, removeStream } from '../actions/StreamActions'
|
|
import * as constants from '../constants'
|
|
import Chat from './Chat'
|
|
import { Media } from './Media'
|
|
import Notifications from './Notifications'
|
|
import { Side } from './Side'
|
|
import Toolbar from './Toolbar'
|
|
import Video from './Video'
|
|
import { getDesktopStream } from '../actions/MediaActions'
|
|
|
|
export interface AppProps {
|
|
active: string | null
|
|
dismissNotification: typeof dismissNotification
|
|
init: () => void
|
|
notifications: Record<string, Notification>
|
|
messages: Message[]
|
|
messagesCount: number
|
|
peers: Record<string, Peer.Instance>
|
|
play: () => void
|
|
sendMessage: (message: TextMessage) => void
|
|
streams: Record<string, AddStreamPayload>
|
|
getDesktopStream: typeof getDesktopStream
|
|
removeStream: typeof removeStream
|
|
onSendFile: (file: File) => void
|
|
toggleActive: (userId: string) => void
|
|
}
|
|
|
|
export interface AppState {
|
|
videos: Record<string, unknown>
|
|
chatVisible: boolean
|
|
}
|
|
|
|
const localStreams: string[] = [constants.ME, constants.ME_DESKTOP]
|
|
|
|
export default class App extends React.PureComponent<AppProps, AppState> {
|
|
state: AppState = {
|
|
videos: {},
|
|
chatVisible: false,
|
|
}
|
|
handleShowChat = () => {
|
|
this.setState({
|
|
chatVisible: true,
|
|
})
|
|
}
|
|
handleHideChat = () => {
|
|
this.setState({
|
|
chatVisible: false,
|
|
})
|
|
}
|
|
handleToggleChat = () => {
|
|
return this.state.chatVisible
|
|
? this.handleHideChat()
|
|
: this.handleShowChat()
|
|
}
|
|
componentDidMount () {
|
|
const { init } = this.props
|
|
init()
|
|
}
|
|
onHangup = () => {
|
|
this.props.removeStream(constants.ME)
|
|
this.props.removeStream(constants.ME_DESKTOP)
|
|
}
|
|
render () {
|
|
const {
|
|
active,
|
|
dismissNotification,
|
|
notifications,
|
|
messages,
|
|
messagesCount,
|
|
onSendFile,
|
|
play,
|
|
peers,
|
|
sendMessage,
|
|
toggleActive,
|
|
streams,
|
|
} = this.props
|
|
|
|
const { videos } = this.state
|
|
|
|
const chatVisibleClassName = classnames({
|
|
'chat-visible': this.state.chatVisible,
|
|
})
|
|
|
|
return (
|
|
<div className="app">
|
|
<Side align='flex-end' left zIndex={2}>
|
|
<Toolbar
|
|
chatVisible={this.state.chatVisible}
|
|
messagesCount={messagesCount}
|
|
onToggleChat={this.handleToggleChat}
|
|
onSendFile={onSendFile}
|
|
onHangup={this.onHangup}
|
|
stream={streams[constants.ME]}
|
|
desktopStream={streams[constants.ME_DESKTOP]}
|
|
onGetDesktopStream={this.props.getDesktopStream}
|
|
onRemoveStream={this.props.removeStream}
|
|
/>
|
|
</Side>
|
|
<Side className={chatVisibleClassName} top zIndex={1}>
|
|
<Notifications
|
|
dismiss={dismissNotification}
|
|
notifications={notifications}
|
|
/>
|
|
<Media />
|
|
</Side>
|
|
<Chat
|
|
messages={messages}
|
|
onClose={this.handleHideChat}
|
|
sendMessage={sendMessage}
|
|
visible={this.state.chatVisible}
|
|
/>
|
|
<div className={classnames('videos', chatVisibleClassName)}>
|
|
{localStreams.map(userId => (
|
|
<Video
|
|
videos={videos}
|
|
key={userId}
|
|
active={active === userId}
|
|
onClick={toggleActive}
|
|
play={play}
|
|
stream={streams[userId]}
|
|
userId={userId}
|
|
muted
|
|
mirrored
|
|
/>
|
|
))}
|
|
{
|
|
map(peers, (_, userId) => userId)
|
|
.filter(stream => !!stream)
|
|
.map(userId =>
|
|
<Video
|
|
active={userId === active}
|
|
key={userId}
|
|
onClick={toggleActive}
|
|
play={play}
|
|
stream={streams[userId]}
|
|
userId={userId}
|
|
videos={videos}
|
|
/>,
|
|
)
|
|
}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
}
|