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

Commit

Permalink
Merge pull request #5693 from matrix-org/travis/move-call-buttons
Browse files Browse the repository at this point in the history
Move call buttons to the room header
  • Loading branch information
turt2live authored Feb 26, 2021
2 parents f1330b7 + 01da863 commit cf0f591
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 144 deletions.
12 changes: 0 additions & 12 deletions res/css/views/rooms/_MessageComposer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -227,18 +227,6 @@ limitations under the License.
mask-image: url('$(res)/img/element-icons/room/composer/attach.svg');
}

.mx_MessageComposer_hangup::before {
mask-image: url('$(res)/img/element-icons/call/hangup.svg');
}

.mx_MessageComposer_voicecall::before {
mask-image: url('$(res)/img/element-icons/call/voice-call.svg');
}

.mx_MessageComposer_videocall::before {
mask-image: url('$(res)/img/element-icons/call/video-call.svg');
}

.mx_MessageComposer_emoji::before {
mask-image: url('$(res)/img/element-icons/room/composer/emoji.svg');
}
Expand Down
13 changes: 13 additions & 0 deletions res/css/views/rooms/_RoomHeader.scss
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,19 @@ limitations under the License.
mask-image: url('$(res)/img/element-icons/room/search-inset.svg');
}

.mx_RoomHeader_voiceCallButton::before {
mask-image: url('$(res)/img/element-icons/call/voice-call.svg');

// The call button SVG is padded slightly differently, so match it up to the size
// of the other icons
mask-size: 20px;
mask-position: center;
}

.mx_RoomHeader_videoCallButton::before {
mask-image: url('$(res)/img/element-icons/call/video-call.svg');
}

.mx_RoomHeader_showPanel {
height: 16px;
}
Expand Down
11 changes: 10 additions & 1 deletion src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import ResizeNotifier from '../../utils/ResizeNotifier';
import ContentMessages from '../../ContentMessages';
import Modal from '../../Modal';
import * as sdk from '../../index';
import CallHandler from '../../CallHandler';
import CallHandler, { PlaceCallType } from '../../CallHandler';
import dis from '../../dispatcher/dispatcher';
import Tinter from '../../Tinter';
import rateLimitedFunc from '../../ratelimitedfunc';
Expand Down Expand Up @@ -1352,6 +1352,14 @@ export default class RoomView extends React.Component<IProps, IState> {
SettingsStore.setValue("PinnedEvents.isOpen", roomId, SettingLevel.ROOM_DEVICE, nowShowingPinned);
};

private onCallPlaced = (type: PlaceCallType) => {
dis.dispatch({
action: 'place_call',
type: type,
room_id: this.state.room.roomId,
});
};

