Merge pull request #6471 from SimonBrandner/fix/voip-event-tiles/18216

Fix VoIP event tile issues
This commit is contained in:
Germain 2021-07-27 08:17:31 +01:00 committed by GitHub
commit 788abac74d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 74 additions and 33 deletions

View file

@ -43,6 +43,14 @@ limitations under the License.
} }
} }
&.mx_CallEvent_voice.mx_CallEvent_missed .mx_CallEvent_type_icon::before {
mask-image: url('$(res)/img/voip/missed-voice.svg');
}
&.mx_CallEvent_video.mx_CallEvent_missed .mx_CallEvent_type_icon::before {
mask-image: url('$(res)/img/voip/missed-video.svg');
}
.mx_CallEvent_info { .mx_CallEvent_info {
display: flex; display: flex;
flex-direction: row; flex-direction: row;

View file

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 4.81815C0 3.76379 0.89543 2.90906 2 2.90906H9.33333C10.4379 2.90906 11.3333 3.76379 11.3333 4.81815V11.1818C11.3333 12.2361 10.4379 13.0909 9.33333 13.0909H2C0.895429 13.0909 0 12.2361 0 11.1818V4.81815ZM12.6667 6.09089L14.9169 4.37255C15.3534 4.03921 16 4.33587 16 4.86947V11.1305C16 11.6641 15.3534 11.9607 14.9169 11.6274L12.6667 9.90907V6.09089ZM3.68584 8.54792C3.68584 8.82819 3.45653 9.05751 3.17625 9.05751C2.89598 9.05751 2.66667 8.82819 2.66667 8.54792V6.50957C2.66667 6.22929 2.89598 5.99998 3.17625 5.99998H5.2146C5.49488 5.99998 5.72419 6.22929 5.72419 6.50957C5.72419 6.78984 5.49488 7.01916 5.2146 7.01916H4.39926L6.2083 8.82819L8.73076 6.30573C8.9295 6.10699 9.25054 6.10699 9.44928 6.30573C9.64802 6.50447 9.64802 6.82551 9.44928 7.02425L6.56501 9.90852C6.36627 10.1073 6.04523 10.1073 5.84649 9.90852L3.68584 7.74787V8.54792Z" fill="#8D97A5"/>
</svg>

After

Width:  |  Height:  |  Size: 1,016 B

View file

@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.00016 6C4.36683 6 4.66683 5.7 4.66683 5.33333V4.28667L7.4935 7.11333C7.7535 7.37333 8.1735 7.37333 8.4335 7.11333L12.2068 3.34C12.4668 3.08 12.4668 2.66 12.2068 2.4C11.9468 2.14 11.5268 2.14 11.2668 2.4L7.96683 5.7L5.60016 3.33333H6.66683C7.0335 3.33333 7.3335 3.03333 7.3335 2.66667C7.3335 2.3 7.0335 2 6.66683 2H4.00016C3.6335 2 3.3335 2.3 3.3335 2.66667V5.33333C3.3335 5.7 3.6335 6 4.00016 6Z" fill="#8D97A5"/>
<path d="M8.00557 8.67107C6.88076 8.62784 4.56757 8.91974 4.0052 9.06763C3.97195 9.07638 3.93363 9.08616 3.89078 9.0971C3.02734 9.31746 0.321813 10.008 0.0294949 12.1958C-0.196977 13.8909 0.937169 14.4039 1.50412 14.3258C1.89653 14.2766 3.02006 14.0989 4.05816 13.9127C5.07753 13.7298 5.07701 13.0573 5.07666 12.6026C5.07665 12.5943 5.07664 12.586 5.07664 12.5778L5.07665 11.6636C5.07665 11.4308 5.29543 11.2962 5.5972 11.2598C6.66548 11.1147 7.5573 11.1143 8.00369 11.1143L8.00745 11.1143C8.45377 11.1143 9.33453 11.1147 10.4028 11.2598C10.7046 11.2962 10.9234 11.4308 10.9234 11.6636L10.9234 12.5778C10.9234 12.586 10.9233 12.5943 10.9233 12.6026C10.923 13.0573 10.9225 13.7298 11.9418 13.9127C12.9799 14.099 14.1035 14.2766 14.4959 14.3258C15.0628 14.4039 16.197 13.8909 15.9705 12.1958C15.6782 10.008 12.9727 9.31747 12.1092 9.0971C12.0664 9.08617 12.0281 9.07639 11.9948 9.06764C11.4324 8.91975 9.13037 8.62783 8.00557 8.67107Z" fill="#8D97A5"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -491,28 +491,18 @@ export default class CallHandler extends EventEmitter {
break; break;
case CallState.Ended: case CallState.Ended:
{ {
Analytics.trackEvent('voip', 'callEnded', 'hangupReason', call.hangupReason); const hangupReason = call.hangupReason;
Analytics.trackEvent('voip', 'callEnded', 'hangupReason', hangupReason);
this.removeCallForRoom(mappedRoomId); this.removeCallForRoom(mappedRoomId);
if (oldState === CallState.InviteSent && ( if (oldState === CallState.InviteSent && call.hangupParty === CallParty.Remote) {
call.hangupParty === CallParty.Remote ||
(call.hangupParty === CallParty.Local && call.hangupReason === CallErrorCode.InviteTimeout)
)) {
this.play(AudioID.Busy); this.play(AudioID.Busy);
let title; let title;
let description; let description;
if (call.hangupReason === CallErrorCode.UserHangup) { // TODO: We should either do away with these or figure out a copy for each code (expect user_hangup...)
title = _t("Call Declined"); if (call.hangupReason === CallErrorCode.UserBusy) {
description = _t("The other party declined the call.");
} else if (call.hangupReason === CallErrorCode.UserBusy) {
title = _t("User Busy"); title = _t("User Busy");
description = _t("The user you called is busy."); description = _t("The user you called is busy.");
} else if (call.hangupReason === CallErrorCode.InviteTimeout) { } else if (hangupReason && ![CallErrorCode.UserHangup, "user hangup"].includes(hangupReason)) {
title = _t("Call Failed");
// XXX: full stop appended as some relic here, but these
// strings need proper input from design anyway, so let's
// not change this string until we have a proper one.
description = _t('The remote side failed to pick up') + '.';
} else {
title = _t("Call Failed"); title = _t("Call Failed");
description = _t("The call could not be established"); description = _t("The call could not be established");
} }
@ -521,7 +511,7 @@ export default class CallHandler extends EventEmitter {
title, description, title, description,
}); });
} else if ( } else if (
call.hangupReason === CallErrorCode.AnsweredElsewhere && oldState === CallState.Connecting hangupReason === CallErrorCode.AnsweredElsewhere && oldState === CallState.Connecting
) { ) {
Modal.createTrackedDialog('Call Handler', 'Call Failed', ErrorDialog, { Modal.createTrackedDialog('Call Handler', 'Call Failed', ErrorDialog, {
title: _t("Answered Elsewhere"), title: _t("Answered Elsewhere"),

View file

@ -74,6 +74,14 @@ export default class CallEventGrouper extends EventEmitter {
return this.hangup?.getContent()?.reason; return this.hangup?.getContent()?.reason;
} }
public get rejectParty(): string {
return this.reject?.getSender();
}
public get gotRejected(): boolean {
return Boolean(this.reject);
}
/** /**
* Returns true if there are only events from the other side - we missed the call * Returns true if there are only events from the other side - we missed the call
*/ */

View file

@ -25,6 +25,7 @@ import { CallErrorCode, CallState } from 'matrix-js-sdk/src/webrtc/call';
import InfoTooltip, { InfoTooltipKind } from '../elements/InfoTooltip'; import InfoTooltip, { InfoTooltipKind } from '../elements/InfoTooltip';
import classNames from 'classnames'; import classNames from 'classnames';
import AccessibleTooltipButton from '../elements/AccessibleTooltipButton'; import AccessibleTooltipButton from '../elements/AccessibleTooltipButton';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
interface IProps { interface IProps {
mxEvent: MatrixEvent; mxEvent: MatrixEvent;
@ -69,6 +70,18 @@ export default class CallEvent extends React.Component<IProps, IState> {
this.setState({ callState: newState }); this.setState({ callState: newState });
}; };
private renderCallBackButton(text: string): JSX.Element {
return (
<AccessibleButton
className="mx_CallEvent_content_button mx_CallEvent_content_button_callBack"
onClick={this.props.callEventGrouper.callBack}
kind="primary"
>
<span> { text } </span>
</AccessibleButton>
);
}
private renderContent(state: CallState | CustomCallState): JSX.Element { private renderContent(state: CallState | CustomCallState): JSX.Element {
if (state === CallState.Ringing) { if (state === CallState.Ringing) {
const silenceClass = classNames({ const silenceClass = classNames({
@ -103,8 +116,18 @@ export default class CallEvent extends React.Component<IProps, IState> {
} }
if (state === CallState.Ended) { if (state === CallState.Ended) {
const hangupReason = this.props.callEventGrouper.hangupReason; const hangupReason = this.props.callEventGrouper.hangupReason;
const gotRejected = this.props.callEventGrouper.gotRejected;
const rejectParty = this.props.callEventGrouper.rejectParty;
if ([CallErrorCode.UserHangup, "user hangup"].includes(hangupReason) || !hangupReason) { if (gotRejected) {
const weDeclinedCall = MatrixClientPeg.get().getUserId() === rejectParty;
return (
<div className="mx_CallEvent_content">
{ weDeclinedCall ? _t("You declined this call") : _t("They declined this call") }
{ this.renderCallBackButton(weDeclinedCall ? _t("Call back") : _t("Call again")) }
</div>
);
} else if (([CallErrorCode.UserHangup, "user hangup"].includes(hangupReason) || !hangupReason)) {
// workaround for https://github.com/vector-im/element-web/issues/5178 // workaround for https://github.com/vector-im/element-web/issues/5178
// it seems Android randomly sets a reason of "user hangup" which is // it seems Android randomly sets a reason of "user hangup" which is
// interpreted as an error code :( // interpreted as an error code :(
@ -116,6 +139,13 @@ export default class CallEvent extends React.Component<IProps, IState> {
{ _t("This call has ended") } { _t("This call has ended") }
</div> </div>
); );
} else if (hangupReason === CallErrorCode.InviteTimeout) {
return (
<div className="mx_CallEvent_content">
{ _t("They didn't pick up") }
{ this.renderCallBackButton(_t("Call again")) }
</div>
);
} }
let reason; let reason;
@ -133,8 +163,6 @@ export default class CallEvent extends React.Component<IProps, IState> {
// (as opposed to an error code they gave but we don't know about, // (as opposed to an error code they gave but we don't know about,
// in which case we show the error code) // in which case we show the error code)
reason = _t("An unknown error occurred"); reason = _t("An unknown error occurred");
} else if (hangupReason === CallErrorCode.InviteTimeout) {
reason = _t("No answer");
} else if (hangupReason === CallErrorCode.UserBusy) { } else if (hangupReason === CallErrorCode.UserBusy) {
reason = _t("The user you called is busy."); reason = _t("The user you called is busy.");
} else { } else {
@ -163,13 +191,7 @@ export default class CallEvent extends React.Component<IProps, IState> {
return ( return (
<div className="mx_CallEvent_content"> <div className="mx_CallEvent_content">
{ _t("You missed this call") } { _t("You missed this call") }
<AccessibleButton { this.renderCallBackButton(_t("Call back")) }
className="mx_CallEvent_content_button mx_CallEvent_content_button_callBack"
onClick={this.props.callEventGrouper.callBack}
kind="primary"
>
<span> { _t("Call back") } </span>
</AccessibleButton>
</div> </div>
); );
} }
@ -186,11 +208,17 @@ export default class CallEvent extends React.Component<IProps, IState> {
const sender = event.sender ? event.sender.name : event.getSender(); const sender = event.sender ? event.sender.name : event.getSender();
const isVoice = this.props.callEventGrouper.isVoice; const isVoice = this.props.callEventGrouper.isVoice;
const callType = isVoice ? _t("Voice call") : _t("Video call"); const callType = isVoice ? _t("Voice call") : _t("Video call");
const content = this.renderContent(this.state.callState); const callState = this.state.callState;
const hangupReason = this.props.callEventGrouper.hangupReason;
const content = this.renderContent(callState);
const className = classNames({ const className = classNames({
mx_CallEvent: true, mx_CallEvent: true,
mx_CallEvent_voice: isVoice, mx_CallEvent_voice: isVoice,
mx_CallEvent_video: !isVoice, mx_CallEvent_video: !isVoice,
mx_CallEvent_missed: (
callState === CustomCallState.Missed ||
(callState === CallState.Ended && hangupReason === CallErrorCode.InviteTimeout)
),
}); });
return ( return (

View file

@ -35,11 +35,8 @@
"Unable to load! Check your network connectivity and try again.": "Unable to load! Check your network connectivity and try again.", "Unable to load! Check your network connectivity and try again.": "Unable to load! Check your network connectivity and try again.",
"Dismiss": "Dismiss", "Dismiss": "Dismiss",
"Call Failed": "Call Failed", "Call Failed": "Call Failed",
"Call Declined": "Call Declined",
"The other party declined the call.": "The other party declined the call.",
"User Busy": "User Busy", "User Busy": "User Busy",
"The user you called is busy.": "The user you called is busy.", "The user you called is busy.": "The user you called is busy.",
"The remote side failed to pick up": "The remote side failed to pick up",
"The call could not be established": "The call could not be established", "The call could not be established": "The call could not be established",
"Answered Elsewhere": "Answered Elsewhere", "Answered Elsewhere": "Answered Elsewhere",
"The call was answered on another device.": "The call was answered on another device.", "The call was answered on another device.": "The call was answered on another device.",
@ -1862,16 +1859,19 @@
"Verification cancelled": "Verification cancelled", "Verification cancelled": "Verification cancelled",
"Compare emoji": "Compare emoji", "Compare emoji": "Compare emoji",
"Connected": "Connected", "Connected": "Connected",
"You declined this call": "You declined this call",
"They declined this call": "They declined this call",
"Call back": "Call back",
"Call again": "Call again",
"This call has ended": "This call has ended", "This call has ended": "This call has ended",
"They didn't pick up": "They didn't pick up",
"Could not connect media": "Could not connect media", "Could not connect media": "Could not connect media",
"Connection failed": "Connection failed", "Connection failed": "Connection failed",
"Their device couldn't start the camera or microphone": "Their device couldn't start the camera or microphone", "Their device couldn't start the camera or microphone": "Their device couldn't start the camera or microphone",
"An unknown error occurred": "An unknown error occurred", "An unknown error occurred": "An unknown error occurred",
"No answer": "No answer",
"Unknown failure: %(reason)s)": "Unknown failure: %(reason)s)", "Unknown failure: %(reason)s)": "Unknown failure: %(reason)s)",
"This call has failed": "This call has failed", "This call has failed": "This call has failed",
"You missed this call": "You missed this call", "You missed this call": "You missed this call",
"Call back": "Call back",
"The call is in an unknown state!": "The call is in an unknown state!", "The call is in an unknown state!": "The call is in an unknown state!",
"Sunday": "Sunday", "Sunday": "Sunday",
"Monday": "Monday", "Monday": "Monday",