blob: 594a1cc0d22532f3ce5dee307c6c4b8643ed9348 [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';
simon4e7445c2022-11-16 21:18:46 -050021import { useTranslation } 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 ({
simon4e7445c2022-11-16 21:18:46 -050060 buttonColor,
simon2d3b6532022-11-08 21:01:57 -050061 ...props
62 }: ExpandableButtonProps & {
63 buttonColor: ColoredCallButtonColor;
64 }) => {
65 return <ExpandableButton {...props} />;
66 }
67)(({ buttonColor }) => {
68 return {
69 color: 'white',
70 backgroundColor: buttonColor === 'green' ? '#183722' : '#5E070D',
71 '&:hover': {
72 backgroundColor: buttonColor === 'green' ? '#0B8271' : '#CC0022',
73 },
74 };
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050075});
76
simon33c06182022-11-02 17:39:31 -040077export const CallingChatButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050078 return <CallButton aria-label="chat" Icon={ChatBubbleIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040079};
simon33c06182022-11-02 17:39:31 -040080
81export const CallingEndButton = (props: ExpandableButtonProps) => {
simon2d3b6532022-11-08 21:01:57 -050082 return <ColoredCallButton buttonColor="red" aria-label="call end" Icon={CallEndIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040083};
simon33c06182022-11-02 17:39:31 -040084
85export const CallingExtensionButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050086 return <CallButton aria-label="extensions" Icon={ExtensionIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040087};
simon33c06182022-11-02 17:39:31 -040088
89export const CallingFullScreenButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050090 return <CallButton aria-label="full screen" Icon={FullScreenIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040091};
simon33c06182022-11-02 17:39:31 -040092
93export const CallingGroupButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050094 return <CallButton aria-label="group options" Icon={GroupAddIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040095};
simon33c06182022-11-02 17:39:31 -040096
97export const CallingMoreVerticalButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -050098 return <CallButton aria-label="more vertical" Icon={MoreVerticalIcon} {...props} />;
simon1170c322022-10-31 14:51:31 -040099};
simon33c06182022-11-02 17:39:31 -0400100
101export const CallingRecordButton = (props: ExpandableButtonProps) => {
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500102 return <CallButton aria-label="recording options" Icon={RecordingIcon} {...props} />;
simon33c06182022-11-02 17:39:31 -0400103};
104
105export const CallingScreenShareButton = (props: ExpandableButtonProps) => {
simon4e7445c2022-11-16 21:18:46 -0500106 const { t } = useTranslation();
simon1170c322022-10-31 14:51:31 -0400107 return (
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500108 <CallButton
simon33c06182022-11-02 17:39:31 -0400109 aria-label="screen share"
110 Icon={ScreenShareArrowIcon}
111 expandMenuOptions={[
112 {
simon4e7445c2022-11-16 21:18:46 -0500113 description: t('share_screen'),
simon33c06182022-11-02 17:39:31 -0400114 icon: <ScreenShareRegularIcon />,
115 },
116 {
simon4e7445c2022-11-16 21:18:46 -0500117 description: t('share_window'),
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500118 icon: <WindowIcon />,
119 },
120 {
simon4e7445c2022-11-16 21:18:46 -0500121 description: t('share_screen_area'),
simon33c06182022-11-02 17:39:31 -0400122 icon: <ScreenShareScreenAreaIcon />,
123 },
124 {
simon4e7445c2022-11-16 21:18:46 -0500125 description: t('share_file'),
simon33c06182022-11-02 17:39:31 -0400126 icon: <FileIcon />,
127 },
128 ]}
129 {...props}
130 />
simon1170c322022-10-31 14:51:31 -0400131 );
132};
133
simon9a8fe202022-11-15 18:25:49 -0500134const useMediaDeviceExpandMenuOptions = (kind: MediaDeviceKind) => {
135 const { mediaDevices } = useContext(WebRTCContext);
136
137 return useMemo(
138 () =>
139 mediaDevices[kind].map((device) => ({
140 key: device.deviceId,
141 description: device.label,
142 })),
143 [mediaDevices, kind]
144 );
145};
146
simon33c06182022-11-02 17:39:31 -0400147export const CallingVolumeButton = (props: ExpandableButtonProps) => {
simon9a8fe202022-11-15 18:25:49 -0500148 const options = useMediaDeviceExpandMenuOptions('audiooutput');
149
simon33c06182022-11-02 17:39:31 -0400150 return (
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500151 <CallButton
simon33c06182022-11-02 17:39:31 -0400152 aria-label="volume options"
153 Icon={VolumeIcon}
154 expandMenuOptions={[
155 {
simon9a8fe202022-11-15 18:25:49 -0500156 options,
simon33c06182022-11-02 17:39:31 -0400157 },
158 ]}
159 {...props}
160 />
161 );
162};
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500163
164export const CallingMicButton = (props: ExpandableButtonProps) => {
simonce2c0c42022-11-02 17:39:31 -0400165 const { isAudioOn, setAudioStatus } = useContext(WebRTCContext);
simon9a8fe202022-11-15 18:25:49 -0500166 const options = useMediaDeviceExpandMenuOptions('audioinput');
simon1170c322022-10-31 14:51:31 -0400167
168 return (
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500169 <CallButton
simon1170c322022-10-31 14:51:31 -0400170 aria-label="microphone options"
simon9a8fe202022-11-15 18:25:49 -0500171 expandMenuOptions={[
172 {
173 options,
174 },
175 ]}
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500176 IconButtonComp={(props) => (
177 <ToggleIconButton
178 IconOn={MicroIcon}
179 IconOff={MicroOffIcon}
180 selected={isAudioOn}
181 toggle={() => setAudioStatus(!isAudioOn)}
182 {...props}
183 />
184 )}
simon1170c322022-10-31 14:51:31 -0400185 {...props}
186 />
187 );
188};
189
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500190export const CallingVideoCameraButton = (props: ExpandableButtonProps) => {
simonce2c0c42022-11-02 17:39:31 -0400191 const { isVideoOn, setVideoStatus } = useContext(WebRTCContext);
simon9a8fe202022-11-15 18:25:49 -0500192 const options = useMediaDeviceExpandMenuOptions('videoinput');
193
simon1170c322022-10-31 14:51:31 -0400194 return (
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500195 <CallButton
simon1170c322022-10-31 14:51:31 -0400196 aria-label="camera options"
simon9a8fe202022-11-15 18:25:49 -0500197 expandMenuOptions={[
198 {
199 options,
200 },
201 ]}
Gabriel Rochon8321a0d2022-11-06 23:18:36 -0500202 IconButtonComp={(props) => (
203 <ToggleIconButton
204 IconOn={VideoCameraIcon}
205 IconOff={VideoCameraOffIcon}
206 selected={isVideoOn}
207 toggle={() => setVideoStatus(!isVideoOn)}
208 {...props}
209 />
210 )}
simon1170c322022-10-31 14:51:31 -0400211 {...props}
212 />
213 );
214};
simon2d3b6532022-11-08 21:01:57 -0500215
216// Calling pending/receiving interface
217export const CallingAnswerAudioButton = (props: ExpandableButtonProps) => {
218 return <ColoredCallButton aria-label="answer audio" buttonColor="green" Icon={PlaceAudioCallIcon} {...props} />;
219};
220
221export const CallingAnswerVideoButton = (props: ExpandableButtonProps) => {
222 return <ColoredCallButton aria-label="answer video" buttonColor="green" Icon={VideoCameraIcon} {...props} />;
223};
224
225export const CallingRefuseButton = (props: ExpandableButtonProps) => {
226 return <ColoredCallButton aria-label="reject" buttonColor="red" Icon={RoundCloseIcon} {...props} />;
227};