blob: 3c147d6a8be81db848e28d894d81d5d6a7e46cee [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,
28 CameraIcon,
29 CameraInBubbleIcon,
30 CancelIcon,
31 CrossedEyeIcon,
32 CrossIcon,
33 EmojiIcon,
34 EyeIcon,
35 FolderIcon,
36 InfoIcon,
37 MicroInBubbleIcon,
38 PaperClipIcon,
39 PenIcon,
40 SaltireIcon,
simon35378692022-10-02 23:25:57 -040041} from './SvgIcon';
idillon-sfl44b05342022-08-24 15:46:42 -040042
simon35378692022-10-02 23:25:57 -040043type ShapedButtonProps = IconButtonProps & {
44 Icon: ComponentType<SvgIconProps>;
45};
46
47const RoundButton = styled(({ Icon, ...props }: ShapedButtonProps) => (
simond47ef9e2022-09-28 22:24:28 -040048 <IconButton {...props} disableRipple={true}>
49 <Icon fontSize="inherit" />
50 </IconButton>
51))(({ theme }) => ({
52 border: `1px solid ${theme.palette.primary.dark}`,
53 color: theme.palette.primary.dark,
54 fontSize: '15px',
55 '&:hover': {
56 background: theme.palette.primary.light,
57 },
58 '&:active': {
59 color: '#FFF',
60 background: theme.palette.primary.dark,
61 },
62 '&.MuiIconButton-sizeSmall': {
63 height: '15px',
64 width: '15px',
65 },
66 '&.MuiIconButton-sizeMedium': {
67 height: '30px',
68 width: '30px',
69 },
70 '&.MuiIconButton-sizeLarge': {
71 height: '53px',
72 width: '53px',
73 },
idillon-sfld5cc7862022-08-25 11:11:34 -040074}));
idillon-sfl44b05342022-08-24 15:46:42 -040075
simon35378692022-10-02 23:25:57 -040076export const CancelPictureButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -040077 return <RoundButton {...props} aria-label="remove picture" Icon={CancelIcon} size="large" />;
78};
idillon-sfl44b05342022-08-24 15:46:42 -040079
simon35378692022-10-02 23:25:57 -040080export const EditPictureButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -040081 return <RoundButton {...props} aria-label="edit picture" Icon={PenIcon} size="large" />;
82};
idillon-sfl44b05342022-08-24 15:46:42 -040083
simon35378692022-10-02 23:25:57 -040084export const UploadPictureButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -040085 return <RoundButton {...props} aria-label="upload picture" Icon={FolderIcon} size="large" />;
86};
idillon-sfl44b05342022-08-24 15:46:42 -040087
simon35378692022-10-02 23:25:57 -040088export const TakePictureButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -040089 return <RoundButton {...props} aria-label="take picture" Icon={CameraIcon} size="large" />;
90};
idillon-sfl37c18df2022-08-26 18:44:27 -040091
simon35378692022-10-02 23:25:57 -040092export const InfoButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -040093 return <RoundButton {...props} aria-label="informations" Icon={InfoIcon} size="small" />;
94};
idillon-sfl37c18df2022-08-26 18:44:27 -040095
simon35378692022-10-02 23:25:57 -040096export const TipButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -040097 return <RoundButton {...props} aria-label="tip" Icon={QuestionMark} size="medium" />;
98};
idillon-sfl37c18df2022-08-26 18:44:27 -040099
simon35378692022-10-02 23:25:57 -0400100export const MoreButton = styled((props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400101 return (
102 <IconButton {...props} disableRipple={true} aria-label="more">
103 <CrossIcon fontSize="inherit" />
104 </IconButton>
105 );
106})(({ theme }) => ({
107 border: `1px solid ${theme.palette.primary.dark}`,
108 color: theme.palette.primary.dark,
109 fontSize: '10px',
110 height: '20px',
111 width: '20px',
112 '&:hover': {
113 background: theme.palette.primary.light,
114 },
115 '&:active': {
116 color: '#FFF',
117 background: theme.palette.primary.dark,
118 },
119}));
idillon927b7592022-09-15 12:56:45 -0400120
simon35378692022-10-02 23:25:57 -0400121export const BackButton = styled((props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400122 return (
123 <IconButton {...props} disableRipple={true} aria-label="back">
124 <ArrowIcon fontSize="inherit" />
125 </IconButton>
126 );
127})(({ theme }) => ({
128 color: theme.palette.primary.dark,
129 fontSize: '15px',
130 height: '30px',
131 width: '51px',
132 borderRadius: '5px',
133 '&:hover': {
134 background: theme.palette.primary.light,
135 },
136}));
idillonb3788bf2022-08-29 15:57:57 -0400137
simon35378692022-10-02 23:25:57 -0400138export const CloseButton = styled((props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400139 return (
140 <IconButton {...props} disableRipple={true} aria-label="close">
141 <SaltireIcon fontSize="inherit" />
142 </IconButton>
143 );
144})(({ theme }) => ({
145 color: theme.palette.primary.dark,
146 fontSize: '15px',
147 height: '30px',
148 width: '30px',
149 borderRadius: '5px',
150 '&:hover': {
151 background: theme.palette.primary.light,
152 },
153}));
idillonb3788bf2022-08-29 15:57:57 -0400154
simon35378692022-10-02 23:25:57 -0400155type ToggleVisibilityButtonProps = IconButtonProps & {
156 visible: boolean;
157};
158export const ToggleVisibilityButton = styled(({ visible, ...props }: ToggleVisibilityButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400159 const Icon = visible ? CrossedEyeIcon : EyeIcon;
160 return (
161 <IconButton {...props} disableRipple={true}>
162 <Icon fontSize="inherit" />
163 </IconButton>
164 );
165})(({ theme }) => ({
166 color: theme.palette.primary.dark,
167 fontSize: '15px',
168 height: '15px',
169 width: '15px',
170 '&:hover': {
171 background: theme.palette.primary.light,
172 },
173}));
idillonaedab942022-09-01 14:29:43 -0400174
simon35378692022-10-02 23:25:57 -0400175const SquareButton = styled(({ Icon, ...props }: ShapedButtonProps) => (
simond47ef9e2022-09-28 22:24:28 -0400176 <IconButton {...props} disableRipple={true}>
177 <Icon fontSize="inherit" />
178 </IconButton>
179))(({ theme }) => ({
180 color: '#7E7E7E',
181 fontSize: '25px',
182 height: '36px',
183 width: '36px',
184 borderRadius: '5px',
185 '&:hover': {
186 background: '#E5E5E5',
187 },
idillonaedab942022-09-01 14:29:43 -0400188}));
189
simon35378692022-10-02 23:25:57 -0400190export const RecordVideoMessageButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400191 return <SquareButton {...props} aria-label="record video message" Icon={CameraInBubbleIcon} />;
192};
idillonaedab942022-09-01 14:29:43 -0400193
simon35378692022-10-02 23:25:57 -0400194export const RecordVoiceMessageButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400195 return <SquareButton {...props} aria-label="record voice message" Icon={MicroInBubbleIcon} />;
196};
idillonaedab942022-09-01 14:29:43 -0400197
simon35378692022-10-02 23:25:57 -0400198export const UploadFileButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400199 return <SquareButton {...props} aria-label="upload file" Icon={PaperClipIcon} />;
200};
idillonaedab942022-09-01 14:29:43 -0400201
simon35378692022-10-02 23:25:57 -0400202export const SendMessageButton = (props: IconButtonProps) => {
simond47ef9e2022-09-28 22:24:28 -0400203 return <SquareButton {...props} aria-label="send message" Icon={Arrow2Icon} />;
204};
idillonaedab942022-09-01 14:29:43 -0400205
simon35378692022-10-02 23:25:57 -0400206export const ReplyMessageButton = styled((props: IconButtonProps) => (
simond47ef9e2022-09-28 22:24:28 -0400207 <IconButton {...props} disableRipple={true} aria-label="send message">
208 <Arrow3Icon fontSize="inherit" />
209 </IconButton>
210))(({ theme }) => ({
211 color: theme.palette.primary.dark,
212 fontSize: '20px',
213 height: '20px',
214 width: '20px',
215 borderRadius: '5px',
216 '&:hover': {
217 background: '#E5E5E5',
218 },
idillon927b7592022-09-15 12:56:45 -0400219}));
220
simon35378692022-10-02 23:25:57 -0400221type EmojiButtonProps = IconButtonProps & {
222 emoji: string;
223};
224export const EmojiButton = styled(({ emoji, ...props }: EmojiButtonProps) => (
simond47ef9e2022-09-28 22:24:28 -0400225 <IconButton {...props} disableRipple={true}>
226 {emoji}
227 </IconButton>
228))(({ theme }) => ({
229 color: 'white',
230 fontSize: '20px',
231 height: '20px',
232 width: '20px',
idillon927b7592022-09-15 12:56:45 -0400233}));
234
simon35378692022-10-02 23:25:57 -0400235type SelectEmojiButtonProps = {
236 onEmojiSelected: (emoji: string) => void;
237};
238export const SelectEmojiButton = ({ onEmojiSelected, ...props }: SelectEmojiButtonProps) => {
239 const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
idillon1664bb22022-09-14 17:18:15 -0400240
simon35378692022-10-02 23:25:57 -0400241 const handleOpenEmojiPicker = useCallback(
242 (e: MouseEvent<HTMLButtonElement>) => setAnchorEl(anchorEl ? null : e.currentTarget),
243 [anchorEl]
244 );
simond47ef9e2022-09-28 22:24:28 -0400245
246 const handleClose = useCallback(() => setAnchorEl(null), [setAnchorEl]);
247
248 const onEmojiClick = useCallback(
simon35378692022-10-02 23:25:57 -0400249 (e: MouseEvent, emojiObject: IEmojiData) => {
simon80b7b3b2022-09-28 17:50:10 -0400250 onEmojiSelected(emojiObject.emoji);
simond47ef9e2022-09-28 22:24:28 -0400251 handleClose();
252 },
simon80b7b3b2022-09-28 17:50:10 -0400253 [handleClose, onEmojiSelected]
simond47ef9e2022-09-28 22:24:28 -0400254 );
255
256 const open = Boolean(anchorEl);
257 const id = open ? 'simple-popover' : undefined;
258
259 return (
260 <ClickAwayListener onClickAway={handleClose}>
261 <Box>
simon35378692022-10-02 23:25:57 -0400262 <SquareButton aria-describedby={id} aria-label="select emoji" Icon={EmojiIcon} onClick={(e) => {}} />
263 <Popper id={id} open={open} anchorEl={anchorEl}>
264 <EmojiPicker onEmojiClick={onEmojiClick} disableAutoFocus={true} disableSkinTonePicker={true} native />
simond47ef9e2022-09-28 22:24:28 -0400265 </Popper>
266 </Box>
267 </ClickAwayListener>
268 );
269};