blob: dbaef70e4cd2f8409f844abfb453adfacb1e484d [file] [log] [blame]
simon1170c322022-10-31 14:51:31 -04001/*
2 * Copyright (C) 2022 Savoir-faire Linux Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
simon33c06182022-11-02 17:39:31 -040018
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050019import { styled } from '@mui/material/styles';
simon9a8fe202022-11-15 18:25:49 -050020import React, { useContext, useMemo } from 'react';
simon33c06182022-11-02 17:39:31 -040021import { Trans } from 'react-i18next';
simon1170c322022-10-31 14:51:31 -040022
simonce2c0c42022-11-02 17:39:31 -040023import { WebRTCContext } from '../contexts/WebRTCProvider';
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050024import { ExpandableButton, ExpandableButtonProps, ToggleIconButton } from './Button';
simon1170c322022-10-31 14:51:31 -040025import {
26 CallEndIcon,
27 ChatBubbleIcon,
28 ExtensionIcon,
simon33c06182022-11-02 17:39:31 -040029 FileIcon,
30 FullScreenIcon,
simon1170c322022-10-31 14:51:31 -040031 GroupAddIcon,
32 MicroIcon,
33 MicroOffIcon,
simon33c06182022-11-02 17:39:31 -040034 MoreVerticalIcon,
simon2d3b6532022-11-08 21:01:57 -050035 PlaceAudioCallIcon,
simon1170c322022-10-31 14:51:31 -040036 RecordingIcon,
simon2d3b6532022-11-08 21:01:57 -050037 RoundCloseIcon,
simon33c06182022-11-02 17:39:31 -040038 ScreenShareArrowIcon,
39 ScreenShareRegularIcon,
40 ScreenShareScreenAreaIcon,
simon1170c322022-10-31 14:51:31 -040041 VideoCameraIcon,
42 VideoCameraOffIcon,
43 VolumeIcon,
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050044 WindowIcon,
simon1170c322022-10-31 14:51:31 -040045} from './SvgIcon';
46
simon2d3b6532022-11-08 21:01:57 -050047type ColoredCallButtonColor = 'red' | 'green';
48
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050049const CallButton = styled((props: ExpandableButtonProps) => {
50 return <ExpandableButton {...props} />;
51})({
simon2d3b6532022-11-08 21:01:57 -050052 color: 'white',
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050053 '&:hover': {
54 backgroundColor: 'rgba(255, 255, 255, 0.15)',
55 },
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050056});
57
simon2d3b6532022-11-08 21:01:57 -050058const ColoredCallButton = styled(
59 ({
60 ...props
61 }: ExpandableButtonProps & {
62 buttonColor: ColoredCallButtonColor;
63 }) => {
64 return <ExpandableButton {...props} />;
65 }
66)(({ buttonColor }) => {
67 return {
68 color: 'white',
69 backgroundColor: buttonColor === 'green' ? '#183722' : '#5E070D',
70 '&:hover': {
71 backgroundColor: buttonColor === 'green' ? '#0B8271' : '#CC0022',
72 },
73 };
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050074});
75
simon33c06182022-11-02 17:39:31 -040076export const CallingChatButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050077 return <CallButton aria-label="chat" Icon={ChatBubbleIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040078};
simon33c06182022-11-02 17:39:31 -040079
80export const CallingEndButton = (props: ExpandableButtonProps) => {
simon2d3b6532022-11-08 21:01:57 -050081 return <ColoredCallButton buttonColor="red" aria-label="call end" Icon={CallEndIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040082};
simon33c06182022-11-02 17:39:31 -040083
84export const CallingExtensionButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050085 return <CallButton aria-label="extensions" Icon={ExtensionIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040086};
simon33c06182022-11-02 17:39:31 -040087
88export const CallingFullScreenButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050089 return <CallButton aria-label="full screen" Icon={FullScreenIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040090};
simon33c06182022-11-02 17:39:31 -040091
92export const CallingGroupButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050093 return <CallButton aria-label="group options" Icon={GroupAddIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040094};
simon33c06182022-11-02 17:39:31 -040095
96export const CallingMoreVerticalButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050097 return <CallButton aria-label="more vertical" Icon={MoreVerticalIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040098};
simon33c06182022-11-02 17:39:31 -040099
100export const CallingRecordButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500101 return <CallButton aria-label="recording options" Icon={RecordingIcon} {...props} />;
simon33c06182022-11-02 17:39:31 -0400102};
103
104export const CallingScreenShareButton = (props: ExpandableButtonProps) => {
simon1170c322022-10-31 14:51:31 -0400105 return (
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500106 <CallButton
simon33c06182022-11-02 17:39:31 -0400107 aria-label="screen share"
108 Icon={ScreenShareArrowIcon}
109 expandMenuOptions={[
110 {
111 description: <Trans i18nKey="share_screen" />,
112 icon: <ScreenShareRegularIcon />,
113 },
114 {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500115 description: <Trans i18nKey="share_window" />,
116 icon: <WindowIcon />,
117 },
118 {
simon33c06182022-11-02 17:39:31 -0400119 description: <Trans i18nKey="share_screen_area" />,
120 icon: <ScreenShareScreenAreaIcon />,
121 },
122 {
123 description: <Trans i18nKey="share_file" />,
124 icon: <FileIcon />,
125 },
126 ]}
127 {...props}
128 />
simon1170c322022-10-31 14:51:31 -0400129 );
130};
131
simon9a8fe202022-11-15 18:25:49 -0500132const useMediaDeviceExpandMenuOptions = (kind: MediaDeviceKind) => {
133 const { mediaDevices } = useContext(WebRTCContext);
134
135 return useMemo(
136 () =>
137 mediaDevices[kind].map((device) => ({
138 key: device.deviceId,
139 description: device.label,
140 })),
141 [mediaDevices, kind]
142 );
143};
144
simon33c06182022-11-02 17:39:31 -0400145export const CallingVolumeButton = (props: ExpandableButtonProps) => {
simon9a8fe202022-11-15 18:25:49 -0500146 const options = useMediaDeviceExpandMenuOptions('audiooutput');
147
simon33c06182022-11-02 17:39:31 -0400148 return (
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500149 <CallButton
simon33c06182022-11-02 17:39:31 -0400150 aria-label="volume options"
151 Icon={VolumeIcon}
152 expandMenuOptions={[
153 {
simon9a8fe202022-11-15 18:25:49 -0500154 options,
simon33c06182022-11-02 17:39:31 -0400155 },
156 ]}
157 {...props}
158 />
159 );
160};
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500161
162export const CallingMicButton = (props: ExpandableButtonProps) => {
simonce2c0c42022-11-02 17:39:31 -0400163 const { isAudioOn, setAudioStatus } = useContext(WebRTCContext);
simon9a8fe202022-11-15 18:25:49 -0500164 const options = useMediaDeviceExpandMenuOptions('audioinput');
simon1170c322022-10-31 14:51:31 -0400165
166 return (
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500167 <CallButton
simon1170c322022-10-31 14:51:31 -0400168 aria-label="microphone options"
simon9a8fe202022-11-15 18:25:49 -0500169 expandMenuOptions={[
170 {
171 options,
172 },
173 ]}
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500174 IconButtonComp={(props) => (
175 <ToggleIconButton
176 IconOn={MicroIcon}
177 IconOff={MicroOffIcon}
178 selected={isAudioOn}
179 toggle={() => setAudioStatus(!isAudioOn)}
180 {...props}
181 />
182 )}
simon1170c322022-10-31 14:51:31 -0400183 {...props}
184 />
185 );
186};
187
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500188export const CallingVideoCameraButton = (props: ExpandableButtonProps) => {
simonce2c0c42022-11-02 17:39:31 -0400189 const { isVideoOn, setVideoStatus } = useContext(WebRTCContext);
simon9a8fe202022-11-15 18:25:49 -0500190 const options = useMediaDeviceExpandMenuOptions('videoinput');
191
simon1170c322022-10-31 14:51:31 -0400192 return (
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500193 <CallButton
simon1170c322022-10-31 14:51:31 -0400194 aria-label="camera options"
simon9a8fe202022-11-15 18:25:49 -0500195 expandMenuOptions={[
196 {
197 options,
198 },
199 ]}
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500200 IconButtonComp={(props) => (
201 <ToggleIconButton
202 IconOn={VideoCameraIcon}
203 IconOff={VideoCameraOffIcon}
204 selected={isVideoOn}
205 toggle={() => setVideoStatus(!isVideoOn)}
206 {...props}
207 />
208 )}
simon1170c322022-10-31 14:51:31 -0400209 {...props}
210 />
211 );
212};
simon2d3b6532022-11-08 21:01:57 -0500213
214// Calling pending/receiving interface
215export const CallingAnswerAudioButton = (props: ExpandableButtonProps) => {
216 return <ColoredCallButton aria-label="answer audio" buttonColor="green" Icon={PlaceAudioCallIcon} {...props} />;
217};
218
219export const CallingAnswerVideoButton = (props: ExpandableButtonProps) => {
220 return <ColoredCallButton aria-label="answer video" buttonColor="green" Icon={VideoCameraIcon} {...props} />;
221};
222
223export const CallingRefuseButton = (props: ExpandableButtonProps) => {
224 return <ColoredCallButton aria-label="reject" buttonColor="red" Icon={RoundCloseIcon} {...props} />;
225};