blob: 0d401a2f63d1f161071290cf975af75d2b3edef0 [file] [log] [blame]
simon26e79f72022-10-05 22:16:08 -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 */
simond47ef9e2022-09-28 22:24:28 -040018import { QuestionMark } from '@mui/icons-material';
simon35378692022-10-02 23:25:57 -040019import { Box, ClickAwayListener, IconButton, IconButtonProps, Popper, SvgIconProps } from '@mui/material';
simond47ef9e2022-09-28 22:24:28 -040020import { styled } from '@mui/material/styles';
simon35378692022-10-02 23:25:57 -040021import EmojiPicker, { IEmojiData } from 'emoji-picker-react';
22import React, { ComponentType, MouseEvent, useCallback, useState } from 'react';
simon07b4eb02022-09-29 17:50:26 -040023
simond47ef9e2022-09-28 22:24:28 -040024import {
25 Arrow2Icon,
26 Arrow3Icon,
27 ArrowIcon,
Gabriel Rochone3ec0d22022-10-08 14:27:03 -040028 CallEndIcon,
simond47ef9e2022-09-28 22:24:28 -040029 CameraIcon,
30 CameraInBubbleIcon,
31 CancelIcon,
Gabriel Rochone3ec0d22022-10-08 14:27:03 -040032 ChatBubbleIcon,
simond47ef9e2022-09-28 22:24:28 -040033 CrossedEyeIcon,
34 CrossIcon,
35 EmojiIcon,
Gabriel Rochone3ec0d22022-10-08 14:27:03 -040036 ExtensionIcon,
simond47ef9e2022-09-28 22:24:28 -040037 EyeIcon,
38 FolderIcon,
Gabriel Rochone3ec0d22022-10-08 14:27:03 -040039 FullscreenIcon,
40 GroupAddIcon,
simond47ef9e2022-09-28 22:24:28 -040041 InfoIcon,
Gabriel Rochone3ec0d22022-10-08 14:27:03 -040042 MicroIcon,
simond47ef9e2022-09-28 22:24:28 -040043 MicroInBubbleIcon,
44 PaperClipIcon,
45 PenIcon,
Gabriel Rochone3ec0d22022-10-08 14:27:03 -040046 RecordingIcon,
simond47ef9e2022-09-28 22:24:28 -040047 SaltireIcon,
Gabriel Rochone3ec0d22022-10-08 14:27:03 -040048 ScreenShareIcon,
49 VideoCameraIcon,
50 VolumeIcon,
simon35378692022-10-02 23:25:57 -040051} from './SvgIcon';
Michelle Sepkap Simef5ebc2e2022-10-27 18:30:53 -040052import CustomTooltip from './Tooltip';
idillon-sfl44b05342022-08-24 15:46:42 -040053
simon35378692022-10-02 23:25:57 -040054type ShapedButtonProps = IconButtonProps & {
55 Icon: ComponentType<SvgIconProps>;
56};
57
58const RoundButton = styled(({ Icon, ...props }: ShapedButtonProps) => (
simond47ef9e2022-09-28 22:24:28 -040059 <IconButton {...props} disableRipple={true}>
60 <Icon fontSize="inherit" />
61 </IconButton>
62))(({ theme }) => ({
63 border: `1px solid ${theme.palette.primary.dark}`,
64 color: theme.palette.primary.dark,
65 fontSize: '15px',
66 '&:hover': {
67 background: theme.palette.primary.light,
68 },
69 '&:active': {
70 color: '#FFF',
71 background: theme.palette.primary.dark,
72 },
73 '&.MuiIconButton-sizeSmall': {
74 height: '15px',
75 width: '15px',
76 },
77 '&.MuiIconButton-sizeMedium': {
78 height: '30px',
79 width: '30px',
80 },
81 '&.MuiIconButton-sizeLarge': {
82 height: '53px',
83 width: '53px',
84 },
idillon-sfld5cc7862022-08-25 11:11:34 -040085}));
idillon-sfl44b05342022-08-24 15:46:42 -040086
simon35378692022-10-02 23:25:57 -040087export const CancelPictureButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -040088 return <RoundButton {...props} aria-label="remove picture" Icon={CancelIcon} size="large" />;
89};
idillon-sfl44b05342022-08-24 15:46:42 -040090
simon35378692022-10-02 23:25:57 -040091export const EditPictureButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -040092 return <RoundButton {...props} aria-label="edit picture" Icon={PenIcon} size="large" />;
93};
idillon-sfl44b05342022-08-24 15:46:42 -040094
simon35378692022-10-02 23:25:57 -040095export const UploadPictureButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -040096 return <RoundButton {...props} aria-label="upload picture" Icon={FolderIcon} size="large" />;
97};
idillon-sfl44b05342022-08-24 15:46:42 -040098
simon35378692022-10-02 23:25:57 -040099export const TakePictureButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400100 return <RoundButton {...props} aria-label="take picture" Icon={CameraIcon} size="large" />;
101};
idillon-sfl37c18df2022-08-26 18:44:27 -0400102
Michelle Sepkap Simef5ebc2e2022-10-27 18:30:53 -0400103type InfoButtonProps = IconButtonProps & {
104 tooltipTitle: string;
105};
106export const InfoButton = ({ tooltipTitle, ...props }: InfoButtonProps) => {
107 return (
108 <CustomTooltip className="tooltip" title={tooltipTitle}>
109 <RoundButton {...props} aria-label="informations" Icon={InfoIcon} size="small" />
110 </CustomTooltip>
111 );
simond47ef9e2022-09-28 22:24:28 -0400112};
idillon-sfl37c18df2022-08-26 18:44:27 -0400113
simon35378692022-10-02 23:25:57 -0400114export const TipButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400115 return <RoundButton {...props} aria-label="tip" Icon={QuestionMark} size="medium" />;
116};
idillon-sfl37c18df2022-08-26 18:44:27 -0400117
simon35378692022-10-02 23:25:57 -0400118export const MoreButton = styled((props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400119 return (
120 <IconButton {...props} disableRipple={true} aria-label="more">
121 <CrossIcon fontSize="inherit" />
122 </IconButton>
123 );
124})(({ theme }) => ({
125 border: `1px solid ${theme.palette.primary.dark}`,
126 color: theme.palette.primary.dark,
127 fontSize: '10px',
128 height: '20px',
129 width: '20px',
130 '&:hover': {
131 background: theme.palette.primary.light,
132 },
133 '&:active': {
134 color: '#FFF',
135 background: theme.palette.primary.dark,
136 },
137}));
idillon927b7592022-09-15 12:56:45 -0400138
simon35378692022-10-02 23:25:57 -0400139export const BackButton = styled((props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400140 return (
141 <IconButton {...props} disableRipple={true} aria-label="back">
142 <ArrowIcon fontSize="inherit" />
143 </IconButton>
144 );
145})(({ theme }) => ({
146 color: theme.palette.primary.dark,
147 fontSize: '15px',
148 height: '30px',
149 width: '51px',
150 borderRadius: '5px',
151 '&:hover': {
152 background: theme.palette.primary.light,
153 },
154}));
idillonb3788bf2022-08-29 15:57:57 -0400155
Gabriel Rochone3ec0d22022-10-08 14:27:03 -0400156export const CallingChatButton = (props: IconButtonProps) => {
157 return (
158 <IconButton {...props} aria-label="chat" sx={{ color: 'white' }}>
159 <ChatBubbleIcon />
160 </IconButton>
161 );
162};
163
164export const CallingEndButton = (props: IconButtonProps) => {
165 return (
166 <IconButton {...props} aria-label="end call" sx={{ color: 'white', backgroundColor: 'red' }}>
167 <CallEndIcon />
168 </IconButton>
169 );
170};
171
172export const CallingExtensionButton = (props: IconButtonProps) => {
173 return (
174 <IconButton {...props} aria-label="extensions" sx={{ color: 'white' }}>
175 <ExtensionIcon />
176 </IconButton>
177 );
178};
179
180export const CallingFullscreenButton = (props: IconButtonProps) => {
181 return (
182 <IconButton {...props} aria-label="fullscreen" sx={{ color: 'white' }}>
183 <FullscreenIcon />
184 </IconButton>
185 );
186};
187
188export const CallingGroupButton = (props: IconButtonProps) => {
189 return (
190 <IconButton {...props} aria-label="group options" sx={{ color: 'white' }}>
191 <GroupAddIcon />
192 </IconButton>
193 );
194};
195
196export const CallingMicButton = (props: IconButtonProps) => {
197 return (
198 <IconButton {...props} aria-label="microphone options" sx={{ color: 'white' }}>
199 <MicroIcon />
200 </IconButton>
201 );
202};
203
204export const CallingRecordButton = (props: IconButtonProps) => {
205 return (
206 <IconButton {...props} aria-label="recording options" sx={{ color: 'white' }}>
207 <RecordingIcon />
208 </IconButton>
209 );
210};
211
212export const CallingScreenShareButton = (props: IconButtonProps) => {
213 return (
214 <IconButton {...props} aria-label="screen share" sx={{ color: 'white' }}>
215 <ScreenShareIcon />
216 </IconButton>
217 );
218};
219
220export const CallingVideoCameraButton = (props: IconButtonProps) => {
221 return (
222 <IconButton {...props} aria-label="camera options" sx={{ color: 'white' }}>
223 <VideoCameraIcon />
224 </IconButton>
225 );
226};
227export const CallingVolumeButton = (props: IconButtonProps) => {
228 return (
229 <IconButton {...props} aria-label="volume options" sx={{ color: 'white' }}>
230 <VolumeIcon />
231 </IconButton>
232 );
233};
234
simon35378692022-10-02 23:25:57 -0400235export const CloseButton = styled((props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400236 return (
237 <IconButton {...props} disableRipple={true} aria-label="close">
238 <SaltireIcon fontSize="inherit" />
239 </IconButton>
240 );
241})(({ theme }) => ({
242 color: theme.palette.primary.dark,
243 fontSize: '15px',
244 height: '30px',
245 width: '30px',
246 borderRadius: '5px',
247 '&:hover': {
248 background: theme.palette.primary.light,
249 },
250}));
idillonb3788bf2022-08-29 15:57:57 -0400251
simon35378692022-10-02 23:25:57 -0400252type ToggleVisibilityButtonProps = IconButtonProps & {
253 visible: boolean;
254};
255export const ToggleVisibilityButton = styled(({ visible, ...props }: ToggleVisibilityButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400256 const Icon = visible ? CrossedEyeIcon : EyeIcon;
257 return (
258 <IconButton {...props} disableRipple={true}>
259 <Icon fontSize="inherit" />
260 </IconButton>
261 );
262})(({ theme }) => ({
263 color: theme.palette.primary.dark,
264 fontSize: '15px',
265 height: '15px',
266 width: '15px',
267 '&:hover': {
268 background: theme.palette.primary.light,
269 },
270}));
idillonaedab942022-09-01 14:29:43 -0400271
simon35378692022-10-02 23:25:57 -0400272const SquareButton = styled(({ Icon, ...props }: ShapedButtonProps) => (
simond47ef9e2022-09-28 22:24:28 -0400273 <IconButton {...props} disableRipple={true}>
274 <Icon fontSize="inherit" />
275 </IconButton>
276))(({ theme }) => ({
277 color: '#7E7E7E',
278 fontSize: '25px',
279 height: '36px',
280 width: '36px',
281 borderRadius: '5px',
282 '&:hover': {
283 background: '#E5E5E5',
284 },
idillonaedab942022-09-01 14:29:43 -0400285}));
286
simon35378692022-10-02 23:25:57 -0400287export const RecordVideoMessageButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400288 return <SquareButton {...props} aria-label="record video message" Icon={CameraInBubbleIcon} />;
289};
idillonaedab942022-09-01 14:29:43 -0400290
simon35378692022-10-02 23:25:57 -0400291export const RecordVoiceMessageButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400292 return <SquareButton {...props} aria-label="record voice message" Icon={MicroInBubbleIcon} />;
293};
idillonaedab942022-09-01 14:29:43 -0400294
simon35378692022-10-02 23:25:57 -0400295export const UploadFileButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400296 return <SquareButton {...props} aria-label="upload file" Icon={PaperClipIcon} />;
297};
idillonaedab942022-09-01 14:29:43 -0400298
simon35378692022-10-02 23:25:57 -0400299export const SendMessageButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400300 return <SquareButton {...props} aria-label="send message" Icon={Arrow2Icon} />;
301};
idillonaedab942022-09-01 14:29:43 -0400302
simon35378692022-10-02 23:25:57 -0400303export const ReplyMessageButton = styled((props: IconButtonProps) => (
simond47ef9e2022-09-28 22:24:28 -0400304 <IconButton {...props} disableRipple={true} aria-label="send message">
305 <Arrow3Icon fontSize="inherit" />
306 </IconButton>
307))(({ theme }) => ({
308 color: theme.palette.primary.dark,
309 fontSize: '20px',
310 height: '20px',
311 width: '20px',
312 borderRadius: '5px',
313 '&:hover': {
314 background: '#E5E5E5',
315 },
idillon927b7592022-09-15 12:56:45 -0400316}));
317
simon35378692022-10-02 23:25:57 -0400318type EmojiButtonProps = IconButtonProps & {
319 emoji: string;
320};
321export const EmojiButton = styled(({ emoji, ...props }: EmojiButtonProps) => (
simond47ef9e2022-09-28 22:24:28 -0400322 <IconButton {...props} disableRipple={true}>
323 {emoji}
324 </IconButton>
325))(({ theme }) => ({
326 color: 'white',
327 fontSize: '20px',
328 height: '20px',
329 width: '20px',
idillon927b7592022-09-15 12:56:45 -0400330}));
331
simon35378692022-10-02 23:25:57 -0400332type SelectEmojiButtonProps = {
333 onEmojiSelected: (emoji: string) => void;
334};
335export const SelectEmojiButton = ({ onEmojiSelected, ...props }: SelectEmojiButtonProps) => {
336 const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
idillon1664bb22022-09-14 17:18:15 -0400337
simon35378692022-10-02 23:25:57 -0400338 const handleOpenEmojiPicker = useCallback(
339 (e: MouseEvent<HTMLButtonElement>) => setAnchorEl(anchorEl ? null : e.currentTarget),
340 [anchorEl]
341 );
simond47ef9e2022-09-28 22:24:28 -0400342
343 const handleClose = useCallback(() => setAnchorEl(null), [setAnchorEl]);
344
345 const onEmojiClick = useCallback(
simon35378692022-10-02 23:25:57 -0400346 (e: MouseEvent, emojiObject: IEmojiData) => {
simon80b7b3b2022-09-28 17:50:10 -0400347 onEmojiSelected(emojiObject.emoji);
simond47ef9e2022-09-28 22:24:28 -0400348 handleClose();
349 },
simon80b7b3b2022-09-28 17:50:10 -0400350 [handleClose, onEmojiSelected]
simond47ef9e2022-09-28 22:24:28 -0400351 );
352
353 const open = Boolean(anchorEl);
354 const id = open ? 'simple-popover' : undefined;
355
356 return (
357 <ClickAwayListener onClickAway={handleClose}>
358 <Box>
simon35378692022-10-02 23:25:57 -0400359 <SquareButton aria-describedby={id} aria-label="select emoji" Icon={EmojiIcon} onClick={(e) => {}} />
360 <Popper id={id} open={open} anchorEl={anchorEl}>
361 <EmojiPicker onEmojiClick={onEmojiClick} disableAutoFocus={true} disableSkinTonePicker={true} native />
simond47ef9e2022-09-28 22:24:28 -0400362 </Popper>
363 </Box>
364 </ClickAwayListener>
365 );
366};