/*global chrome */ import React, { Component } from 'react'; import { Typography, TextField, InputAdornment, IconButton, ButtonGroup, Button, ExpansionPanel, ExpansionPanelSummary, ExpansionPanelDetails, Card, CardContent, Tooltip, } from '@material-ui/core'; import Thread from './Thread'; import Send from '@material-ui/icons/Send'; import Exit from '@material-ui/icons/ExitToApp'; import Share from '@material-ui/icons/Share'; import Delete from '@material-ui/icons/Delete'; import PhoneEnable from '@material-ui/icons/CallRounded'; import PhoneDisable from '@material-ui/icons/CallEndRounded'; import MicOff from '@material-ui/icons/MicOff'; import MicOn from '@material-ui/icons/Mic'; import Gif from '@material-ui/icons/Gif'; import { Carousel } from '@giphy/react-components'; import { GiphyFetch } from '@giphy/js-fetch-api'; import { SendMessageApi, LeaveRoomApi, DeleteRoomApi, UpdatePlayerApi, getPlayerSource, PLAYER_SOURCE, LocalData, PLAYER_STATUS, emptyLocalData, } from './Api'; import { goTo } from 'route-lite'; import Create from './Create'; import VideoListener from './VideoListener'; import CallManager from './CallManager'; import { MoreVert, PauseCircleFilled, LinkOutlined, PlayCircleFilled } from '@material-ui/icons'; const giphyFetch = new GiphyFetch('ojJbIMUN6XRMn4mHiFFav3rMCpXUg8sq'); const alertMessage = { name: '', text: 'Functionality may be buggy, support on this site is in beta.', time: '', uid: '', }; export default class Chat extends Component { constructor(props) { super(props); this.state = { name: '', messages: [], newMessage: '', admin: null, gif: false, onCall: false, muted: false, menuPopover: true, }; this.port = null; this.gifClick = this.gifClick.bind(this); this.endParty = this.endParty.bind(this); this.handleMute = this.handleMute.bind(this); this.leaveParty = this.leaveParty.bind(this); this.shareParty = this.shareParty.bind(this); this.syncPlayer = this.syncPlayer.bind(this); this.sendMessage = this.sendMessage.bind(this); this.getCarousel = this.getCarousel.bind(this); this.handlePhoneCall = this.handlePhoneCall.bind(this); this.callEventListener = this.callEventListener.bind(this); this.mCallManager = new CallManager(this.callEventListener, this.props.notify); this.sendMessageInvoker = this.sendMessageInvoker.bind(this); this.videoEventListener = this.videoEventListener.bind(this); this.mVideoListener = new VideoListener(this.videoEventListener); } componentDidMount() { // EVENT CAPTURE FOR ENTER TO SEND window.onkeypress = (ev) => { if (ev.code === 'Enter') { if (ev.target === document.getElementById('chat-message-box-input')) { if (ev.shiftKey === false && this.state.gif === true) ev.preventDefault(); if (ev.shiftKey === false && this.state.gif === false) { ev.preventDefault(); this.sendMessageInvoker(); } } } }; // VIDEO LISTENER START this.mVideoListener.start(); // CHROME FIREBASE FIRESTORE LISTENER this.port = chrome.runtime.connect({ name: LocalData().partyName }); // Initialize listener this.port.postMessage({ type: 'INIT', roomId: LocalData().partyName, }); // Listener this.port.onMessage.addListener((response) => { if (response.isError === true) { this.props.notify('Uh oh. Got lost from the party.'); goTo(Create, this.props); return; } this.setState(response); if (response.player) this.mVideoListener.doUpdate(response.player); const pcc = document.querySelector('.thread-container'); if (pcc) pcc.scrollTop = pcc.scrollHeight; }); // DONE WITH MOUNTING TASKS this.props.updateLoading(false); } componentWillUnmount() { this.mVideoListener.end(); } videoEventListener(video) { this.syncPlayer(video); } callEventListener(event) { this.setState(event); } syncPlayer(video) { const { status, showName, time, source, element, showChanged } = video; if (element) { UpdatePlayerApi({ roomId: LocalData().partyName, showChanged, userName: LocalData().userName, player: { status, showName, time, source, updatedBy: LocalData().userUid, url: window.location.href, }, }).catch((err) => { this.props.updateLoading(false); this.props.notify(err.message || err.statusText); console.error('Sync Party API error', err); }); } else { this.mVideoListener.start(); } } endParty() { this.props.notify('Ending party...'); this.props.updateLoading(true); const data = { partyName: LocalData().partyName, }; DeleteRoomApi(data) .then((res) => { this.props.notify('Ended party'); emptyLocalData(); goTo(Create, this.props); this.props.updateLoading(false); }) .catch((err) => { this.props.updateLoading(false); this.props.notify(err.message || err.statusText); console.error('End Party API error', err); }); } leaveParty() { this.props.notify('Leaving party...'); this.props.updateLoading(true); const data = { partyName: LocalData().partyName, userUid: LocalData().userUid, }; LeaveRoomApi(data) .then((res) => { this.props.notify('Left party'); emptyLocalData(); goTo(Create, this.props); this.props.updateLoading(false); }) .catch((err) => { this.props.updateLoading(false); this.props.notify(err.message || err.statusText); console.error('End Party API error', err); }); } shareParty() { const el = document.createElement('textarea'); el.value = `Join my party on Watch Party!\nParty Name: ${LocalData().partyName}\nParty Pin: ${ LocalData().partyPin }\n${window.location.href}\n---\nGet Watch Party at https:\\\\get.chromewatchparty.com`; document.body.appendChild(el); el.select(); document.execCommand('copy'); document.body.removeChild(el); this.props.notify('Copied party invitation'); } sendMessage(message) { const data = { roomId: LocalData().partyName, name: LocalData().userName, uid: LocalData().userUid, text: message, time: new Date(), type: '', }; if (this.state.gif === true) data.type = 'giphy'; SendMessageApi(data).catch((err) => { this.props.notify(err.message || err.statusText); console.error('Send Message API error', err); }); } sendMessageInvoker(overrideMessage) { if (overrideMessage) this.sendMessage(overrideMessage); else { const trim = this.state.newMessage.replace(/^\s+|\s+$/g, ''); if (trim !== '') this.sendMessage(trim); } this.setState({ newMessage: '' }); } gifClick(iGif, ev) { ev.preventDefault(); this.sendMessageInvoker(iGif.images.original.url); } getCarousel(offset) { return this.state.newMessage === '' ? giphyFetch.trending({ offset, limit: 1 }) : giphyFetch.search(this.state.newMessage, { offset, limit: 1 }); } handlePhoneCall() { const { onCall, conference, admin } = this.state; this.mCallManager.toggleCall(onCall, conference, admin); } handleMute() { this.mCallManager.toggleMute(this.state.muted); } getPrettyTime(t) { return t > 3600 ? new Date(t * 1000).toISOString().substr(11, 8) : new Date(t * 1000).toISOString().substr(14, 5); } render() { const { admin, name, messages, newMessage, gif, onCall, muted, player } = this.state; if (getPlayerSource() === PLAYER_SOURCE.HBONOW && messages[0] !== alertMessage) messages.unshift(alertMessage); return (
} >
WATCH PARTY {name}
), }} /> {admin && ( )}
{player ? ( {player.showName && player.status !== PLAYER_STATUS.NOT_PLAYING ? ( {player.status === PLAYER_STATUS.PAUSED ? `PAUSED AT ${this.getPrettyTime(player.time)}` : player.status === PLAYER_STATUS.PLAYING ? `STARTED PLAYING FROM ${this.getPrettyTime(player.time)}` : `SHOW IS AT ${this.getPrettyTime(player.time)}`}
{player.status === PLAYER_STATUS.PAUSED ? ( ) : ( )}
{player.showName}
) : ( Nothing playing right now )} {player && player.showName && player.status ? ( ) : null}
) : null}
{gif || newMessage ? null : ( {onCall ? ( ) : ( )} )} {!gif && !newMessage && onCall && !muted ? ( ) : !gif && !newMessage && onCall && muted ? ( ) : null} { this.setState({ newMessage: e.target.value }); if (this.state.gif) { const carousel = document.querySelector('.giphy-carousel'); setTimeout(() => carousel.scroll(carousel.scrollWidth, carousel.scrollHeight), 250); } }} InputProps={{ id: 'chat-message-box-input', endAdornment: ( this.sendMessageInvoker(newMessage)} edge="end" > ), startAdornment: ( this.setState({ gif: !gif })} edge="start"> ), }} />
{gif ? ( ) : null}
); } }