Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Basic call transfer initiation support
Browse files Browse the repository at this point in the history
Adapt the InviteDialog to select a transfer target

Doesn't support supplying a roo mID fr the transfer: just leaves
the transferee to work out how to contact the target themselves.

MSC2747 (matrix-org/matrix-spec-proposals#2747)
Requires matrix-org/matrix-js-sdk#1558
  • Loading branch information
dbkr committed Dec 15, 2020
1 parent 7998f79 commit a33be00
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
18 changes: 18 additions & 0 deletions src/components/views/context_menus/CallContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { _t } from '../../../languageHandler';
import { ContextMenu, IProps as IContextMenuProps, MenuItem } from '../../structures/ContextMenu';
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
import CallHandler from '../../../CallHandler';
import InviteDialog, { KIND_CALL_TRANSFER } from '../dialogs/InviteDialog';
import Modal from '../../../Modal';

interface IProps extends IContextMenuProps {
call: MatrixCall;
Expand All @@ -46,14 +48,30 @@ export default class CallContextMenu extends React.Component<IProps> {
this.props.onFinished();
}

onTransferClick = () => {
Modal.createTrackedDialog(
'Transfer Call', '', InviteDialog, {kind: KIND_CALL_TRANSFER, call: this.props.call},
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true,
);
this.props.onFinished();
}

render() {
const holdUnholdCaption = this.props.call.isRemoteOnHold() ? _t("Resume") : _t("Hold");
const handler = this.props.call.isRemoteOnHold() ? this.onUnholdClick : this.onHoldClick;

let transferItem;
if (this.props.call.opponentCanBeTransferred()) {
transferItem = <MenuItem className="mx_CallContextMenu_item" onClick={this.onTransferClick}>
{_t("Transfer")}
</MenuItem>;
}

return <ContextMenu {...this.props}>
<MenuItem className="mx_CallContextMenu_item" onClick={handler}>
{holdUnholdCaption}
</MenuItem>
{transferItem}
</ContextMenu>;
}
}
38 changes: 37 additions & 1 deletion src/components/views/dialogs/InviteDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ import SettingsStore from "../../../settings/SettingsStore";
import {UIFeature} from "../../../settings/UIFeature";
import CountlyAnalytics from "../../../CountlyAnalytics";
import {Room} from "matrix-js-sdk/src/models/room";
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';

// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
/* eslint-disable camelcase */

export const KIND_DM = "dm";
export const KIND_INVITE = "invite";
export const KIND_CALL_TRANSFER = "call_transfer";

const INITIAL_ROOMS_SHOWN = 3; // Number of rooms to show at first
const INCREMENT_ROOMS_SHOWN = 5; // Number of rooms to add when 'show more' is clicked
Expand Down Expand Up @@ -310,6 +312,9 @@ interface IInviteDialogProps {
// The room ID this dialog is for. Only required for KIND_INVITE.
roomId: string,

// The call to transfer. Only required for KIND_CALL_TRANSFER.
call: MatrixCall,

// Initial value to populate the filter with
initialText: string,
}
Expand Down Expand Up @@ -345,6 +350,8 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps

if (props.kind === KIND_INVITE && !props.roomId) {
throw new Error("When using KIND_INVITE a roomId is required for an InviteDialog");
} else if (props.kind === KIND_CALL_TRANSFER && !props.call) {
throw new Error("When using KIND_CALL_TRANSFER a call is required for an InviteDialog");
}

const alreadyInvited = new Set([MatrixClientPeg.get().getUserId(), SdkConfig.get()['welcomeUserId']]);
Expand Down Expand Up @@ -702,6 +709,29 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
});
};

_transferCall = async () => {
this._convertFilter();
const targets = this._convertFilter();
const targetIds = targets.map(t => t.userId);
if (targetIds.length > 1) {
this.setState({
errorText: _t("A call can only be transferred to a single user."),
});
}

this.setState({busy: true});
try {
await this.props.call.transfer(targetIds[0]);
this.setState({busy: false});
this.props.onFinished();
} catch (e) {
this.setState({
busy: false,
errorText: _t("Failed to transfer call"),
});
}
};

_onKeyDown = (e) => {
if (this.state.busy) return;
const value = e.target.value.trim();
Expand Down Expand Up @@ -1217,7 +1247,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
}
buttonText = _t("Go");
goButtonFn = this._startDm;
} else { // KIND_INVITE
} else if (this.props.kind === KIND_INVITE) {
title = _t("Invite to this room");

if (identityServersEnabled) {
Expand Down Expand Up @@ -1251,6 +1281,12 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps

buttonText = _t("Invite");
goButtonFn = this._inviteUsers;
} else if (this.props.kind === KIND_CALL_TRANSFER) {
title = _t("Transfer");
buttonText = _t("Transfer");
goButtonFn = this._transferCall;
} else {
console.error("Unknown kind of InviteDialog: " + this.props.kind);
}

const hasSelection = this.state.targets.length > 0
Expand Down
1 change: 1 addition & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2267,6 +2267,7 @@
"If you've forgotten your recovery key you can <button>set up new recovery options</button>": "If you've forgotten your recovery key you can <button>set up new recovery options</button>",
"Resume": "Resume",
"Hold": "Hold",
"Transfer": "Transfer",
"Reject invitation": "Reject invitation",
"Are you sure you want to reject the invitation?": "Are you sure you want to reject the invitation?",
"Unable to reject invite": "Unable to reject invite",
Expand Down

0 comments on commit a33be00

Please sign in to comment.