diff --git a/app/components/AudioCallBox.js b/app/components/AudioCallBox.js
index 66805be..d8066b4 100644
--- a/app/components/AudioCallBox.js
+++ b/app/components/AudioCallBox.js
@@ -1,282 +1,259 @@
import React, { Component } from 'react';
import { View, Platform } from 'react-native';
import { IconButton, Dialog, Text, ActivityIndicator, Colors } from 'react-native-paper';
-
import PropTypes from 'prop-types';
import autoBind from 'auto-bind';
-import Logger from "../../Logger";
+import EscalateConferenceModal from './EscalateConferenceModal';
import CallOverlay from './CallOverlay';
import DTMFModal from './DTMFModal';
-import EscalateConferenceModal from './EscalateConferenceModal';
import UserIcon from './UserIcon';
-
-import utils from '../utils';
-
import styles from '../assets/styles/blink/_AudioCallBox.scss';
-
-const logger = new Logger("AudioCallBox");
+import utils from '../utils';
class AudioCallBox extends Component {
constructor(props) {
super(props);
autoBind(this);
- this.userHangup = false;
-
this.state = {
active : false,
audioMuted : false,
showDtmfModal : false,
showEscalateConferenceModal : false,
call : this.props.call,
reconnectingCall : this.props.reconnectingCall
};
- // this.speechEvents = null;
this.remoteAudio = React.createRef();
+ this.userHangup = false;
}
componentDidMount() {
// This component is used both for as 'local media' and as the in-call component.
// Thus, if the call is not null it means we are beyond the 'local media' phase
// so don't call the mediaPlaying prop.
if (this.state.call != null) {
switch (this.state.call.state) {
case 'established':
this.attachStream(this.state.call);
break;
case 'incoming':
this.props.mediaPlaying();
// fall through
default:
this.state.call.on('stateChanged', this.callStateChanged);
break;
}
} else {
this.props.mediaPlaying();
}
}
componentWillUnmount() {
if (this.state.call != null) {
this.state.call.removeListener('stateChanged', this.callStateChanged);
}
}
//getDerivedStateFromProps(nextProps, state) {
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.call && nextProps.call !== this.state.call) {
if (nextProps.call.state === 'established') {
this.attachStream(nextProps.call);
this.setState({reconnectingCall: false});
}
nextProps.call.on('stateChanged', this.callStateChanged);
if (this.state.call !== null) {
this.state.call.removeListener('stateChanged', this.callStateChanged);
}
this.setState({call: nextProps.call});
}
if (nextProps.reconnectingCall != this.state.reconnectingCall) {
console.log('Audio box got prop reconnecting', nextProps.reconnectingCall);
this.setState({reconnectingCall: nextProps.reconnectingCall});
}
}
componentWillUnmount() {
if (this.state.call != null) {
this.state.call.removeListener('stateChanged', this.callStateChanged);
}
clearTimeout(this.callTimer);
}
callStateChanged(oldState, newState, data) {
if (newState === 'established') {
this.attachStream(this.state.call);
this.setState({reconnectingCall: false});
}
}
attachStream(call) {
this.setState({stream: call.getRemoteStreams()[0]}); //we dont use it anywhere though as audio gets automatically piped
- // const options = {
- // interval: 225,
- // play: false
- // };
- // this.speechEvents = hark(remoteStream, options);
- // this.speechEvents.on('speaking', () => {
- // this.setState({active: true});
- // });
- // this.speechEvents.on('stopped_speaking', () => {
- // this.setState({active: false});
- // });
}
escalateToConference(participants) {
this.props.escalateToConference(participants);
}
hangupCall(event) {
event.preventDefault();
this.props.hangupCall('user_press_hangup');
this.userHangup = true;
}
cancelCall(event) {
event.preventDefault();
this.props.hangupCall('user_cancelled');
}
muteAudio(event) {
event.preventDefault();
const localStream = this.state.call.getLocalStreams()[0];
const track = localStream.getAudioTracks()[0];
if(this.state.audioMuted) {
- //console.log('Unmute microphone');
this.state.callKeepToggleMute(false);
track.enabled = true;
this.setState({audioMuted: false});
} else {
- //console.log('Mute microphone');
track.enabled = false;
this.state.callKeepToggleMute(true);
this.setState({audioMuted: true});
}
}
showDtmfModal() {
this.setState({showDtmfModal: true});
}
hideDtmfModal() {
this.setState({showDtmfModal: false});
}
toggleEscalateConferenceModal() {
this.setState({
showEscalateConferenceModal: !this.state.showEscalateConferenceModal
});
}
-// {this.props.orientation !== 'landscape' && !this.userHangup && (!this.state.call || (this.state.call && this.state.call.state !== 'established')) ?
-
render() {
let remoteIdentity = {uri: this.props.remoteUri, displayName: this.props.remoteDisplayName};
-
- const buttonClass = (Platform.OS === 'ios') ? styles.iosButton : styles.androidButton;
let displayName = (this.props.remoteDisplayName && this.props.remoteUri !== this.props.remoteDisplayName) ? this.props.remoteDisplayName: this.props.remoteUri;
let buttonContainerClass = this.props.orientation === 'landscape' ? styles.landscapeButtonContainer : styles.portraitButtonContainer;
- //console.log('Audio box reconnecting', this.state.reconnectingCall);
+
+ const buttonSize = 34;
+ const buttonClass = (Platform.OS === 'ios') ? styles.iosButton : styles.androidButton;
return (
{displayName}
{ (this.props.remoteDisplayName && this.props.remoteUri !== this.props.remoteDisplayName) ?
{this.props.remoteUri}
: null }
{this.props.orientation !== 'landscape' && !this.userHangup && this.state.reconnectingCall ?
:
null
}
{this.state.call && this.state.call.state === 'established' ?
:
}
);
}
}
AudioCallBox.propTypes = {
remoteUri : PropTypes.string.isRequired,
remoteDisplayName : PropTypes.string,
call : PropTypes.object,
connection : PropTypes.object,
accountId : PropTypes.string,
escalateToConference : PropTypes.func,
hangupCall : PropTypes.func,
mediaPlaying : PropTypes.func,
callKeepSendDtmf : PropTypes.func,
callKeepToggleMute : PropTypes.func,
toggleSpeakerPhone : PropTypes.func,
speakerPhoneEnabled : PropTypes.bool,
orientation : PropTypes.string,
isTablet : PropTypes.bool,
reconnectingCall : PropTypes.bool
};
export default AudioCallBox;
diff --git a/app/components/ReadyBox.js b/app/components/ReadyBox.js
index 0d60782..d59d100 100644
--- a/app/components/ReadyBox.js
+++ b/app/components/ReadyBox.js
@@ -1,265 +1,261 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
-// import VizSensor = require('react-visibility-sensor').default;
import autoBind from 'auto-bind';
import { View, Platform} from 'react-native';
import { IconButton, Title, Button } from 'react-native-paper';
import ConferenceModal from './ConferenceModal';
import HistoryTileBox from './HistoryTileBox';
import FooterBox from './FooterBox';
import URIInput from './URIInput';
import config from '../config';
import utils from '../utils';
-
import styles from '../assets/styles/blink/_ReadyBox.scss';
+
class ReadyBox extends Component {
constructor(props) {
super(props);
autoBind(this);
this.state = {
- targetUri: this.props.missedTargetUri,
+ targetUri: '',
contacts: this.props.contacts,
selectedContact: null,
showConferenceModal: false,
sticky: false,
favoriteUris: this.props.favoriteUris,
blockedUris: this.props.blockedUris,
historyFilter: null
};
}
getTargetUri() {
const defaultDomain = this.props.account.id.substring(this.props.account.id.indexOf('@') + 1);
return utils.normalizeUri(this.state.targetUri, defaultDomain);
}
async componentDidMount() {
- //console.log('Ready now');
if (this.state.targetUri) {
console.log('We must call', this.state.targetUri);
}
}
filterHistory(filter) {
- //console.log('set historyFilter', filter);
this.setState({'historyFilter': filter});
this.handleTargetChange('');
}
handleTargetChange(value, contact) {
let new_value = value;
if (contact) {
if (this.state.targetUri === contact.uri) {
new_value = '';
}
}
if (this.state.targetUri === value) {
new_value = '';
}
if (new_value === '') {
contact = null;
}
this.setState({targetUri: new_value, selectedContact: contact});
}
handleTargetSelect() {
if (this.props.connection === null) {
this.props._notificationCenter.postSystemNotification("Server unreachable", {timeout: 2});
return;
}
// the user pressed enter, start a video call by default
if (this.state.targetUri.endsWith(`@${config.defaultConferenceDomain}`)) {
this.props.startConference(this.state.targetUri, {audio: true, video: true});
} else {
this.props.startCall(this.getTargetUri(), {audio: true, video: true});
}
}
showConferenceModal(event) {
event.preventDefault();
if (this.state.targetUri.length !== 0) {
const uri = `${this.state.targetUri.split('@')[0].replace(/[\s()-]/g, '')}@${config.defaultConferenceDomain}`;
this.handleConferenceCall(uri.toLowerCase());
} else {
this.setState({showConferenceModal: true});
}
}
handleAudioCall(event) {
event.preventDefault();
if (this.state.targetUri.endsWith(`@${config.defaultConferenceDomain}`)) {
this.props.startConference(this.state.targetUri, {audio: true, video: false});
} else {
this.props.startCall(this.getTargetUri(), {audio: true, video: false});
}
}
handleVideoCall(event) {
event.preventDefault();
if (this.state.targetUri.endsWith(`@${config.defaultConferenceDomain}`)) {
this.props.startConference(this.state.targetUri, {audio: true, video: false});
} else {
this.props.startCall(this.getTargetUri(), {audio: true, video: true});
}
}
handleConferenceCall(targetUri, options={audio: true, video: true, conference: true}) {
if (targetUri) {
this.props.startConference(targetUri, options);
}
this.setState({showConferenceModal: false});
}
render() {
//utils.timestampedLog('Render ready');
const defaultDomain = `${config.defaultDomain}`;
let uriClass = styles.portraitUriInputBox;
let uriGroupClass = styles.portraitUriButtonGroup;
let titleClass = styles.portraitTitle;
const buttonClass = (Platform.OS === 'ios') ? styles.iosButton : styles.androidButton;
if (this.props.isTablet) {
titleClass = this.props.orientation === 'landscape' ? styles.landscapeTabletTitle : styles.portraitTabletTitle;
} else {
titleClass = this.props.orientation === 'landscape' ? styles.landscapeTitle : styles.portraitTitle;
}
if (this.props.isTablet) {
uriGroupClass = this.props.orientation === 'landscape' ? styles.landscapeTabletUriButtonGroup : styles.portraitTabletUriButtonGroup;
} else {
uriGroupClass = this.props.orientation === 'landscape' ? styles.landscapeUriButtonGroup : styles.portraitUriButtonGroup;
}
if (this.props.isTablet) {
uriClass = this.props.orientation === 'landscape' ? styles.landscapeTabletUriInputBox : styles.portraitTabletUriInputBox;
} else {
uriClass = this.props.orientation === 'landscape' ? styles.landscapeUriInputBox : styles.portraitUriInputBox;
}
const historyClass = this.props.orientation === 'landscape' ? styles.landscapeHistory : styles.portraitHistory;
return (
{((this.state.favoriteUris.length > 0 || this.state.blockedUris.length > 0 ) ||
(this.state.favoriteUris.length === 0 && this.state.historyFilter === 'favorite') ||
(this.state.blockedUris.length === 0 && this.state.historyFilter === 'blocked')
) ?
{(this.state.favoriteUris.length > 0 && this.state.historyFilter !== 'favorite')? : null}
{(this.state.blockedUris.length > 0 && this.state.historyFilter !== 'blocked')? : null}
: null}
{this.props.isTablet && 0?
: null}
);
}
}
ReadyBox.propTypes = {
account : PropTypes.object.isRequired,
password : PropTypes.string.isRequired,
config : PropTypes.object.isRequired,
startCall : PropTypes.func.isRequired,
startConference : PropTypes.func.isRequired,
- missedTargetUri : PropTypes.string,
contacts : PropTypes.array,
orientation : PropTypes.string,
isTablet : PropTypes.bool,
refreshHistory : PropTypes.bool,
cacheHistory : PropTypes.func,
serverHistory : PropTypes.array,
localHistory : PropTypes.array,
myDisplayName : PropTypes.string,
myPhoneNumber : PropTypes.string,
deleteHistoryEntry: PropTypes.func,
setFavoriteUri : PropTypes.func,
setBlockedUri : PropTypes.func,
favoriteUris : PropTypes.array,
blockedUris : PropTypes.array
};
export default ReadyBox;
diff --git a/app/components/VideoBox.js b/app/components/VideoBox.js
index b11621d..0892732 100644
--- a/app/components/VideoBox.js
+++ b/app/components/VideoBox.js
@@ -1,445 +1,361 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
+import dtmf from 'react-native-dtmf';
import debug from 'react-native-debug';
import autoBind from 'auto-bind';
import { IconButton, ActivityIndicator, Colors } from 'react-native-paper';
import { View, Dimensions, TouchableWithoutFeedback, Platform } from 'react-native';
import { RTCView } from 'react-native-webrtc';
import CallOverlay from './CallOverlay';
import EscalateConferenceModal from './EscalateConferenceModal';
import DTMFModal from './DTMFModal';
import config from '../config';
-import dtmf from 'react-native-dtmf';
-
import styles from '../assets/styles/blink/_VideoBox.scss';
const DEBUG = debug('blinkrtc:Video');
debug.enable('*');
+
class VideoBox extends Component {
constructor(props) {
super(props);
autoBind(this);
- this.userHangup = false;
this.state = {
callOverlayVisible: true,
audioMuted: false,
videoMuted: false,
localVideoShow: false,
remoteVideoShow: false,
remoteSharesScreen: false,
showEscalateConferenceModal: false,
localStream: null,
remoteStream: null,
showDtmfModal: false,
doorOpened: false
};
this.overlayTimer = null;
this.localVideo = React.createRef();
this.remoteVideo = React.createRef();
+ this.userHangup = false;
}
callStateChanged(oldState, newState, data) {
this.forceUpdate();
}
openDoor() {
const tone = this.props.intercomDtmfTone;
DEBUG('DTMF tone sent to intercom: ' + tone);
this.setState({doorOpened: true});
this.forceUpdate();
dtmf.stopTone(); //don't play a tone at the same time as another
dtmf.playTone(dtmf['DTMF_' + tone], 1000);
if (this.props.call !== null && this.props.call.state === 'established') {
this.props.call.sendDtmf(tone);
/*this.props.notificationCenter.postSystemNotification('Door opened', {timeout: 5});*/
}
}
componentDidMount() {
- /*
- console.log('VideoBox: did mount');
- console.log('Call is', this.props.call);
- console.log('localStreams', this.props.call.getLocalStreams());
- console.log('remoteStreams', this.props.call.getRemoteStreams());
- */
-
this.setState({
localStream: this.props.call.getLocalStreams()[0],
localVideoShow: true,
remoteStream: this.props.call.getRemoteStreams()[0],
remoteVideoShow: true
});
- this.props.call.on('stateChanged', this.callStateChanged);
-
- // sylkrtc.utils.attachMediaStream(, this.localVideo.current, {disableContextMenu: true});
- // let promise = this.localVideo.current.play()
- // if (promise !== undefined) {
- // promise.then(_ => {
- // this.setState({localVideoShow: true}); // eslint-disable-line react/no-did-mount-set-state
- // // Autoplay started!
- // }).catch(error => {
- // // Autoplay was prevented.
- // // Show a "Play" button so that user can start playback.
- // });
- // } else {
- // this.localVideo.current.addEventListener('playing', () => {
- // this.setState({}); // eslint-disable-line react/no-did-mount-set-state
- // });
- // }
-
- // this.remoteVideo.current.addEventListener('playing', this.handleRemoteVideoPlaying);
- // sylkrtc.utils.attachMediaStream(this.props.call.getRemoteStreams()[0], this.remoteVideo.current, {disableContextMenu: true});
+ if (this.props.call) {
+ this.props.call.on('stateChanged', this.callStateChanged);
+ }
this.armOverlayTimer();
}
componentWillUnmount() {
- // clearTimeout(this.overlayTimer);
- // this.remoteVideo.current.removeEventListener('playing', this.handleRemoteVideoPlaying);
- // this.exitFullscreen();
if (this.props.call != null) {
this.props.call.removeListener('stateChanged', this.callStateChanged);
}
}
showDtmfModal() {
this.setState({showDtmfModal: true});
}
hideDtmfModal() {
this.setState({showDtmfModal: false});
}
handleFullscreen(event) {
event.preventDefault();
// this.toggleFullscreen();
}
handleRemoteVideoPlaying() {
this.setState({remoteVideoShow: true});
- // this.remoteVideo.current.onresize = (event) => {
- // this.handleRemoteResize(event)
- // };
- // this.armOverlayTimer();
}
handleRemoteResize(event, target) {
- //DEBUG("%o", event);
const resolutions = [ '1280x720', '960x540', '640x480', '640x360', '480x270','320x180'];
const videoResolution = event.target.videoWidth + 'x' + event.target.videoHeight;
if (resolutions.indexOf(videoResolution) === -1) {
this.setState({remoteSharesScreen: true});
} else {
this.setState({remoteSharesScreen: false});
}
}
muteAudio(event) {
event.preventDefault();
const localStream = this.state.localStream;
if (localStream.getAudioTracks().length > 0) {
const track = localStream.getAudioTracks()[0];
if(this.state.audioMuted) {
DEBUG('Unmute microphone');
track.enabled = true;
this.props.callKeepToggleMute(false);
this.setState({audioMuted: false});
} else {
DEBUG('Mute microphone');
track.enabled = false;
this.props.callKeepToggleMute(true);
this.setState({audioMuted: true});
}
}
}
muteVideo(event) {
event.preventDefault();
const localStream = this.state.localStream;
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});
}
}
}
toggleCamera(event) {
event.preventDefault();
const localStream = this.state.localStream;
if (localStream.getVideoTracks().length > 0) {
const track = localStream.getVideoTracks()[0];
track._switchCamera();
}
}
hangupCall(event) {
event.preventDefault();
this.props.hangupCall('user_press_hangup');
this.userHangup = true;
}
cancelCall(event) {
event.preventDefault();
this.props.hangupCall('user_cancelled');
}
escalateToConference(participants) {
this.props.escalateToConference(participants);
}
armOverlayTimer() {
clearTimeout(this.overlayTimer);
this.overlayTimer = setTimeout(() => {
this.setState({callOverlayVisible: false});
}, 4000);
}
toggleCallOverlay() {
this.setState({callOverlayVisible: !this.state.callOverlayVisible});
}
toggleEscalateConferenceModal() {
this.setState({
callOverlayVisible : false,
showEscalateConferenceModal : !this.state.showEscalateConferenceModal
});
}
render() {
- if (this.props.call == null) {
+ if (this.props.call === null) {
return null;
}
- //console.log('Render Video Box in state', this.props.call.state);
+ // 'mirror' : !this.props.call.sharingScreen && !this.props.generatedVideoTrack,
+ // we do not want mirrored local video once the call has started, just in preview
const localVideoClasses = classNames({
'video-thumbnail' : true,
- 'mirror' : !this.props.call.sharingScreen && !this.props.generatedVideoTrack,
'hidden' : !this.state.localVideoShow,
'animated' : true,
'fadeIn' : this.state.localVideoShow || this.state.videoMuted,
'fadeOut' : this.state.videoMuted,
'fit' : this.props.call.sharingScreen
});
const remoteVideoClasses = classNames({
'poster' : !this.state.remoteVideoShow,
'animated' : true,
'fadeIn' : this.state.remoteVideoShow,
'large' : true,
'fit' : this.state.remoteSharesScreen
});
- // let callButtons;
- // let watermark;
-
let buttons;
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 buttonContainerClass = this.props.orientation === 'landscape' ? styles.landscapeButtonContainer : styles.portraitButtonContainer;
+ const buttonSize = 34;
if (this.state.callOverlayVisible) {
- // const screenSharingButtonIcons = classNames({
- // 'fa' : true,
- // 'fa-clone' : true,
- // 'fa-flip-horizontal' : true,
- // 'text-warning' : this.props.call.sharingScreen
- // });
-
- // const fullScreenButtonIcons = classNames({
- // 'fa' : true,
- // 'fa-expand' : !this.isFullScreen(),
- // 'fa-compress' : this.isFullScreen()
- // });
-
- // const commonButtonClasses = classNames({
- // 'btn' : true,
- // 'btn-round' : true,
- // 'btn-default' : true
- // });
- // const buttons = [];
-
- // buttons.push();
- // if (this.isFullscreenSupported()) {
- // buttons.push();
- // }
- // buttons.push(
);
-
- // callButtons = (
- // //
-
- // //
- // );
let content = (
);
if (this.props.intercomDtmfTone) {
content = (
);
}
buttons = ({content});
- } else {
- // watermark = (
- //
- //
- //
- // );
}
- //console.log('local media stream in videobox', this.state);
-
return (
- {/* */}
- {/* {watermark} */}
- {/* */}
{this.state.remoteVideoShow && !this.props.reconnectingCall ?
: null }
{ this.state.localVideoShow ?
: null }
{this.props.reconnectingCall
?
: null
}
{buttons}
);
}
}
VideoBox.propTypes = {
call : PropTypes.object,
connection : PropTypes.object,
accountId : PropTypes.string,
remoteUri : PropTypes.string,
remoteDisplayName : PropTypes.string,
localMedia : PropTypes.object,
hangupCall : PropTypes.func,
shareScreen : PropTypes.func,
escalateToConference : PropTypes.func,
generatedVideoTrack : PropTypes.bool,
callKeepSendDtmf : PropTypes.func,
callKeepToggleMute : PropTypes.func,
toggleSpeakerPhone : PropTypes.func,
speakerPhoneEnabled : PropTypes.bool,
intercomDtmfTone : PropTypes.string,
orientation : PropTypes.string,
isTablet : PropTypes.bool,
reconnectingCall : PropTypes.bool
};
export default VideoBox;