diff --git a/app/assets/styles/blink/_ConferenceBox.scss b/app/assets/styles/blink/_ConferenceBox.scss
index 2bf9dac..7f792b2 100644
--- a/app/assets/styles/blink/_ConferenceBox.scss
+++ b/app/assets/styles/blink/_ConferenceBox.scss
@@ -1,58 +1,59 @@
.container {
flex: 1;
}
.button {
background-color: white;
margin: 8px;
}
.iosButton {
background-color: white;
margin: 8px;
padding-top: 4px;
}
.androidButton {
background-color: white;
margin: 8px;
}
.conferenceContainer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
align-content: flex-end;
}
.videosContainer {
flex: 1;
+ flex-wrap: wrap;
}
.landscapeVideosContainer {
flex-direction: row;
}
.hangupButton {
background-color: rgba(#a94442, .8);
}
.wholePageVideo {
width: 100%;
height: 100%;
}
.buttonContainer {
flex-direction: row;
margin: 0 auto;
}
.carouselContainer {
position: absolute;
bottom: 10;
left: 10;
right: 10;
}
diff --git a/app/assets/styles/blink/_ConferenceMatrixParticipant.scss b/app/assets/styles/blink/_ConferenceMatrixParticipant.scss
index 84ee3aa..ad7dd04 100644
--- a/app/assets/styles/blink/_ConferenceMatrixParticipant.scss
+++ b/app/assets/styles/blink/_ConferenceMatrixParticipant.scss
@@ -1,42 +1,53 @@
.container {
flex: 1;
+ width: 100%;
+}
+
+.portraitTabletContainer {
+ flex-basis: 50%;
+ width: 50%;
+}
+
+.landscapeTabletContainer {
+ flex-basis: 50%;
+ height: 50%;
}
.soloContainer {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.videoContainer {
height: 100%;
width: 100%;
}
.video {
height: 100%;
width: 100%;
}
.controlsTop {
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 1;
display: flex;
align-items: center;
flex-direction: row;
max-height: 50px;
min-height: 50px;
padding-left: 20px;
}
.badge {
background-color: #5cb85c;
margin-bottom: 10px;
font-size: 14px;
font-weight: 500;
}
diff --git a/app/assets/styles/blink/_ConferenceParticipant.scss b/app/assets/styles/blink/_ConferenceParticipant.scss
index c8cce63..8ccefd3 100644
--- a/app/assets/styles/blink/_ConferenceParticipant.scss
+++ b/app/assets/styles/blink/_ConferenceParticipant.scss
@@ -1,17 +1,13 @@
.container {
flex: 1;
- width: 120px;
- height: 90px;
- border-width: 1px;
- border-radius: 5px;
}
.videoContainer {
- height: 100%;
- width: 100%;
+ width: 120px;
+ height: 90px;
}
.video {
height: 100%;
width: 100%;
}
diff --git a/app/assets/styles/blink/_ConferenceParticipantSelf.scss b/app/assets/styles/blink/_ConferenceParticipantSelf.scss
index 22ccd2b..60196b4 100644
--- a/app/assets/styles/blink/_ConferenceParticipantSelf.scss
+++ b/app/assets/styles/blink/_ConferenceParticipantSelf.scss
@@ -1,21 +1,22 @@
.container {
flex: 1;
width: 120px;
height: 90px;
elevation: 5;
}
.video {
height:100%;
width: 100%;
}
.muteIcon {
position: absolute;
top: 30px;
width: 100%;
z-index: 2;
}
+
.icon {
margin: 0 auto;
}
diff --git a/app/components/ConferenceBox.js b/app/components/ConferenceBox.js
index 66655dc..d638f56 100644
--- a/app/components/ConferenceBox.js
+++ b/app/components/ConferenceBox.js
@@ -1,736 +1,765 @@
'use strict';
import React, {Component, Fragment} from 'react';
import { View, Platform, TouchableWithoutFeedback } from 'react-native';
import PropTypes from 'prop-types';
import * as sylkrtc from 'sylkrtc';
import classNames from 'classnames';
import debug from 'react-native-debug';
import superagent from 'superagent';
import autoBind from 'auto-bind';
import { RTCView } from 'react-native-webrtc';
import { IconButton, Appbar, Portal, Modal, Surface, Paragraph } from 'react-native-paper';
import config from '../config';
import utils from '../utils';
//import AudioPlayer from './AudioPlayer';
import ConferenceDrawer from './ConferenceDrawer';
import ConferenceDrawerLog from './ConferenceDrawerLog';
// import ConferenceDrawerFiles from './ConferenceDrawerFiles';
import ConferenceDrawerParticipant from './ConferenceDrawerParticipant';
import ConferenceDrawerParticipantList from './ConferenceDrawerParticipantList';
import ConferenceDrawerSpeakerSelection from './ConferenceDrawerSpeakerSelection';
import ConferenceHeader from './ConferenceHeader';
import ConferenceCarousel from './ConferenceCarousel';
import ConferenceParticipant from './ConferenceParticipant';
import ConferenceMatrixParticipant from './ConferenceMatrixParticipant';
import ConferenceParticipantSelf from './ConferenceParticipantSelf';
import InviteParticipantsModal from './InviteParticipantsModal';
import styles from '../assets/styles/blink/_ConferenceBox.scss';
const DEBUG = debug('blinkrtc:ConferenceBox');
debug.enable('*');
class ConferenceBox extends Component {
constructor(props) {
super(props);
autoBind(this);
this.state = {
callOverlayVisible: true,
audioMuted: false,
videoMuted: false,
participants: props.call.participants.slice(),
showInviteModal: false,
showDrawer: false,
showFiles: false,
shareOverlayVisible: false,
activeSpeakers: props.call.activeParticipants.slice(),
selfDisplayedLarge: false,
eventLog: [],
sharedFiles: props.call.sharedFiles.slice(),
largeVideoStream: null
};
const friendlyName = this.props.remoteUri.split('@')[0];
//if (window.location.origin.startsWith('file://')) {
this.callUrl = `${config.publicUrl}/conference/${friendlyName}`;
//} else {
// this.callUrl = `${window.location.origin}/conference/${friendlyName}`;
//}
const emailMessage = `You can join me in the conference using a Web browser at ${this.callUrl} ` +
'or by using the freely available Sylk WebRTC client app at http://sylkserver.com';
const subject = 'Join me, maybe?';
this.emailLink = `mailto:?subject=${encodeURI(subject)}&body=${encodeURI(emailMessage)}`;
this.overlayTimer = null;
this.logEvent = {};
this.haveVideo = false;
this.uploads = [];
[
'error',
'warning',
'info',
'debug'
].forEach((level) => {
this.logEvent[level] = (
(action, messages, originator) => {
const log = this.state.eventLog.slice();
log.unshift({originator, originator, level: level, action: action, messages: messages});
this.setState({eventLog: log});
}
);
});
}
componentDidMount() {
for (let p of this.state.participants) {
p.on('stateChanged', this.onParticipantStateChanged);
p.attach();
}
this.props.call.on('participantJoined', this.onParticipantJoined);
this.props.call.on('participantLeft', this.onParticipantLeft);
this.props.call.on('roomConfigured', this.onConfigureRoom);
this.props.call.on('fileSharing', this.onFileSharing);
this.armOverlayTimer();
// attach to ourselves first if there are no other participants
if (this.state.participants.length === 0) {
setTimeout(() => {
const item = {
stream: this.props.call.getLocalStreams()[0],
identity: this.props.call.localIdentity
};
this.selectVideo(item);
});
} else {
// this.changeResolution();
}
if (this.props.call.getLocalStreams()[0].getVideoTracks().length !== 0) {
this.haveVideo = true;
}
}
componentWillUnmount() {
clearTimeout(this.overlayTimer);
this.uploads.forEach((upload) => {
this.props.notificationCenter().removeNotification(upload[1]);
upload[0].abort();
})
}
onParticipantJoined(p) {
DEBUG(`Participant joined: ${p.identity}`);
if (p.identity._uri.search('guest.') === -1) {
// used for history item
this.props.saveParticipant(this.props.call.id, this.props.remoteUri.split('@')[0], p.identity._uri);
}
// this.refs.audioPlayerParticipantJoined.play();
p.on('stateChanged', this.onParticipantStateChanged);
p.attach();
this.setState({
participants: this.state.participants.concat([p])
});
// this.changeResolution();
}
onParticipantLeft(p) {
DEBUG(`Participant left: ${p.identity}`);
// this.refs.audioPlayerParticipantLeft.play();
const participants = this.state.participants.slice();
const idx = participants.indexOf(p);
if (idx !== -1) {
participants.splice(idx, 1);
this.setState({
participants: participants
});
}
p.detach(true);
// this.changeResolution();
}
onParticipantStateChanged(oldState, newState) {
if (newState === 'established' || newState === null) {
this.maybeSwitchLargeVideo();
}
}
onConfigureRoom(config) {
const newState = {};
newState.activeSpeakers = config.activeParticipants;
this.setState(newState);
if (config.activeParticipants.length === 0) {
this.logEvent.info('set speakers to', ['Nobody'], config.originator);
} else {
const speakers = config.activeParticipants.map((p) => {return p.identity.displayName || p.identity.uri});
this.logEvent.info('set speakers to', speakers, config.originator);
}
this.maybeSwitchLargeVideo();
}
onFileSharing(files) {
let stateFiles = this.state.sharedFiles;
stateFiles = stateFiles.concat(files);
this.setState({sharedFiles: stateFiles});
files.forEach((file)=>{
if (file.session !== this.props.call.id) {
this.props.notificationCenter().postFileShared(file, this.showFiles);
}
})
}
+ onVideoSelected(item) {
+ const participants = this.state.participants.slice();
+ const idx = participants.indexOf(item);
+ participants.splice(idx, 1);
+ participants.unshift(item);
+ if (item.videoPaused) {
+ item.resumeVideo();
+ }
+ this.setState({
+ participants: participants
+ });
+ }
+
changeResolution() {
let stream = this.props.call.getLocalStreams()[0];
if (this.state.participants.length < 2) {
this.props.call.scaleLocalTrack(stream, 1.5);
} else if (this.state.participants.length < 5) {
this.props.call.scaleLocalTrack(stream, 2);
} else {
this.props.call.scaleLocalTrack(stream, 1);
}
}
selectVideo(item) {
DEBUG('Switching video to: %o', item);
if (item.stream) {
this.setState({selfDisplayedLarge: true, largeVideoStream: item.stream});
}
}
maybeSwitchLargeVideo() {
// Switch the large video to another source, maybe.
if (this.state.participants.length === 0 && !this.state.selfDisplayedLarge) {
// none of the participants are eligible, show ourselves
const item = {
stream: this.props.call.getLocalStreams()[0],
identity: this.props.call.localIdentity
};
this.selectVideo(item);
} else if (this.state.selfDisplayedLarge) {
this.setState({selfDisplayedLarge: false});
}
}
handleClipboardButton() {
utils.copyToClipboard(this.callUrl);
this.props.notificationCenter().postSystemNotification('Join me, maybe?', {body: 'Link copied to the clipboard'});
this.setState({shareOverlayVisible: false});
}
handleEmailButton(event) {
// if (navigator.userAgent.indexOf('Chrome') > 0) {
// let emailWindow = window.open(this.emailLink, '_blank');
// setTimeout(() => {
// emailWindow.close();
// }, 500);
// } else {
// window.open(this.emailLink, '_self');
// }
this.setState({shareOverlayVisible: false});
}
handleShareOverlayEntered() {
this.setState({shareOverlayVisible: true});
}
handleShareOverlayExited() {
this.setState({shareOverlayVisible: false});
}
handleActiveSpeakerSelected(participant, secondVideo=false) { // eslint-disable-line space-infix-ops
let newActiveSpeakers = this.state.activeSpeakers.slice();
if (secondVideo) {
if (participant.id !== 'none') {
if (newActiveSpeakers.length >= 1) {
newActiveSpeakers[1] = participant;
} else {
newActiveSpeakers[0] = participant;
}
} else {
newActiveSpeakers.splice(1,1);
}
} else {
if (participant.id !== 'none') {
newActiveSpeakers[0] = participant;
} else {
newActiveSpeakers.shift();
}
}
this.props.call.configureRoom(newActiveSpeakers.map((element) => element.publisherId), (error) => {
if (error) {
// This causes a state update, hence the drawer lists update
this.logEvent.error('set speakers failed', [], this.localIdentity);
}
});
}
handleDrop(files) {
DEBUG('Dropped file %o', files);
this.uploadFiles(files);
};
handleFiles(e) {
DEBUG('Selected files %o', e.target.files);
this.uploadFiles(e.target.files);
event.target.value = '';
}
uploadFiles(files) {
for (var key in files) {
// is the item a File?
if (files.hasOwnProperty(key) && files[key] instanceof File) {
let uploadRequest;
let complete = false;
const filename = files[key].name
let progressNotification = this.props.notificationCenter().postFileUploadProgress(
filename,
(notification) => {
if (!complete) {
uploadRequest.abort();
this.uploads.splice(this.uploads.indexOf(uploadRequest), 1);
}
}
);
uploadRequest = superagent
.post(`${config.fileSharingUrl}/${this.props.remoteUri}/${this.props.call.id}/${filename}`)
.send(files[key])
.on('progress', (e) => {
this.props.notificationCenter().editFileUploadNotification(e.percent, progressNotification);
})
.end((err, response) => {
complete = true;
this.props.notificationCenter().removeFileUploadNotification(progressNotification);
if (err) {
this.props.notificationCenter().postFileUploadFailed(filename);
}
this.uploads.splice(this.uploads.indexOf(uploadRequest), 1);
});
this.uploads.push([uploadRequest, progressNotification]);
}
}
}
downloadFile(filename) {
// const a = document.createElement('a');
// a.href = `${config.fileSharingUrl}/${this.props.remoteUri}/${this.props.call.id}/${filename}`;
// a.target = '_blank';
// a.download = filename;
// const clickEvent = document.createEvent('MouseEvent');
// clickEvent.initMouseEvent('click', true, true, window, 0,
// clickEvent.screenX, clickEvent.screenY, clickEvent.clientX, clickEvent.clientY,
// clickEvent.ctrlKey, clickEvent.altKey, clickEvent.shiftKey, clickEvent.metaKey,
// 0, null);
// a.dispatchEvent(clickEvent);
}
preventOverlay(event) {
// Stop the overlay when we are the thumbnail bar
event.stopPropagation();
}
muteAudio(event) {
event.preventDefault();
const localStream = this.props.call.getLocalStreams()[0];
if (localStream.getAudioTracks().length > 0) {
const track = localStream.getAudioTracks()[0];
if(this.state.audioMuted) {
DEBUG('Unmute microphone');
track.enabled = true;
this.setState({audioMuted: false});
} else {
DEBUG('Mute microphone');
track.enabled = false;
this.setState({audioMuted: true});
}
}
}
toggleCamera(event) {
event.preventDefault();
const localStream = this.props.call.getLocalStreams()[0];
if (localStream.getVideoTracks().length > 0) {
const track = localStream.getVideoTracks()[0];
track._switchCamera();
}
}
muteVideo(event) {
event.preventDefault();
const localStream = this.props.call.getLocalStreams()[0];
if (localStream.getVideoTracks().length > 0) {
const track = localStream.getVideoTracks()[0];
if (this.state.videoMuted) {
DEBUG('Unmute camera');
track.enabled = true;
this.setState({videoMuted: false});
} else {
DEBUG('Mute camera');
track.enabled = false;
this.setState({videoMuted: true});
}
}
}
hangup(event) {
event.preventDefault();
for (let participant of this.state.participants) {
participant.detach();
}
this.props.hangup();
}
armOverlayTimer() {
clearTimeout(this.overlayTimer);
this.overlayTimer = setTimeout(() => {
this.setState({callOverlayVisible: false});
}, 4000);
}
showOverlay() {
// if (!this.state.shareOverlayVisible && !this.state.showDrawer && !this.state.showFiles) {
// if (!this.state.callOverlayVisible) {
this.setState({callOverlayVisible: !this.state.callOverlayVisible});
// }
// this.armOverlayTimer();
// }
}
toggleInviteModal() {
this.setState({showInviteModal: !this.state.showInviteModal});
}
toggleDrawer() {
this.setState({callOverlayVisible: true, showDrawer: !this.state.showDrawer, showFiles: false});
clearTimeout(this.overlayTimer);
}
toggleFiles() {
this.setState({callOverlayVisible: true, showFiles: !this.state.showFiles, showDrawer: false});
clearTimeout(this.overlayTimer);
}
showFiles() {
this.setState({callOverlayVisible: true, showFiles: true, showDrawer: false});
clearTimeout(this.overlayTimer);
}
inviteParticipants(uris) {
console.log('Invite participants', uris);
this.props.saveInvitedParties(this.props.call.id, this.props.remoteUri.split('@')[0], uris);
this.props.call.inviteParticipants(uris);
}
render() {
if (this.props.call === null) {
return ();
}
let watermark;
const largeVideoClasses = classNames({
'animated' : true,
'fadeIn' : true,
'large' : true,
'mirror' : !this.props.call.sharingScreen && !this.props.generatedVideoTrack,
'fit' : this.props.call.sharingScreen
});
let matrixClasses = classNames({
'matrix' : true
});
const containerClasses = classNames({
'video-container': true,
'conference': true,
'drawer-visible': this.state.showDrawer || this.state.showFiles
});
const remoteUri = this.props.remoteUri.split('@')[0];
// const shareOverlay = (
//
//
//
//
// Invite other online users of this service, share this link with others or email, so they can easily join this conference.
//
//
//
//
//
//
//
//
//
//
//
// );
const buttons = {};
// const commonButtonTopClasses = classNames({
// 'btn' : true,
// 'btn-link' : true
// });
// const fullScreenButtonIcons = classNames({
// 'fa' : true,
// 'fa-2x' : true,
// 'fa-expand' : !this.isFullScreen(),
// 'fa-compress' : this.isFullScreen()
// });
const topButtons = [];
// if (!this.state.showFiles) {
// if (this.state.sharedFiles.length !== 0) {
// topButtons.push(
//
//
//
// );
// }
// }
if (!this.state.showDrawer) {
topButtons.push();
}
buttons.top = {right: topButtons};
const muteButtonIcons = this.state.audioMuted ? 'microphone-off' : 'microphone';
const muteVideoButtonIcons = this.state.videoMuted ? 'video-off' : 'video';
const buttonClass = (Platform.OS === 'ios') ? styles.iosButton : styles.androidButton;
const bottomButtons = [];
bottomButtons.push(
);
if (this.haveVideo) {
bottomButtons.push(
);
}
bottomButtons.push(
);
if (this.haveVideo) {
bottomButtons.push(
);
}
bottomButtons.push(
)
// bottomButtons.push(
//
//
//
// );
bottomButtons.push(
);
buttons.bottom = bottomButtons;
const participants = [];
if (this.state.participants.length > 0) {
if (this.state.activeSpeakers.findIndex((element) => {return element.id === this.props.call.id}) === -1) {
participants.push(
);
}
}
const drawerParticipants = [];
drawerParticipants.push(
);
let videos = [];
if (this.state.participants.length === 0) {
videos.push(
);
} else {
const activeSpeakers = this.state.activeSpeakers;
const activeSpeakersCount = activeSpeakers.length;
if (activeSpeakersCount > 0) {
activeSpeakers.forEach((p) => {
videos.push(
);
});
this.state.participants.forEach((p) => {
if (this.state.activeSpeakers.indexOf(p) === -1) {
participants.push(
{}}
+ pauseVideo={true}
+ display={true}
/>
);
}
drawerParticipants.push(
);
});
} else {
- this.state.participants.forEach((p) => {
+ this.state.participants.forEach((p, idx) => {
videos.push(
= 4) || (idx >= 2 && this.props.isTablet === false)}
+ isLandscape={this.props.isLandscape}
+ isTablet={this.props.isTablet}
+ useTwoRows={this.state.participants.length > 2}
/>
);
-
+ if (idx >= 4 || idx >= 2 && this.props.isTablet === false) {
+ participants.push(
+
+ );
+ }
drawerParticipants.push(
);
});
}
}
// let filesDrawerContent = (
//
// );
return (
{videos}
{participants}
{drawerParticipants}
);
}
}
ConferenceBox.propTypes = {
notificationCenter : PropTypes.func.isRequired,
call : PropTypes.object,
hangup : PropTypes.func,
saveParticipant : PropTypes.func,
saveInvitedParties : PropTypes.func,
previousParticipants: PropTypes.array,
remoteUri : PropTypes.string,
generatedVideoTrack : PropTypes.bool,
toggleSpeakerPhone : PropTypes.func,
speakerPhoneEnabled : PropTypes.bool,
isLandscape : PropTypes.bool,
isTablet : PropTypes.bool
};
export default ConferenceBox;
diff --git a/app/components/ConferenceMatrixParticipant.js b/app/components/ConferenceMatrixParticipant.js
index 904daa5..4d1edfd 100644
--- a/app/components/ConferenceMatrixParticipant.js
+++ b/app/components/ConferenceMatrixParticipant.js
@@ -1,138 +1,150 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
// const hark = require('hark');
import classNames from 'classnames';
import autoBind from 'auto-bind';
import { Paragraph, Badge } from 'react-native-paper';
import { RTCView } from 'react-native-webrtc';
import { View } from 'react-native';
import styles from '../assets/styles/blink/_ConferenceMatrixParticipant.scss';
class ConferenceMatrixParticipant extends Component {
constructor(props) {
super(props);
autoBind(this);
this.state = {
active: false,
hasVideo: false,
sharesScreen: false,
audioMuted: false,
stream: null
}
this.speechEvents = null;
this.videoElement = React.createRef();
if (!props.isLocal) {
props.participant.on('stateChanged', this.onParticipantStateChanged);
}
}
componentDidMount() {
this.maybeAttachStream();
+ if (!this.props.pauseVideo && this.props.participant.videoPaused) {
+ this.props.participant.resumeVideo();
+ }
// this.videoElement.current.oncontextmenu = (e) => {
// // disable right click for video elements
// e.preventDefault();
// };
// this.videoElement.current.onresize = (event) => {
// this.handleResize(event);
// };
}
componentWillUnmount() {
if (!this.props.isLocal) {
this.props.participant.removeListener('stateChanged', this.onParticipantStateChanged);
}
// if (this.speechEvents !== null) {
// this.speechEvents.stop();
// this.speechEvents = null;
// }
}
onParticipantStateChanged(oldState, newState) {
if (newState === 'established') {
this.maybeAttachStream();
}
}
handleResize(event) {
// console.log(event.srcElement.videoWidth);
const resolutions = ['1280x720', '960x540', '640x480', '640x360', '480x270', '320x180'];
if (this.state.hasVideo) {
const videoResolution = event.target.videoWidth + 'x' + event.target.videoHeight;
if (resolutions.indexOf(videoResolution) === -1) {
this.setState({sharesScreen: true});
} else {
this.setState({sharesScreen: false});
}
}
}
maybeAttachStream() {
const streams = this.props.participant.streams;
console.log(this.props.participant);
if (streams.length > 0) {
this.setState({stream: streams[0], hasVideo: streams[0].getVideoTracks().length > 0});
// const options = {
// interval: 150,
// play: false
// };
// this.speechEvents = hark(streams[0], options);
// this.speechEvents.on('speaking', () => {
// this.setState({active: true});
// });
// this.speechEvents.on('stopped_speaking', () => {
// this.setState({active: false});
// });
}
}
render() {
// const classes = classNames({
// 'poster' : !this.state.hasVideo,
// 'fit' : this.state.sharesScreen
// });
// const remoteVideoClasses = classNames({
// 'remote-video' : true,
// 'large' : this.props.large,
// 'conference-active' : this.state.active
// });
const participantInfo = (
{this.props.participant.identity.displayName || this.props.participant.identity.uri}
);
let activeIcon;
if (this.props.isLocal) {
activeIcon = (
Speaker
);
}
+ let style = null;
+ if (this.props.isTablet === true && this.props.useTwoRows) {
+ style = styles.portraitTabletContainer;
+ if (this.props.isLandscape) {
+ style = styles.landscapeTabletContainer;
+ }
+ }
return (
-
+
{activeIcon}
{/* {participantInfo} */}
);
}
}
ConferenceMatrixParticipant.propTypes = {
participant: PropTypes.object.isRequired,
large: PropTypes.bool,
- isLocal: PropTypes.bool
+ isLocal: PropTypes.bool,
+ isTablet: PropTypes.bool,
+ isLandscape: PropTypes.bool
};
export default ConferenceMatrixParticipant;
diff --git a/app/components/ConferenceParticipant.js b/app/components/ConferenceParticipant.js
index d64bed7..3b2e48e 100644
--- a/app/components/ConferenceParticipant.js
+++ b/app/components/ConferenceParticipant.js
@@ -1,134 +1,147 @@
import React from 'react';
import PropTypes from 'prop-types';
// const hark = require('hark');
-import { View } from 'react-native';
+import { View, TouchableWithoutFeedback } from 'react-native';
import classNames from 'classnames';
import autoBind from 'auto-bind';
import { IconButton, Surface } from 'react-native-paper';
import { RTCView } from 'react-native-webrtc';
+import UserIcon from './UserIcon';
+
import styles from '../assets/styles/blink/_ConferenceParticipant.scss';
class ConferenceParticipant extends React.Component {
constructor(props) {
super(props);
autoBind(this);
this.state = {
active: false,
hasVideo: false,
overlayVisible: false,
audioMuted: false,
stream: null
}
this.speechEvents = null;
this.videoElement = React.createRef();
props.participant.on('stateChanged', this.onParticipantStateChanged);
}
componentDidMount() {
this.maybeAttachStream();
// this.videoElement.current.oncontextmenu = (e) => {
// // disable right click for video elements
// e.preventDefault();
// };
}
componentWillUnmount() {
//this.videoElement.current.pause();
this.props.participant.removeListener('stateChanged', this.onParticipantStateChanged);
if (this.speechEvents !== null) {
this.speechEvents.stop();
this.speechEvents = null;
}
}
onParticipantStateChanged(oldState, newState) {
if (newState === 'established') {
this.maybeAttachStream();
}
}
onMuteAudioClicked(event) {
event.preventDefault();
const streams = this.props.participant.streams;
if (streams[0].getAudioTracks().length > 0) {
const track = streams[0].getAudioTracks()[0];
if(this.state.audioMuted) {
track.enabled = true;
this.setState({audioMuted: false});
} else {
track.enabled = false;
this.setState({audioMuted: true});
}
}
}
maybeAttachStream() {
const streams = this.props.participant.streams;
if (streams.length > 0) {
this.setState({stream: streams[0], hasVideo: streams[0].getVideoTracks().length > 0});
+ if (this.props.pauseVideo) {
+ this.props.participant.pauseVideo();
+ }
// const options = {
// interval: 150,
// play: false
// };
// this.speechEvents = hark(streams[0], options);
// this.speechEvents.on('speaking', () => {
// this.setState({active: true});
// });
// this.speechEvents.on('stopped_speaking', () => {
// this.setState({active: false});
// });
}
}
showOverlay() {
this.setState({overlayVisible: true});
}
hideOverlay() {
if (!this.state.audioMuted) {
this.setState({overlayVisible: false});
}
}
render() {
// const tooltip = (
// {this.props.participant.identity.displayName || this.props.participant.identity.uri}
// );
const classes = classNames({
'poster' : !this.state.hasVideo,
'conference-active' : this.state.active
});
let muteButton;
if (this.state.overlayVisible) {
const muteButtonIcons = this.state.audioMuted ? 'microphone-off' : 'microphone';
muteButton = (
);
}
+ let icon;
+ if (this.props.pauseVideo && this.props.display) {
+ icon = this.props.selected(this.props.participant)}>;
+ }
return (
-
+
{muteButton}
+ {icon}
{/* */}
-
+
{/* */}
);
}
}
ConferenceParticipant.propTypes = {
- participant: PropTypes.object.isRequired
+ participant: PropTypes.object.isRequired,
+ display: PropTypes.bool,
+ pauseVideo: PropTypes.bool,
+ selected: PropTypes.func
};
export default ConferenceParticipant;