Video calls: some more cleaup.
This commit is contained in:
+20
-1
@@ -2633,7 +2633,12 @@ video {
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#video-call-hangup {
|
.video-call-accept {
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-call-hangup {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: red;
|
background-color: red;
|
||||||
}
|
}
|
||||||
@@ -2642,3 +2647,17 @@ video {
|
|||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: gray;
|
background-color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.incoming-call-title {
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incoming-call-badges {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incoming-call-actions {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -209,3 +209,8 @@ export function cancelablePromise(promise) {
|
|||||||
export function isVideoCall(mime) {
|
export function isVideoCall(mime) {
|
||||||
return mime == 'application/tinode-video-call';
|
return mime == 'application/tinode-video-call';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clips string to the specified length.
|
||||||
|
export function clipStr(str, length) {
|
||||||
|
return str && str.substring(0, length);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// InfoView: panel with topic/user info.
|
// IncomingCallView: displays Accept & Reject buttons for incoming calls.
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
import Tinode from 'tinode-sdk';
|
import Tinode from 'tinode-sdk';
|
||||||
|
|
||||||
@@ -8,18 +8,14 @@ import AvatarUpload from '../widgets/avatar-upload.jsx';
|
|||||||
import BadgeList from '../widgets/badge-list.jsx';
|
import BadgeList from '../widgets/badge-list.jsx';
|
||||||
import MenuCancel from '../widgets/menu-cancel.jsx';
|
import MenuCancel from '../widgets/menu-cancel.jsx';
|
||||||
|
|
||||||
import { MAX_TITLE_LENGTH, MAX_TOPIC_DESCRIPTION_LENGTH, NO_ACCESS_MODE } from '../config.js';
|
import { CALL_STATE_INCOMING_RECEIVED, MAX_TITLE_LENGTH } from '../config.js';
|
||||||
|
|
||||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
import { makeImageUrl } from '../lib/blob-helpers.js';
|
||||||
import { arrayEqual, theCard } from '../lib/utils.js';
|
import { clipStr } from '../lib/utils.js'
|
||||||
|
|
||||||
function _clip(str, length) {
|
|
||||||
return str && str.substring(0, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
const RING_SOUND = new Audio("audio/phone_ring.mp3");
|
const RING_SOUND = new Audio("audio/phone_ring.mp3");
|
||||||
|
|
||||||
class CallView extends React.Component {
|
class IncomingCallView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@@ -29,7 +25,6 @@ class CallView extends React.Component {
|
|||||||
avatar: null,
|
avatar: null,
|
||||||
trustedBadges: [],
|
trustedBadges: [],
|
||||||
previousMetaDesc: undefined,
|
previousMetaDesc: undefined,
|
||||||
offerSent: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.resetDesc = this.resetDesc.bind(this);
|
this.resetDesc = this.resetDesc.bind(this);
|
||||||
@@ -45,7 +40,7 @@ class CallView extends React.Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.resetDesc(topic, this.props);
|
this.resetDesc(topic, this.props);
|
||||||
if (this.props.callState == 2) {
|
if (this.props.callState == CALL_STATE_INCOMING_RECEIVED) {
|
||||||
RING_SOUND.play();
|
RING_SOUND.play();
|
||||||
this.ringTimer = setInterval(() => RING_SOUND.play(), 2000);
|
this.ringTimer = setInterval(() => RING_SOUND.play(), 2000);
|
||||||
this.props.onRinging(this.props.topic, this.props.seq);
|
this.props.onRinging(this.props.topic, this.props.seq);
|
||||||
@@ -96,7 +91,7 @@ class CallView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
fullName: _clip(topic.public ? topic.public.fn : undefined, MAX_TITLE_LENGTH),
|
fullName: clipStr(topic.public ? topic.public.fn : undefined, MAX_TITLE_LENGTH),
|
||||||
avatar: makeImageUrl(topic.public ? topic.public.photo : null),
|
avatar: makeImageUrl(topic.public ? topic.public.photo : null),
|
||||||
trustedBadges: badges,
|
trustedBadges: badges,
|
||||||
});
|
});
|
||||||
@@ -126,16 +121,9 @@ class CallView extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const {formatMessage} = this.props.intl;
|
const {formatMessage} = this.props.intl;
|
||||||
let panelTitle = 'Unknown';
|
let panelTitle = 'Unknown';
|
||||||
switch (this.props.callState) {
|
if (this.props.callState == CALL_STATE_INCOMING_RECEIVED) {
|
||||||
case 1:
|
panelTitle = <FormattedMessage id="calls_incoming_title"
|
||||||
panelTitle = 'Calling';
|
defaultMessage="Incoming Call" description="Incoming call title (Incoming call view)" />;
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
panelTitle = 'Incoming Call From';
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
panelTitle = 'Call Established';
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -156,24 +144,22 @@ class CallView extends React.Component {
|
|||||||
uid={this.props.topic}
|
uid={this.props.topic}
|
||||||
title={this.state.fullName} />
|
title={this.state.fullName} />
|
||||||
</center>
|
</center>
|
||||||
<div className="group" style={{padding: "10px", textAlign: "center"}}>
|
<div className="group incoming-call-title">
|
||||||
<div className="large ellipsized">{this.state.fullName}</div>
|
<div className="large ellipsized">{clipStr(this.state.fullName)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="group" style={{textAlign: "center"}}>
|
<div className="group incoming-call-badges">
|
||||||
<BadgeList trustedBadges={this.state.trustedBadges} />
|
<BadgeList trustedBadges={this.state.trustedBadges} />
|
||||||
</div>
|
</div>
|
||||||
<div id="actions" className="group" style={{padding: "20px", textAlign: "center"}}>
|
<div id="actions" className="group incoming-call-actions">
|
||||||
{this.props.callState >= 1 && this.props.callState < 3 ?
|
{this.props.callState == CALL_STATE_INCOMING_RECEIVED ?
|
||||||
<button onClick={this.handleRejectCall} style={{borderRadius: "10px", backgroundColor: "red"}}>
|
<>
|
||||||
|
<button className="video-call-hangup" onClick={this.handleRejectCall}>
|
||||||
<i className="material-icons">call_end</i>
|
<i className="material-icons">call_end</i>
|
||||||
</button>
|
</button>
|
||||||
:
|
<button className="video-call-accept" onClick={this.handleAcceptCall}>
|
||||||
null
|
|
||||||
}
|
|
||||||
{this.props.callState >= 2 && this.props.callState < 3 ?
|
|
||||||
<button onClick={this.handleAcceptCall} style={{borderRadius: "10px", backgroundColor: "green"}}>
|
|
||||||
<i className="material-icons">call</i>
|
<i className="material-icons">call</i>
|
||||||
</button>
|
</button>
|
||||||
|
</>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@@ -185,4 +171,4 @@ class CallView extends React.Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default injectIntl(CallView);
|
export default injectIntl(IncomingCallView);
|
||||||
@@ -18,7 +18,7 @@ import TopicSecurity from '../widgets/topic-security.jsx';
|
|||||||
import { MAX_TITLE_LENGTH, MAX_TOPIC_DESCRIPTION_LENGTH, NO_ACCESS_MODE } from '../config.js';
|
import { MAX_TITLE_LENGTH, MAX_TOPIC_DESCRIPTION_LENGTH, NO_ACCESS_MODE } from '../config.js';
|
||||||
|
|
||||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
import { makeImageUrl } from '../lib/blob-helpers.js';
|
||||||
import { theCard } from '../lib/utils.js';
|
import { theCard, clipStr } from '../lib/utils.js';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
info: {
|
info: {
|
||||||
@@ -78,10 +78,6 @@ const messages = defineMessages({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function _clip(str, length) {
|
|
||||||
return str && str.substring(0, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
class InfoView extends React.Component {
|
class InfoView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -206,11 +202,11 @@ class InfoView extends React.Component {
|
|||||||
deleter: acs && acs.isDeleter(),
|
deleter: acs && acs.isDeleter(),
|
||||||
muted: acs && acs.isMuted(),
|
muted: acs && acs.isMuted(),
|
||||||
|
|
||||||
fullName: _clip(topic.public ? topic.public.fn : undefined, MAX_TITLE_LENGTH),
|
fullName: clipStr(topic.public ? topic.public.fn : undefined, MAX_TITLE_LENGTH),
|
||||||
description: _clip(topic.public ? topic.public.note : undefined, MAX_TOPIC_DESCRIPTION_LENGTH),
|
description: clipStr(topic.public ? topic.public.note : undefined, MAX_TOPIC_DESCRIPTION_LENGTH),
|
||||||
avatar: makeImageUrl(topic.public ? topic.public.photo : null),
|
avatar: makeImageUrl(topic.public ? topic.public.photo : null),
|
||||||
trustedBadges: badges,
|
trustedBadges: badges,
|
||||||
private: _clip(topic.private ? topic.private.comment : null, MAX_TITLE_LENGTH),
|
private: clipStr(topic.private ? topic.private.comment : null, MAX_TITLE_LENGTH),
|
||||||
archived: topic.isArchived(),
|
archived: topic.isArchived(),
|
||||||
address: topic.name,
|
address: topic.name,
|
||||||
groupTopic: topic.isGroupType(),
|
groupTopic: topic.isGroupType(),
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import Invitation from '../widgets/invitation.jsx';
|
|||||||
import LetterTile from '../widgets/letter-tile.jsx';
|
import LetterTile from '../widgets/letter-tile.jsx';
|
||||||
import LoadSpinner from '../widgets/load-spinner.jsx';
|
import LoadSpinner from '../widgets/load-spinner.jsx';
|
||||||
import LogoView from './logo-view.jsx';
|
import LogoView from './logo-view.jsx';
|
||||||
import RtcPanel from '../widgets/rtc-panel.jsx';
|
import CallPanel from '../widgets/call-panel.jsx';
|
||||||
import SendMessage from '../widgets/send-message.jsx';
|
import SendMessage from '../widgets/send-message.jsx';
|
||||||
|
|
||||||
import { DEFAULT_P2P_ACCESS_MODE, IMAGE_PREVIEW_DIM, KEYPRESS_DELAY,
|
import { DEFAULT_P2P_ACCESS_MODE, IMAGE_PREVIEW_DIM, KEYPRESS_DELAY,
|
||||||
@@ -984,7 +984,7 @@ class MessagesView extends React.Component {
|
|||||||
} else if (this.state.rtcPanel) {
|
} else if (this.state.rtcPanel) {
|
||||||
const topic = this.props.tinode.getTopic(this.state.topic);
|
const topic = this.props.tinode.getTopic(this.state.topic);
|
||||||
component2 = (
|
component2 = (
|
||||||
<RtcPanel
|
<CallPanel
|
||||||
topic={topic}
|
topic={topic}
|
||||||
seq={this.props.callSeq}
|
seq={this.props.callSeq}
|
||||||
callState={this.props.callState}
|
callState={this.props.callState}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import ContextMenu from '../widgets/context-menu.jsx';
|
|||||||
import ForwardDialog from '../widgets/forward-dialog.jsx';
|
import ForwardDialog from '../widgets/forward-dialog.jsx';
|
||||||
|
|
||||||
import InfoView from './info-view.jsx';
|
import InfoView from './info-view.jsx';
|
||||||
import CallView from './call-view.jsx';
|
import IncomingCallView from './incoming-call-view.jsx';
|
||||||
import MessagesView from './messages-view.jsx';
|
import MessagesView from './messages-view.jsx';
|
||||||
import SidepanelView from './sidepanel-view.jsx';
|
import SidepanelView from './sidepanel-view.jsx';
|
||||||
|
|
||||||
@@ -2024,7 +2024,7 @@ class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{this.state.callTopic && this.state.callState == CALL_STATE_INCOMING_RECEIVED ?
|
{this.state.callTopic && this.state.callState == CALL_STATE_INCOMING_RECEIVED ?
|
||||||
<CallView
|
<IncomingCallView
|
||||||
tinode={this.tinode}
|
tinode={this.tinode}
|
||||||
onClose={this.handleCallClose}
|
onClose={this.handleCallClose}
|
||||||
topic={this.state.callTopic}
|
topic={this.state.callTopic}
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
|
// CallPanel: displays local and remote viewports and controls.
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import LetterTile from '../widgets/letter-tile.jsx';
|
import LetterTile from '../widgets/letter-tile.jsx';
|
||||||
|
|
||||||
import { CALL_STATE_OUTGOING_INITATED, CALL_STATE_IN_PROGRESS, CALL_WEBRTC_CONFIG } from '../config.js';
|
import { CALL_STATE_OUTGOING_INITATED, CALL_STATE_IN_PROGRESS, CALL_WEBRTC_CONFIG,
|
||||||
|
MAX_TITLE_LENGTH } from '../config.js';
|
||||||
|
|
||||||
export default class RtcPanel extends React.PureComponent {
|
import { clipStr } from '../lib/utils.js'
|
||||||
|
|
||||||
|
export default class CallPanel extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@@ -372,13 +376,13 @@ export default class RtcPanel extends React.PureComponent {
|
|||||||
<div className="video-elem">
|
<div className="video-elem">
|
||||||
<video id="remoteVideo" ref={this.remoteRef} autoPlay playsInline></video>
|
<video id="remoteVideo" ref={this.remoteRef} autoPlay playsInline></video>
|
||||||
{remoteActive ?
|
{remoteActive ?
|
||||||
<div className="video-title">{this.props.title}</div>
|
<div className="video-title">{clipStr(this.props.title, MAX_TITLE_LENGTH)}</div>
|
||||||
:
|
:
|
||||||
null}
|
null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="video-container-controls">
|
<div id="video-container-controls">
|
||||||
<button id="video-call-hangup" onClick={this.handleCloseClick}>
|
<button className="video-call-hangup" onClick={this.handleCloseClick}>
|
||||||
<i className="material-icons">call_end</i>
|
<i className="material-icons">call_end</i>
|
||||||
</button>
|
</button>
|
||||||
<button className="video-call-toggle-media" onClick={this.handleToggleCameraClick}><i className="material-icons">{videoIcon}</i></button>
|
<button className="video-call-toggle-media" onClick={this.handleToggleCameraClick}><i className="material-icons">{videoIcon}</i></button>
|
||||||
Reference in New Issue
Block a user