provide UI feedback for remote hangup

This commit is contained in:
or-else
2022-06-03 16:50:06 -07:00
parent ae15a043b1
commit 4e720a0d5b
6 changed files with 339 additions and 459 deletions
Binary file not shown.
+31 -8
View File
@@ -11,6 +11,8 @@ import { clipStr } from '../lib/utils.js'
const RING_SOUND = new Audio('audio/call-out.m4a'); const RING_SOUND = new Audio('audio/call-out.m4a');
RING_SOUND.loop = true; RING_SOUND.loop = true;
const CALL_ENDED_SOUND = new Audio('audio/call-end.m4a');
CALL_ENDED_SOUND.loop = true;
const messages = defineMessages({ const messages = defineMessages({
already_in_call: { already_in_call: {
@@ -28,7 +30,8 @@ class CallPanel extends React.PureComponent {
localStream: undefined, localStream: undefined,
pc: undefined, pc: undefined,
previousOnInfo: undefined previousOnInfo: undefined,
waitingForPeer: false
}; };
this.localStreamConstraints = { this.localStreamConstraints = {
@@ -134,7 +137,7 @@ class CallPanel extends React.PureComponent {
// Start local video. // Start local video.
navigator.mediaDevices.getUserMedia(this.localStreamConstraints) navigator.mediaDevices.getUserMedia(this.localStreamConstraints)
.then(stream => { .then(stream => {
this.setState({localStream: stream}); this.setState({localStream: stream, waitingForPeer: true});
this.localRef.current.srcObject = stream; this.localRef.current.srcObject = stream;
RING_SOUND.play(); RING_SOUND.play();
@@ -146,6 +149,8 @@ class CallPanel extends React.PureComponent {
} }
stop() { stop() {
CALL_ENDED_SOUND.pause();
CALL_ENDED_SOUND.currentTime = 0;
RING_SOUND.pause(); RING_SOUND.pause();
RING_SOUND.currentTime = 0; RING_SOUND.currentTime = 0;
@@ -163,7 +168,7 @@ class CallPanel extends React.PureComponent {
this.state.pc.close(); this.state.pc.close();
} }
this.setState({pc: null}); this.setState({pc: null, waitingForPeer: false});
} }
stopTracks(el) { stopTracks(el) {
@@ -197,7 +202,7 @@ class CallPanel extends React.PureComponent {
pc.onnegotiationneeded = this.handleNegotiationNeededEvent; pc.onnegotiationneeded = this.handleNegotiationNeededEvent;
pc.ontrack = this.handleTrackEvent; pc.ontrack = this.handleTrackEvent;
this.setState({pc: pc}); this.setState({pc: pc, waitingForPeer: false});
return pc; return pc;
} }
@@ -264,14 +269,15 @@ class CallPanel extends React.PureComponent {
switch(e.name) { switch(e.name) {
case 'NotFoundError': case 'NotFoundError':
// Cannot start the call b/c no camera and/or microphone found. // Cannot start the call b/c no camera and/or microphone found.
this.reportError(e); this.reportError(e.message);
break; break;
case 'SecurityError': case 'SecurityError':
case 'PermissionDeniedError': case 'PermissionDeniedError':
// Do nothing; this is the same as the user canceling the call. // Do nothing; this is the same as the user canceling the call.
break; break;
default: default:
console.log('Error opening your camera and/or microphone: ' + e.message); this.reportError(e.message);
console.error('Error opening your camera and/or microphone: ' + e.message);
break; break;
} }
@@ -309,8 +315,24 @@ class CallPanel extends React.PureComponent {
.catch(this.handleGetUserMediaError); .catch(this.handleGetUserMediaError);
} }
// Call disconnected by remote.
handleRemoteHangup() { handleRemoteHangup() {
this.handleCloseClick(); if (!this.state.waitingForPeer) {
// This is live call, just hang up.
this.handleCloseClick();
} else {
// This is a call which is not yet connected.
// Stop pulse animation.
this.setState({waitingForPeer: false});
// Change sound and wait a bit before ending it.
RING_SOUND.pause();
RING_SOUND.currentTime = 0;
CALL_ENDED_SOUND.loop = true;
CALL_ENDED_SOUND.play();
setTimeout(_ => {
this.handleCloseClick();
}, 2000);
}
} }
handleCloseClick() { handleCloseClick() {
@@ -345,6 +367,7 @@ class CallPanel extends React.PureComponent {
const audioIcon = this.state.localStream && this.state.localStream.getAudioTracks()[0].enabled ? 'mic' : 'mic_off'; const audioIcon = this.state.localStream && this.state.localStream.getAudioTracks()[0].enabled ? 'mic' : 'mic_off';
const videoIcon = this.state.localStream && this.state.localStream.getVideoTracks()[0].enabled ? 'videocam' : 'videocam_off'; const videoIcon = this.state.localStream && this.state.localStream.getVideoTracks()[0].enabled ? 'videocam' : 'videocam_off';
const peerTitle = clipStr(this.props.title, MAX_PEER_TITLE_LENGTH); const peerTitle = clipStr(this.props.title, MAX_PEER_TITLE_LENGTH);
const pulseAnimation = this.state.waitingForPeer ? ' pulse' : '';
return ( return (
<> <>
@@ -361,7 +384,7 @@ class CallPanel extends React.PureComponent {
<video ref={this.remoteRef} autoPlay playsInline></video> <video ref={this.remoteRef} autoPlay playsInline></video>
{remoteActive ? {remoteActive ?
<div className="caller-name inactive">{peerTitle}</div> : <div className="caller-name inactive">{peerTitle}</div> :
<div className="caller-card pulse"> <div className={`caller-card${pulseAnimation}`}>
<div className="avatar-box"> <div className="avatar-box">
<LetterTile <LetterTile
tinode={this.props.tinode} tinode={this.props.tinode}
+305 -448
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long