Move video call message state and duration to head.
'webrtc' header for state. 'webrtc-duration' header for duration. Content is now Drafty.videoCall() / VC.
This commit is contained in:
@@ -6,3 +6,6 @@ export const CALL_STATE_IN_PROGRESS = 3;
|
|||||||
|
|
||||||
// Mime type used for video call messages.
|
// Mime type used for video call messages.
|
||||||
export const CALL_MESSAGE_MIME_TYPE = 'application/x-tinode-webrtc';
|
export const CALL_MESSAGE_MIME_TYPE = 'application/x-tinode-webrtc';
|
||||||
|
|
||||||
|
// Video call drafty headers representing call state.
|
||||||
|
export const CALL_HEAD_STARTED = 'started';
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { defineMessages } from 'react-intl';
|
|||||||
import { Drafty } from 'tinode-sdk';
|
import { Drafty } from 'tinode-sdk';
|
||||||
|
|
||||||
import AudioPlayer from '../widgets/audio-player.jsx'
|
import AudioPlayer from '../widgets/audio-player.jsx'
|
||||||
|
import CallMessage from '../widgets/call-message.jsx'
|
||||||
|
import CallStatus from '../widgets/call-status.jsx';
|
||||||
import LazyImage from '../widgets/lazy-image.jsx'
|
import LazyImage from '../widgets/lazy-image.jsx'
|
||||||
import UploadingImage from '../widgets/uploading-image.jsx'
|
import UploadingImage from '../widgets/uploading-image.jsx'
|
||||||
|
|
||||||
@@ -163,6 +165,14 @@ export function fullFormatter(style, data, values, key, stack) {
|
|||||||
attr.className = 'reply-quote'
|
attr.className = 'reply-quote'
|
||||||
attr.onClick = this.onQuoteClick;
|
attr.onClick = this.onQuoteClick;
|
||||||
break;
|
break;
|
||||||
|
case 'VC':
|
||||||
|
el = CallMessage;
|
||||||
|
// Video call messages do not have content.
|
||||||
|
values = null;
|
||||||
|
attr.content = this.callState;
|
||||||
|
attr.response = this.isResponse;
|
||||||
|
attr.duration = this.callDuration;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (!el) {
|
if (!el) {
|
||||||
// Unknown element.
|
// Unknown element.
|
||||||
@@ -245,6 +255,12 @@ export function previewFormatter(style, data, values, key) {
|
|||||||
el = React.Fragment;
|
el = React.Fragment;
|
||||||
values = [<i key="ex" className="material-icons">attachment</i>, ' ', this.formatMessage(messages.drafty_attachment)];
|
values = [<i key="ex" className="material-icons">attachment</i>, ' ', this.formatMessage(messages.drafty_attachment)];
|
||||||
break;
|
break;
|
||||||
|
case 'VC':
|
||||||
|
el = CallStatus;
|
||||||
|
attr.incoming = this.previewIsResponse;
|
||||||
|
attr.success = true; // FIXME: use actuall call completion status instead of TRUE.
|
||||||
|
values = null;
|
||||||
|
break;
|
||||||
case 'QQ':
|
case 'QQ':
|
||||||
case 'HD':
|
case 'HD':
|
||||||
el = null;
|
el = null;
|
||||||
|
|||||||
@@ -1137,20 +1137,14 @@ class MessagesView extends React.Component {
|
|||||||
);
|
);
|
||||||
prevDate = thisDate;
|
prevDate = thisDate;
|
||||||
}
|
}
|
||||||
let duration;
|
const duration = msg.head ? msg.head['webrtc-duration'] : undefined;
|
||||||
if (msg.head && isVideoCall(msg.head.mime)) {
|
|
||||||
topic.messageVersions(msg, (cur, before) => {
|
|
||||||
if (cur.content == 'finished' && before.content == 'accepted') {
|
|
||||||
duration = msg.ts - before.ts;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
messageNodes.push(
|
messageNodes.push(
|
||||||
<ChatMessage
|
<ChatMessage
|
||||||
tinode={this.props.tinode}
|
tinode={this.props.tinode}
|
||||||
content={msg.content}
|
content={msg.content}
|
||||||
mimeType={msg.head ? msg.head.mime : null}
|
mimeType={msg.head ? msg.head.mime : null}
|
||||||
timestamp={msg.ts}
|
timestamp={msg.ts}
|
||||||
|
callState={msg.head ? msg.head.webrtc : null}
|
||||||
duration={duration}
|
duration={duration}
|
||||||
response={isReply}
|
response={isReply}
|
||||||
seq={msg.seq}
|
seq={msg.seq}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { API_KEY, APP_NAME, DEFAULT_P2P_ACCESS_MODE, FORWARDED_PREVIEW_LENGTH, L
|
|||||||
MEDIA_BREAKPOINT, RECEIVED_DELAY } from '../config.js';
|
MEDIA_BREAKPOINT, RECEIVED_DELAY } from '../config.js';
|
||||||
import { CALL_STATE_NONE, CALL_STATE_OUTGOING_INITATED,
|
import { CALL_STATE_NONE, CALL_STATE_OUTGOING_INITATED,
|
||||||
CALL_STATE_INCOMING_RECEIVED, CALL_STATE_IN_PROGRESS,
|
CALL_STATE_INCOMING_RECEIVED, CALL_STATE_IN_PROGRESS,
|
||||||
CALL_MESSAGE_MIME_TYPE } from '../constants.js';
|
CALL_MESSAGE_MIME_TYPE, CALL_HEAD_STARTED } from '../constants.js';
|
||||||
import { PACKAGE_VERSION } from '../version.js';
|
import { PACKAGE_VERSION } from '../version.js';
|
||||||
import { base64ReEncode, makeImageUrl } from '../lib/blob-helpers.js';
|
import { base64ReEncode, makeImageUrl } from '../lib/blob-helpers.js';
|
||||||
import { detectServerAddress, isLocalHost, isSecureConnection } from '../lib/host-name.js';
|
import { detectServerAddress, isLocalHost, isSecureConnection } from '../lib/host-name.js';
|
||||||
@@ -1687,8 +1687,11 @@ class TinodeWeb extends React.Component {
|
|||||||
handleCallInvite(callTopic, callSeq, callState) {
|
handleCallInvite(callTopic, callSeq, callState) {
|
||||||
switch (callState) {
|
switch (callState) {
|
||||||
case CALL_STATE_OUTGOING_INITATED:
|
case CALL_STATE_OUTGOING_INITATED:
|
||||||
let head = {mime: CALL_MESSAGE_MIME_TYPE };
|
let head = {
|
||||||
this.handleSendMessage('started', undefined, undefined, head)
|
mime: CALL_MESSAGE_MIME_TYPE,
|
||||||
|
webrtc: CALL_HEAD_STARTED
|
||||||
|
};
|
||||||
|
this.handleSendMessage(Drafty.videoCall(), undefined, undefined, head)
|
||||||
.then((ctrl) => {
|
.then((ctrl) => {
|
||||||
if (ctrl.code < 200 || ctrl.code >= 300 || !ctrl.params || !ctrl.params.seq) {
|
if (ctrl.code < 200 || ctrl.code >= 300 || !ctrl.params || !ctrl.params.seq) {
|
||||||
this.handleCallClose();
|
this.handleCallClose();
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default class CallStatus extends React.PureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="composed-material">
|
<div className="composed-material">
|
||||||
<i class="material-icons">call</i><i class="material-icons second">{icon2}</i>
|
<i className="material-icons">call</i><i className="material-icons second">{icon2}</i>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { FormattedMessage, injectIntl } from 'react-intl';
|
|||||||
import { Drafty, Tinode } from 'tinode-sdk';
|
import { Drafty, Tinode } from 'tinode-sdk';
|
||||||
|
|
||||||
import Attachment from './attachment.jsx';
|
import Attachment from './attachment.jsx';
|
||||||
import CallMessage from './call-message.jsx';
|
|
||||||
import LetterTile from './letter-tile.jsx';
|
import LetterTile from './letter-tile.jsx';
|
||||||
import ReceivedMarker from './received-marker.jsx'
|
import ReceivedMarker from './received-marker.jsx'
|
||||||
|
|
||||||
|
import { CALL_MESSAGE_MIME_TYPE } from '../constants.js'
|
||||||
import { fullFormatter } from '../lib/formatters.js';
|
import { fullFormatter } from '../lib/formatters.js';
|
||||||
import { isVideoCall, sanitizeUrl } from '../lib/utils.js';
|
import { isVideoCall, sanitizeUrl } from '../lib/utils.js';
|
||||||
|
|
||||||
@@ -34,6 +34,12 @@ class BaseChatMessage extends React.PureComponent {
|
|||||||
formatMessage: props.intl.formatMessage.bind(props.intl),
|
formatMessage: props.intl.formatMessage.bind(props.intl),
|
||||||
viewportWidth: props.viewportWidth,
|
viewportWidth: props.viewportWidth,
|
||||||
authorizeURL: props.tinode.authorizeURL.bind(props.tinode),
|
authorizeURL: props.tinode.authorizeURL.bind(props.tinode),
|
||||||
|
|
||||||
|
// Video call related bits.
|
||||||
|
callState: props.callState,
|
||||||
|
isResponse: props.response,
|
||||||
|
callDuration: props.duration,
|
||||||
|
|
||||||
onImagePreview: this.handleImagePreview,
|
onImagePreview: this.handleImagePreview,
|
||||||
onFormButtonClick: this.handleFormButtonClick,
|
onFormButtonClick: this.handleFormButtonClick,
|
||||||
onQuoteClick: this.handleQuoteClick
|
onQuoteClick: this.handleQuoteClick
|
||||||
@@ -120,7 +126,7 @@ class BaseChatMessage extends React.PureComponent {
|
|||||||
|
|
||||||
let content = this.props.content;
|
let content = this.props.content;
|
||||||
const attachments = [];
|
const attachments = [];
|
||||||
if (this.props.mimeType == Drafty.getContentType() && Drafty.isValid(content)) {
|
if ([Drafty.getContentType(), CALL_MESSAGE_MIME_TYPE].includes(this.props.mimeType) && Drafty.isValid(content)) {
|
||||||
Drafty.attachments(content, (att, i) => {
|
Drafty.attachments(content, (att, i) => {
|
||||||
if (att.mime == 'application/json') {
|
if (att.mime == 'application/json') {
|
||||||
// Don't show json objects as attachments.
|
// Don't show json objects as attachments.
|
||||||
@@ -147,12 +153,6 @@ class BaseChatMessage extends React.PureComponent {
|
|||||||
<FormattedMessage id="deleted_content"
|
<FormattedMessage id="deleted_content"
|
||||||
defaultMessage="content deleted" description="Shown when messages are deleted" />
|
defaultMessage="content deleted" description="Shown when messages are deleted" />
|
||||||
</i></>
|
</i></>
|
||||||
} else if (isVideoCall(this.props.mimeType)) {
|
|
||||||
// Video call message.
|
|
||||||
content = <CallMessage
|
|
||||||
content={this.props.content}
|
|
||||||
response={this.props.response}
|
|
||||||
duration={this.props.duration} />
|
|
||||||
} else if (typeof content != 'string') {
|
} else if (typeof content != 'string') {
|
||||||
content = <><i className="material-icons gray">warning_amber</i> <i className="gray">
|
content = <><i className="material-icons gray">warning_amber</i> <i className="gray">
|
||||||
<FormattedMessage id="invalid_content"
|
<FormattedMessage id="invalid_content"
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
import CallStatus from './call-status.jsx';
|
|
||||||
import ContactBadges from './contact-badges.jsx';
|
import ContactBadges from './contact-badges.jsx';
|
||||||
import LetterTile from './letter-tile.jsx';
|
import LetterTile from './letter-tile.jsx';
|
||||||
import UnreadBadge from './unread-badge.jsx';
|
import UnreadBadge from './unread-badge.jsx';
|
||||||
@@ -71,16 +70,11 @@ class Contact extends React.Component {
|
|||||||
|
|
||||||
// The this.props.preview contains alreay shortened Drafty or string.
|
// The this.props.preview contains alreay shortened Drafty or string.
|
||||||
let preview;
|
let preview;
|
||||||
if (this.props.previewIsVideoCall) {
|
if (typeof this.props.preview == 'string') {
|
||||||
// TODO: use words to describe call status and duration.
|
|
||||||
preview = <CallStatus
|
|
||||||
incoming={this.props.previewIsResponse}
|
|
||||||
success={true} />; // FIXME: use actuall call completion status instead of TRUE.
|
|
||||||
} else if (typeof this.props.preview == 'string') {
|
|
||||||
preview = this.props.preview;
|
preview = this.props.preview;
|
||||||
} else if (Drafty.isValid(this.props.preview)) {
|
} else if (Drafty.isValid(this.props.preview)) {
|
||||||
preview = React.createElement(React.Fragment, null, Drafty.format(this.props.preview, previewFormatter,
|
preview = React.createElement(React.Fragment, null, Drafty.format(this.props.preview, previewFormatter,
|
||||||
{formatMessage: this.props.intl.formatMessage}));
|
{formatMessage: this.props.intl.formatMessage, previewIsResponse: this.props.previewIsResponse}));
|
||||||
} else if (this.props.preview) {
|
} else if (this.props.preview) {
|
||||||
preview =
|
preview =
|
||||||
<><i className="material-icons gray">warning_amber</i> <i className="gray">
|
<><i className="material-icons gray">warning_amber</i> <i className="gray">
|
||||||
|
|||||||
+360
-521
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+74
-88
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user