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

Commit c998095

Browse files
committed
Add CallViewDropdownButton
Signed-off-by: Šimon Brandner <[email protected]>
1 parent e7dcef9 commit c998095

File tree

1 file changed

+60
-10
lines changed

1 file changed

+60
-10
lines changed

src/components/views/voip/CallView/CallViewButtons.tsx

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
1616
limitations under the License.
1717
*/
1818

19-
import React, { createRef } from "react";
19+
import React, { createRef, useState } from "react";
2020
import classNames from "classnames";
2121
import { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
2222

@@ -26,10 +26,14 @@ import DialpadContextMenu from "../../context_menus/DialpadContextMenu";
2626
import { Alignment } from "../../elements/Tooltip";
2727
import {
2828
alwaysAboveLeftOf,
29+
alwaysAboveRightOf,
2930
ChevronFace,
3031
ContextMenuTooltipButton,
32+
useContextMenu,
3133
} from '../../../structures/ContextMenu';
3234
import { _t } from "../../../../languageHandler";
35+
import DeviceContextMenu from "../../context_menus/DeviceContextMenu";
36+
import { MediaDeviceKindEnum } from "../../../../MediaDeviceHandler";
3337

3438
// Height of the header duplicated from CSS because we need to subtract it from our max
3539
// height to get the max height of the video
@@ -39,15 +43,22 @@ const TOOLTIP_Y_OFFSET = -24;
3943

4044
const CONTROLS_HIDE_DELAY = 2000;
4145

42-
interface IButtonProps {
46+
interface IButtonProps extends Omit<React.ComponentProps<typeof AccessibleTooltipButton>, "title"> {
4347
state: boolean;
4448
className: string;
45-
onLabel: string;
46-
offLabel: string;
47-
onClick: () => void;
49+
onLabel?: string;
50+
offLabel?: string;
51+
onClick: (event: React.MouseEvent) => void;
4852
}
4953

50-
const CallViewToggleButton: React.FC<IButtonProps> = ({ state: isOn, className, onLabel, offLabel, onClick }) => {
54+
const CallViewToggleButton: React.FC<IButtonProps> = ({
55+
children,
56+
state: isOn,
57+
className,
58+
onLabel,
59+
offLabel,
60+
...props
61+
}) => {
5162
const classes = classNames("mx_CallViewButtons_button", className, {
5263
mx_CallViewButtons_button_on: isOn,
5364
mx_CallViewButtons_button_off: !isOn,
@@ -56,11 +67,48 @@ const CallViewToggleButton: React.FC<IButtonProps> = ({ state: isOn, className,
5667
return (
5768
<AccessibleTooltipButton
5869
className={classes}
59-
onClick={onClick}
6070
title={isOn ? onLabel : offLabel}
6171
alignment={Alignment.Top}
6272
yOffset={TOOLTIP_Y_OFFSET}
63-
/>
73+
{...props}
74+
>
75+
{ children }
76+
</AccessibleTooltipButton>
77+
);
78+
};
79+
80+
interface IDropdownButtonProps extends IButtonProps {
81+
deviceKinds: MediaDeviceKindEnum[];
82+
}
83+
84+
const CallViewDropdownButton: React.FC<IDropdownButtonProps> = ({ state, deviceKinds, ...props }) => {
85+
const [menuDisplayed, buttonRef, openMenu, closeMenu] = useContextMenu();
86+
const [hoveringDropdown, setHoveringDropdown] = useState(false);
87+
88+
const classes = classNames("mx_CallViewButtons_button", "mx_CallViewButtons_dropdownButton", {
89+
mx_CallViewButtons_dropdownButton_collapsed: !menuDisplayed,
90+
});
91+
92+
const onClick = (event: React.MouseEvent): void => {
93+
event.stopPropagation();
94+
openMenu();
95+
};
96+
97+
return (
98+
<CallViewToggleButton inputRef={buttonRef} forceHide={menuDisplayed || hoveringDropdown} state={state} {...props}>
99+
<CallViewToggleButton
100+
className={classes}
101+
onClick={onClick}
102+
onHover={(hovering) => setHoveringDropdown(hovering)}
103+
state={state}
104+
/>
105+
{ menuDisplayed && <DeviceContextMenu
106+
{...alwaysAboveRightOf(buttonRef.current?.getBoundingClientRect())}
107+
108+
onFinished={closeMenu}
109+
deviceKinds={deviceKinds}
110+
/> }
111+
</CallViewToggleButton>
64112
);
65113
};
66114

@@ -221,19 +269,21 @@ export default class CallViewButtons extends React.Component<IProps, IState> {
221269
alignment={Alignment.Top}
222270
yOffset={TOOLTIP_Y_OFFSET}
223271
/> }
224-
<CallViewToggleButton
272+
<CallViewDropdownButton
225273
state={!this.props.buttonsState.micMuted}
226274
className="mx_CallViewButtons_button_mic"
227275
onLabel={_t("Mute the microphone")}
228276
offLabel={_t("Unmute the microphone")}
229277
onClick={this.props.handlers.onMicMuteClick}
278+
deviceKinds={[MediaDeviceKindEnum.AudioInput, MediaDeviceKindEnum.AudioOutput]}
230279
/>
231-
{ this.props.buttonsVisibility.vidMute && <CallViewToggleButton
280+
{ this.props.buttonsVisibility.vidMute && <CallViewDropdownButton
232281
state={!this.props.buttonsState.vidMuted}
233282
className="mx_CallViewButtons_button_vid"
234283
onLabel={_t("Stop the camera")}
235284
offLabel={_t("Start the camera")}
236285
onClick={this.props.handlers.onVidMuteClick}
286+
deviceKinds={[MediaDeviceKindEnum.VideoInput]}
237287
/> }
238288
{ this.props.buttonsVisibility.screensharing && <CallViewToggleButton
239289
state={this.props.buttonsState.screensharing}

0 commit comments

Comments
 (0)