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

Commit cf0f591

Browse files
authored
Merge pull request #5693 from matrix-org/travis/move-call-buttons
Move call buttons to the room header
2 parents f1330b7 + 01da863 commit cf0f591

File tree

7 files changed

+48
-144
lines changed

7 files changed

+48
-144
lines changed

res/css/views/rooms/_MessageComposer.scss

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -227,18 +227,6 @@ limitations under the License.
227227
mask-image: url('$(res)/img/element-icons/room/composer/attach.svg');
228228
}
229229

230-
.mx_MessageComposer_hangup::before {
231-
mask-image: url('$(res)/img/element-icons/call/hangup.svg');
232-
}
233-
234-
.mx_MessageComposer_voicecall::before {
235-
mask-image: url('$(res)/img/element-icons/call/voice-call.svg');
236-
}
237-
238-
.mx_MessageComposer_videocall::before {
239-
mask-image: url('$(res)/img/element-icons/call/video-call.svg');
240-
}
241-
242230
.mx_MessageComposer_emoji::before {
243231
mask-image: url('$(res)/img/element-icons/room/composer/emoji.svg');
244232
}

res/css/views/rooms/_RoomHeader.scss

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,19 @@ limitations under the License.
252252
mask-image: url('$(res)/img/element-icons/room/search-inset.svg');
253253
}
254254

255+
.mx_RoomHeader_voiceCallButton::before {
256+
mask-image: url('$(res)/img/element-icons/call/voice-call.svg');
257+
258+
// The call button SVG is padded slightly differently, so match it up to the size
259+
// of the other icons
260+
mask-size: 20px;
261+
mask-position: center;
262+
}
263+
264+
.mx_RoomHeader_videoCallButton::before {
265+
mask-image: url('$(res)/img/element-icons/call/video-call.svg');
266+
}
267+
255268
.mx_RoomHeader_showPanel {
256269
height: 16px;
257270
}

src/components/structures/RoomView.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import ResizeNotifier from '../../utils/ResizeNotifier';
3434
import ContentMessages from '../../ContentMessages';
3535
import Modal from '../../Modal';
3636
import * as sdk from '../../index';
37-
import CallHandler from '../../CallHandler';
37+
import CallHandler, { PlaceCallType } from '../../CallHandler';
3838
import dis from '../../dispatcher/dispatcher';
3939
import Tinter from '../../Tinter';
4040
import rateLimitedFunc from '../../ratelimitedfunc';
@@ -1352,6 +1352,14 @@ export default class RoomView extends React.Component<IProps, IState> {
13521352
SettingsStore.setValue("PinnedEvents.isOpen", roomId, SettingLevel.ROOM_DEVICE, nowShowingPinned);
13531353
};
13541354