private onSettingsClick = () => {
dis.dispatch({ action: "open_room_settings" });
};
Expand Down Expand Up @@ -2031,6 +2039,7 @@ export default class RoomView extends React.Component<IProps, IState> {
e2eStatus={this.state.e2eStatus}
onAppsClick={this.state.hasPinnedWidgets ? this.onAppsClick : null}
appsShown={this.state.showApps}
onCallPlaced={this.onCallPlaced}
/>
<MainSplit panel={rightPanel} resizeNotifier={this.props.resizeNotifier}>
<div className="mx_RoomView_body">
Expand Down
129 changes: 1 addition & 128 deletions src/components/views/rooms/MessageComposer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017, 2018 New Vector Ltd
Copyright 2020 The Matrix.org Foundation C.I.C.
Copyright 2015-2018, 2020, 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,7 +17,6 @@ import React, {createRef} from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import CallHandler from '../../../CallHandler';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import * as sdk from '../../../index';
import dis from '../../../dispatcher/dispatcher';
Expand All @@ -33,11 +30,8 @@ import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
import ReplyPreview from "./ReplyPreview";
import {UIFeature} from "../../../settings/UIFeature";
import WidgetStore from "../../../stores/WidgetStore";
import WidgetUtils from "../../../utils/WidgetUtils";
import {UPDATE_EVENT} from "../../../stores/AsyncStore";
import ActiveWidgetStore from "../../../stores/ActiveWidgetStore";
import { PlaceCallType } from "../../../CallHandler";
import { CallState } from 'matrix-js-sdk/src/webrtc/call';

function ComposerAvatar(props) {
const MemberStatusMessageAvatar = sdk.getComponent('avatars.MemberStatusMessageAvatar');
Expand All @@ -50,97 +44,6 @@ ComposerAvatar.propTypes = {
me: PropTypes.object.isRequired,
};

function CallButton(props) {
const onVoiceCallClick = (ev) => {
dis.dispatch({
action: 'place_call',
type: PlaceCallType.Voice,
room_id: props.roomId,
});
};

return (<AccessibleTooltipButton
className="mx_MessageComposer_button mx_MessageComposer_voicecall"
onClick={onVoiceCallClick}
title={_t('Voice call')}
/>);
}

CallButton.propTypes = {
roomId: PropTypes.string.isRequired,
};

function VideoCallButton(props) {
const onCallClick = (ev) => {
dis.dispatch({
action: 'place_call',
type: ev.shiftKey ? PlaceCallType.ScreenSharing : PlaceCallType.Video,
room_id: props.roomId,
});
};

return <AccessibleTooltipButton
className="mx_MessageComposer_button mx_MessageComposer_videocall"
onClick={onCallClick}
title={_t('Video call')}
/>;
}

VideoCallButton.propTypes = {
roomId: PropTypes.string.isRequired,
};

function HangupButton(props) {
const onHangupClick = () => {
if (props.isConference) {
dis.dispatch({
action: props.canEndConference ? 'end_conference' : 'hangup_conference',
room_id: props.roomId,
});
return;
}

const call = CallHandler.sharedInstance().getCallForRoom(props.roomId);
if (!call) {
return;
}

const action = call.state === CallState.Ringing ? 'reject' : 'hangup';

dis.dispatch({
action,
// hangup the call for this room. NB. We use the room in props as the room ID
// as call.roomId may be the 'virtual room', and the dispatch actions always
// use the user-facing room (there was a time when we deliberately used
// call.roomId and *not* props.roomId, but that was for the old
// style Freeswitch conference calls and those times are gone.)
room_id: props.roomId,
});
};

let tooltip = _t("Hangup");
if (props.isConference && props.canEndConference) {
tooltip = _t("End conference");
}

const canLeaveConference = !props.isConference ? true : props.isInConference;
return (
<AccessibleTooltipButton
className="mx_MessageComposer_button mx_MessageComposer_hangup"
onClick={onHangupClick}
title={tooltip}
disabled={!canLeaveConference}
/>
);
}

HangupButton.propTypes = {
roomId: PropTypes.string.isRequired,
isConference: PropTypes.bool.isRequired,
canEndConference: PropTypes.bool,
isInConference: PropTypes.bool,
};

const EmojiButton = ({addEmoji}) => {
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();

Expand Down Expand Up @@ -265,7 +168,6 @@ export default class MessageComposer extends React.Component {
this.state = {
tombstone: this._getRoomTombstone(),
canSendMessages: this.props.room.maySendMessage(),
showCallButtons: SettingsStore.getValue("showCallButtonsInComposer"),
hasConference: WidgetStore.instance.doesRoomHaveConference(this.props.room),
joinedConference: WidgetStore.instance.isJoinedToConferenceIn(this.props.room),
};
Expand Down Expand Up @@ -405,12 +307,7 @@ export default class MessageComposer extends React.Component {
];

if (!this.state.tombstone && this.state.canSendMessages) {
// This also currently includes the call buttons. Really we should
// check separately for whether we can call, but this is slightly
// complex because of conference calls.

const SendMessageComposer = sdk.getComponent("rooms.SendMessageComposer");
const callInProgress = this.props.callState && this.props.callState !== 'ended';

controls.push(
<SendMessageComposer
Expand All @@ -430,30 +327,6 @@ export default class MessageComposer extends React.Component {
SettingsStore.getValue("MessageComposerInput.showStickersButton")) {
controls.push(<Stickerpicker key="stickerpicker_controls_button" room={this.props.room} />);
}

if (this.state.showCallButtons) {
if (this.state.hasConference) {
const canEndConf = WidgetUtils.canUserModifyWidgets(this.props.room.roomId);
controls.push(
<HangupButton
key="controls_hangup"
roomId={this.props.room.roomId}
isConference={true}
canEndConference={canEndConf}
isInConference={this.state.joinedConference}
/>,
);
} else if (callInProgress) {
controls.push(
<HangupButton key="controls_hangup" roomId={this.props.room.roomId} isConference={false} />,
);
} else {
controls.push(
<CallButton key="controls_call" roomId={this.props.room.roomId} />,
<VideoCallButton key="controls_videocall" roomId={this.props.room.roomId} />,
);
}
}
} else if (this.state.tombstone) {
const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];

Expand Down
20 changes: 20 additions & 0 deletions src/components/views/rooms/RoomHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {DefaultTagID} from "../../../stores/room-list/models";
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
import RoomTopic from "../elements/RoomTopic";
import RoomName from "../elements/RoomName";
import {PlaceCallType} from "../../../CallHandler";

export default class RoomHeader extends React.Component {
static propTypes = {
Expand All @@ -45,6 +46,7 @@ export default class RoomHeader extends React.Component {
e2eStatus: PropTypes.string,
onAppsClick: PropTypes.func,
appsShown: PropTypes.bool,
onCallPlaced: PropTypes.func, // (PlaceCallType) => void;
};

static defaultProps = {
Expand Down Expand Up @@ -226,8 +228,26 @@ export default class RoomHeader extends React.Component {
title={_t("Search")} />;
}

let voiceCallButton;
let videoCallButton;
if (this.props.inRoom && SettingsStore.getValue("showCallButtonsInComposer")) {
voiceCallButton =
<AccessibleTooltipButton
className="mx_RoomHeader_button mx_RoomHeader_voiceCallButton"
onClick={() => this.props.onCallPlaced(PlaceCallType.Voice)}
title={_t("Voice call")} />;
videoCallButton =
<AccessibleTooltipButton
className="mx_RoomHeader_button mx_RoomHeader_videoCallButton"
onClick={(ev) => this.props.onCallPlaced(
ev.shiftKey ? PlaceCallType.ScreenSharing : PlaceCallType.Video)}
title={_t("Video call")} />;
}

const rightRow =
<div className="mx_RoomHeader_buttons">
{ videoCallButton }
{ voiceCallButton }
{ pinnedEventsButton }
{ forgetButton }
{ appsButton }
Expand Down
5 changes: 2 additions & 3 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1416,9 +1416,6 @@
"Invited": "Invited",
"Filter room members": "Filter room members",
"%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (power %(powerLevelNumber)s)",
"Voice call": "Voice call",
"Video call": "Video call",
"Hangup": "Hangup",
"Emoji picker": "Emoji picker",
"Upload file": "Upload file",
"Send an encrypted reply…": "Send an encrypted reply…",
Expand Down Expand Up @@ -1476,6 +1473,8 @@
"Hide Widgets": "Hide Widgets",
"Show Widgets": "Show Widgets",
"Search": "Search",
"Voice call": "Voice call",
"Video call": "Video call",
"Start a Conversation": "Start a Conversation",
"Open dial pad": "Open dial pad",
"Invites": "Invites",
Expand Down
2 changes: 2 additions & 0 deletions src/settings/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,8 @@ export const SETTINGS: {[setting: string]: ISetting} = {
default: 3000,
},
"showCallButtonsInComposer": {
// Dev note: This is no longer "in composer" but is instead "in room header".
// TODO: Rename with settings v3
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
default: true,
controller: new UIFeatureController(UIFeature.Voip),
Expand Down

0 comments on commit cf0f591

Please sign in to comment.