1355+
private onCallPlaced = (type: PlaceCallType) => {
1356+
dis.dispatch({
1357+
action: 'place_call',
1358+
type: type,
1359+
room_id: this.state.room.roomId,
1360+
});
1361+
};
1362+
13551363
private onSettingsClick = () => {
13561364
dis.dispatch({ action: "open_room_settings" });
13571365
};
@@ -2031,6 +2039,7 @@ export default class RoomView extends React.Component<IProps, IState> {
20312039
e2eStatus={this.state.e2eStatus}
20322040
onAppsClick={this.state.hasPinnedWidgets ? this.onAppsClick : null}
20332041
appsShown={this.state.showApps}
2042+
onCallPlaced={this.onCallPlaced}
20342043
/>
20352044
<MainSplit panel={rightPanel} resizeNotifier={this.props.resizeNotifier}>
20362045
<div className="mx_RoomView_body">

src/components/views/rooms/MessageComposer.js

Lines changed: 1 addition & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
/*
2-
Copyright 2015, 2016 OpenMarket Ltd
3-
Copyright 2017, 2018 New Vector Ltd
4-
Copyright 2020 The Matrix.org Foundation C.I.C.
2+
Copyright 2015-2018, 2020, 2021 The Matrix.org Foundation C.I.C.
53
64
Licensed under the Apache License, Version 2.0 (the "License");
75
you may not use this file except in compliance with the License.
@@ -19,7 +17,6 @@ import React, {createRef} from 'react';
1917
import classNames from 'classnames';
2018
import PropTypes from 'prop-types';
2119
import { _t } from '../../../languageHandler';
22-
import CallHandler from '../../../CallHandler';
2320
import {MatrixClientPeg} from '../../../MatrixClientPeg';
2421
import * as sdk from '../../../index';
2522
import dis from '../../../dispatcher/dispatcher';
@@ -33,11 +30,8 @@ import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
3330
import ReplyPreview from "./ReplyPreview";
3431
import {UIFeature} from "../../../settings/UIFeature";
3532
import WidgetStore from "../../../stores/WidgetStore";
36-
import WidgetUtils from "../../../utils/WidgetUtils";
3733
import {UPDATE_EVENT} from "../../../stores/AsyncStore";
3834
import ActiveWidgetStore from "../../../stores/ActiveWidgetStore";
39-
import { PlaceCallType } from "../../../CallHandler";
40-
import { CallState } from 'matrix-js-sdk/src/webrtc/call';
4135

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

53-
function CallButton(props) {
54-
const onVoiceCallClick = (ev) => {
55-
dis.dispatch({
56-
action: 'place_call',
57-
type: PlaceCallType.Voice,
58-
room_id: props.roomId,
59-
});
60-
};
61-
62-
return (<AccessibleTooltipButton
63-
className="mx_MessageComposer_button mx_MessageComposer_voicecall"
64-
onClick={onVoiceCallClick}
65-
title={_t('Voice call')}
66-
/>);
67-
}
68-
69-
CallButton.propTypes = {
70-
roomId: PropTypes.string.isRequired,
71-
};
72-
73-
function VideoCallButton(props) {
74-
const onCallClick = (ev) => {
75-
dis.dispatch({
76-
action: 'place_call',
77-
type: ev.shiftKey ? PlaceCallType.ScreenSharing : PlaceCallType.Video,
78-
room_id: props.roomId,
79-
});
80-
};
81-
82-
return <AccessibleTooltipButton
83-
className="mx_MessageComposer_button mx_MessageComposer_videocall"
84-
onClick={onCallClick}
85-
title={_t('Video call')}
86-
/>;
87-
}
88-
89-
VideoCallButton.propTypes = {
90-
roomId: PropTypes.string.isRequired,
91-
};
92-
93-
function HangupButton(props) {
94-
const onHangupClick = () => {
95-
if (props.isConference) {
96-
dis.dispatch({
97-
action: props.canEndConference ? 'end_conference' : 'hangup_conference',
98-
room_id: props.roomId,
99-
});
100-
return;
101-
}
102-
103-
const call = CallHandler.sharedInstance().getCallForRoom(props.roomId);
104-
if (!call) {
105-
return;
106-
}
107-
108-
const action = call.state === CallState.Ringing ? 'reject' : 'hangup';
109-
110-
dis.dispatch({
111-
action,
112-
// hangup the call for this room. NB. We use the room in props as the room ID
113-
// as call.roomId may be the 'virtual room', and the dispatch actions always
114-
// use the user-facing room (there was a time when we deliberately used
115-
// call.roomId and *not* props.roomId, but that was for the old
116-
// style Freeswitch conference calls and those times are gone.)
117-
room_id: props.roomId,
118-
});
119-
};
120-
121-
let tooltip = _t("Hangup");
122-
if (props.isConference && props.canEndConference) {
123-
tooltip = _t("End conference");
124-
}
125-
126-
const canLeaveConference = !props.isConference ? true : props.isInConference;
127-
return (
128-
<AccessibleTooltipButton
129-
className="mx_MessageComposer_button mx_MessageComposer_hangup"
130-
onClick={onHangupClick}
131-
title={tooltip}
132-
disabled={!canLeaveConference}
133-
/>
134-
);
135-
}
136-
137-
HangupButton.propTypes = {
138-
roomId: PropTypes.string.isRequired,
139-
isConference: PropTypes.bool.isRequired,
140-
canEndConference: PropTypes.bool,
141-
isInConference: PropTypes.bool,
142-
};
143-
14447
const EmojiButton = ({addEmoji}) => {
14548
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
14649

@@ -265,7 +168,6 @@ export default class MessageComposer extends React.Component {
265168
this.state = {
266169
tombstone: this._getRoomTombstone(),
267170
canSendMessages: this.props.room.maySendMessage(),
268-
showCallButtons: SettingsStore.getValue("showCallButtonsInComposer"),
269171
hasConference: WidgetStore.instance.doesRoomHaveConference(this.props.room),
270172
joinedConference: WidgetStore.instance.isJoinedToConferenceIn(this.props.room),
271173
};
@@ -405,12 +307,7 @@ export default class MessageComposer extends React.Component {
405307
];
406308

407309
if (!this.state.tombstone && this.state.canSendMessages) {
408-
// This also currently includes the call buttons. Really we should
409-
// check separately for whether we can call, but this is slightly
410-
// complex because of conference calls.
411-
412310
const SendMessageComposer = sdk.getComponent("rooms.SendMessageComposer");
413-
const callInProgress = this.props.callState && this.props.callState !== 'ended';
414311

415312
controls.push(
416313
<SendMessageComposer
@@ -430,30 +327,6 @@ export default class MessageComposer extends React.Component {
430327
SettingsStore.getValue("MessageComposerInput.showStickersButton")) {
431328
controls.push(<Stickerpicker key="stickerpicker_controls_button" room={this.props.room} />);
432329
}
433-
434-
if (this.state.showCallButtons) {
435-
if (this.state.hasConference) {
436-
const canEndConf = WidgetUtils.canUserModifyWidgets(this.props.room.roomId);
437-
controls.push(
438-
<HangupButton
439-
key="controls_hangup"
440-
roomId={this.props.room.roomId}
441-
isConference={true}
442-
canEndConference={canEndConf}
443-
isInConference={this.state.joinedConference}
444-
/>,
445-
);
446-
} else if (callInProgress) {
447-
controls.push(
448-
<HangupButton key="controls_hangup" roomId={this.props.room.roomId} isConference={false} />,
449-
);
450-
} else {
451-
controls.push(
452-
<CallButton key="controls_call" roomId={this.props.room.roomId} />,
453-
<VideoCallButton key="controls_videocall" roomId={this.props.room.roomId} />,
454-
);
455-
}
456-
}
457330
} else if (this.state.tombstone) {
458331
const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];
459332

src/components/views/rooms/RoomHeader.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {DefaultTagID} from "../../../stores/room-list/models";
3131
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
3232
import RoomTopic from "../elements/RoomTopic";
3333
import RoomName from "../elements/RoomName";
34+
import {PlaceCallType} from "../../../CallHandler";
3435

3536
export default class RoomHeader extends React.Component {
3637
static propTypes = {
@@ -45,6 +46,7 @@ export default class RoomHeader extends React.Component {
4546
e2eStatus: PropTypes.string,
4647
onAppsClick: PropTypes.func,
4748
appsShown: PropTypes.bool,
49+
onCallPlaced: PropTypes.func, // (PlaceCallType) => void;
4850
};
4951

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

231+
let voiceCallButton;
232+
let videoCallButton;
233+
if (this.props.inRoom && SettingsStore.getValue("showCallButtonsInComposer")) {
234+
voiceCallButton =
235+
<AccessibleTooltipButton
236+
className="mx_RoomHeader_button mx_RoomHeader_voiceCallButton"
237+
onClick={() => this.props.onCallPlaced(PlaceCallType.Voice)}
238+
title={_t("Voice call")} />;
239+
videoCallButton =
240+
<AccessibleTooltipButton
241+
className="mx_RoomHeader_button mx_RoomHeader_videoCallButton"
242+
onClick={(ev) => this.props.onCallPlaced(
243+
ev.shiftKey ? PlaceCallType.ScreenSharing : PlaceCallType.Video)}
244+
title={_t("Video call")} />;
245+
}
246+
229247
const rightRow =
230248
<div className="mx_RoomHeader_buttons">
249+
{ videoCallButton }
250+
{ voiceCallButton }
231251
{ pinnedEventsButton }
232252
{ forgetButton }
233253
{ appsButton }

src/i18n/strings/en_EN.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,9 +1416,6 @@
14161416
"Invited": "Invited",
14171417
"Filter room members": "Filter room members",
14181418
"%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (power %(powerLevelNumber)s)",
1419-
"Voice call": "Voice call",
1420-
"Video call": "Video call",
1421-
"Hangup": "Hangup",
14221419
"Emoji picker": "Emoji picker",
14231420
"Upload file": "Upload file",
14241421
"Send an encrypted reply…": "Send an encrypted reply…",
@@ -1476,6 +1473,8 @@
14761473
"Hide Widgets": "Hide Widgets",
14771474
"Show Widgets": "Show Widgets",
14781475
"Search": "Search",
1476+
"Voice call": "Voice call",
1477+
"Video call": "Video call",
14791478
"Start a Conversation": "Start a Conversation",
14801479
"Open dial pad": "Open dial pad",
14811480
"Invites": "Invites",

src/settings/Settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,8 @@ export const SETTINGS: {[setting: string]: ISetting} = {
632632
default: 3000,
633633
},
634634
"showCallButtonsInComposer": {
635+
// Dev note: This is no longer "in composer" but is instead "in room header".
636+
// TODO: Rename with settings v3
635637
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
636638
default: true,
637639
controller: new UIFeatureController(UIFeature.Voip),

0 commit comments

Comments
 (0)