blob: f0c5d31ad9309afbbeaf23598f58abca749d26d8 [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 */
simon07b4eb02022-09-29 17:50:26 -040018import { AddCircle, DeleteRounded, GroupRounded, PhoneCallbackRounded } from '@mui/icons-material';
simond47ef9e2022-09-28 22:24:28 -040019import {
simon07b4eb02022-09-29 17:50:26 -040020 Card,
21 CardContent,
22 Grid,
23 IconButton,
simond47ef9e2022-09-28 22:24:28 -040024 List,
25 ListItem,
simon07b4eb02022-09-29 17:50:26 -040026 ListItemAvatar,
simond47ef9e2022-09-28 22:24:28 -040027 ListItemIcon,
28 ListItemSecondaryAction,
29 ListItemText,
30 ListSubheader,
simond47ef9e2022-09-28 22:24:28 -040031 Paper,
simon07b4eb02022-09-29 17:50:26 -040032 Switch,
simond47ef9e2022-09-28 22:24:28 -040033 TextField,
simon07b4eb02022-09-29 17:50:26 -040034 Toolbar,
35 Typography,
simond47ef9e2022-09-28 22:24:28 -040036} from '@mui/material';
simon07b4eb02022-09-29 17:50:26 -040037import { motion } from 'framer-motion';
simon416d0792022-11-03 02:46:18 -040038import { Account, AccountDetails } from 'jami-web-common';
simon07b4eb02022-09-29 17:50:26 -040039import { useState } from 'react';
Adrien Béraud6ecaa402021-04-06 17:37:25 -040040
simon416d0792022-11-03 02:46:18 -040041import { useAuthContext } from '../contexts/AuthProvider';
simon5da8ca62022-11-09 15:21:25 -050042import { apiUrl } from '../utils/constants';
simond47ef9e2022-09-28 22:24:28 -040043import ConversationAvatar from './ConversationAvatar';
44import ConversationsOverviewCard from './ConversationsOverviewCard';
simon07b4eb02022-09-29 17:50:26 -040045import JamiIdCard from './JamiIdCard';
Adrien Béraud4e287b92021-04-24 16:15:56 -040046
simond47ef9e2022-09-28 22:24:28 -040047const transition = { duration: 0.3, ease: [0.43, 0.13, 0.23, 0.96] };
Adrien Béraud6c934962021-06-07 10:13:26 -040048
49const thumbnailVariants = {
50 initial: { scale: 0.9, opacity: 0 },
51 enter: { scale: 1, opacity: 1, transition },
52 exit: {
53 scale: 0.5,
54 opacity: 0,
simonfe1de722022-10-02 00:21:43 -040055 transition: { ...transition, duration: 1.5 },
simond47ef9e2022-09-28 22:24:28 -040056 },
57};
Adrien Béraud6c934962021-06-07 10:13:26 -040058
simonfe1de722022-10-02 00:21:43 -040059type AccountPreferencesProps = {
simon416d0792022-11-03 02:46:18 -040060 // TODO: Remove account prop after migration to new server
61 account?: Account;
simonfe1de722022-10-02 00:21:43 -040062};
63
simon416d0792022-11-03 02:46:18 -040064export default function AccountPreferences({ account: _account }: AccountPreferencesProps) {
65 const authContext = useAuthContext(true);
66 const account = _account ?? authContext?.account;
simon5da8ca62022-11-09 15:21:25 -050067 const token = authContext?.token;
68 if (!account || !token) {
simon416d0792022-11-03 02:46:18 -040069 throw new Error('Account not defined');
70 }
71
simonfe1de722022-10-02 00:21:43 -040072 const devices: string[][] = [];
73 const accountDevices = account.getDevices();
74 for (const i in accountDevices) devices.push([i, accountDevices[i]]);
Adrien Béraud4e287b92021-04-24 16:15:56 -040075
simond47ef9e2022-09-28 22:24:28 -040076 console.log(devices);
ervinanohf1758a42022-09-14 14:52:51 -040077
78 const isJamiAccount = account.getType() === Account.TYPE_JAMI;
simond47ef9e2022-09-28 22:24:28 -040079 const alias = isJamiAccount ? 'Jami account' : 'SIP account';
ervinanohf1758a42022-09-14 14:52:51 -040080 const moderators = account.getDefaultModerators();
simond47ef9e2022-09-28 22:24:28 -040081 const [defaultModeratorUri, setDefaultModeratorUri] = useState('');
ervinanohf1758a42022-09-14 14:52:51 -040082
83 const [details, setDetails] = useState(account.getDetails());
Adrien Béraud86986032021-04-25 12:04:53 -040084
Adrien Béraud4e287b92021-04-24 16:15:56 -040085 const addModerator = () => {
86 if (defaultModeratorUri) {
simon5da8ca62022-11-09 15:21:25 -050087 fetch(new URL(`/default-moderators/${defaultModeratorUri}`, apiUrl), {
88 headers: {
89 Authorization: `Bearer ${token}`,
90 },
91 method: 'PUT',
92 });
simond47ef9e2022-09-28 22:24:28 -040093 setDefaultModeratorUri('');
Adrien Béraud4e287b92021-04-24 16:15:56 -040094 }
ervinanohf1758a42022-09-14 14:52:51 -040095 };
Adrien Béraud4e287b92021-04-24 16:15:56 -040096
simonfe1de722022-10-02 00:21:43 -040097 const removeModerator = (uri: string) =>
simon5da8ca62022-11-09 15:21:25 -050098 fetch(new URL(`/default-moderators/${uri}`, apiUrl), {
99 headers: {
100 Authorization: `Bearer ${token}`,
101 },
102 method: 'DELETE',
103 });
Adrien Béraud4e287b92021-04-24 16:15:56 -0400104
simonfe1de722022-10-02 00:21:43 -0400105 const handleToggle = (key: keyof AccountDetails, value: boolean) => {
ervinanohf1758a42022-09-14 14:52:51 -0400106 console.log(`handleToggle ${key} ${value}`);
simonfe1de722022-10-02 00:21:43 -0400107 const newDetails: Partial<AccountDetails> = {};
simond47ef9e2022-09-28 22:24:28 -0400108 newDetails[key] = value ? 'true' : 'false';
ervinanohf1758a42022-09-14 14:52:51 -0400109 console.log(newDetails);
simon5da8ca62022-11-09 15:21:25 -0500110 fetch(new URL('/account', apiUrl), {
111 method: 'PATCH',
Adrien Béraud86986032021-04-25 12:04:53 -0400112 headers: {
simond47ef9e2022-09-28 22:24:28 -0400113 Accept: 'application/json',
simon5da8ca62022-11-09 15:21:25 -0500114 Authorization: `Bearer ${token}`,
simond47ef9e2022-09-28 22:24:28 -0400115 'Content-Type': 'application/json',
Adrien Béraud86986032021-04-25 12:04:53 -0400116 },
ervinanohf1758a42022-09-14 14:52:51 -0400117 body: JSON.stringify(newDetails),
118 });
119 setDetails({ ...account.updateDetails(newDetails) });
120 };
Adrien Béraud86986032021-04-25 12:04:53 -0400121
Adrien Béraud150b4782021-04-21 19:40:59 -0400122 return (
Adrien Béraud6c934962021-06-07 10:13:26 -0400123 <motion.div
ervinanohf1758a42022-09-14 14:52:51 -0400124 initial="initial"
125 animate="enter"
126 exit="exit"
127 variants={{
128 enter: { transition: { staggerChildren: 0.05 } },
129 exit: { transition: { staggerChildren: 0.02 } },
130 }}
131 >
132 <motion.div variants={thumbnailVariants}>
133 <Typography variant="h2" component="h2" gutterBottom>
134 {alias}
135 </Typography>
136 </motion.div>
Adrien Béraud21c53cf2021-04-22 00:04:32 -0400137 <Grid container spacing={3} style={{ marginBottom: 16 }}>
ervinanohf1758a42022-09-14 14:52:51 -0400138 {isJamiAccount && (
139 <Grid item xs={12}>
140 <motion.div variants={thumbnailVariants}>
141 <JamiIdCard account={account} />
142 </motion.div>
143 </Grid>
144 )}
Adrien Béraud150b4782021-04-21 19:40:59 -0400145
146 <Grid item xs={12} sm={6}>
ervinanohf1758a42022-09-14 14:52:51 -0400147 <motion.div variants={thumbnailVariants}>
simon5da8ca62022-11-09 15:21:25 -0500148 <ConversationsOverviewCard />
Adrien Béraud6c934962021-06-07 10:13:26 -0400149 </motion.div>
Adrien Béraud150b4782021-04-21 19:40:59 -0400150 </Grid>
151
152 <Grid item xs={12} sm={6}>
ervinanohf1758a42022-09-14 14:52:51 -0400153 <motion.div variants={thumbnailVariants}>
154 <Card>
155 <CardContent>
156 <Typography color="textSecondary" gutterBottom>
157 Current calls
158 </Typography>
159 <Typography gutterBottom variant="h5" component="h2">
160 0
161 </Typography>
162 </CardContent>
163 </Card>
Adrien Béraud6c934962021-06-07 10:13:26 -0400164 </motion.div>
Adrien Béraud150b4782021-04-21 19:40:59 -0400165 </Grid>
Adrien Béraud6c934962021-06-07 10:13:26 -0400166
ervinanohf1758a42022-09-14 14:52:51 -0400167 <Grid item xs={12} sm={6}>
168 <motion.div variants={thumbnailVariants}>
169 <Card>
170 <CardContent>
171 <Typography color="textSecondary" gutterBottom>
172 Appareils associés
173 </Typography>
174 <Typography gutterBottom variant="h5" component="h2">
simon80b7b3b2022-09-28 17:50:10 -0400175 {devices.map((device, i) => (
176 <ListItem key={i}>
ervinanohf1758a42022-09-14 14:52:51 -0400177 <GroupRounded />
simond47ef9e2022-09-28 22:24:28 -0400178 <ListItemText id="switch-list-label-rendezvous" primary={device[1]} secondary={device[0]} />
ervinanohf1758a42022-09-14 14:52:51 -0400179 </ListItem>
180 ))}
181 {/* <ListItemTextsion> */}
182 </Typography>
183 </CardContent>
184 </Card>
185 </motion.div>
186 </Grid>
Adrien Béraud150b4782021-04-21 19:40:59 -0400187 </Grid>
188
ervinanohf1758a42022-09-14 14:52:51 -0400189 <List
190 subheader={
191 <motion.div variants={thumbnailVariants}>
192 <ListSubheader>Settings</ListSubheader>
193 </motion.div>
194 }
195 >
196 <motion.div variants={thumbnailVariants}>
197 <ListItem>
198 <ListItemIcon>
199 <GroupRounded />
200 </ListItemIcon>
simond47ef9e2022-09-28 22:24:28 -0400201 <ListItemText id="switch-list-label-rendezvous" primary="Rendez-Vous point" />
ervinanohf1758a42022-09-14 14:52:51 -0400202 <ListItemSecondaryAction>
203 <Switch
204 edge="end"
simond47ef9e2022-09-28 22:24:28 -0400205 onChange={(e) => handleToggle('Account.rendezVous', e.target.checked)}
206 checked={details['Account.rendezVous'] === 'true'}
ervinanohf1758a42022-09-14 14:52:51 -0400207 inputProps={{
simond47ef9e2022-09-28 22:24:28 -0400208 'aria-labelledby': 'switch-list-label-rendezvous',
ervinanohf1758a42022-09-14 14:52:51 -0400209 }}
210 />
211 </ListItemSecondaryAction>
212 </ListItem>
Adrien Béraud6c934962021-06-07 10:13:26 -0400213 </motion.div>
214 <motion.div variants={thumbnailVariants}>
ervinanohf1758a42022-09-14 14:52:51 -0400215 <ListItem>
216 <ListItemIcon>
217 <PhoneCallbackRounded />
218 </ListItemIcon>
simond47ef9e2022-09-28 22:24:28 -0400219 <ListItemText id="switch-list-label-publicin" primary="Allow connection from unkown peers" />
ervinanohf1758a42022-09-14 14:52:51 -0400220 <ListItemSecondaryAction>
221 <Switch
222 edge="end"
simond47ef9e2022-09-28 22:24:28 -0400223 onChange={(e) => handleToggle('DHT.PublicInCalls', e.target.checked)}
224 checked={details['DHT.PublicInCalls'] === 'true'}
225 inputProps={{ 'aria-labelledby': 'switch-list-label-publicin' }}
ervinanohf1758a42022-09-14 14:52:51 -0400226 />
227 </ListItemSecondaryAction>
228 </ListItem>
Adrien Béraud6c934962021-06-07 10:13:26 -0400229 </motion.div>
230 <motion.div variants={thumbnailVariants}>
ervinanohf1758a42022-09-14 14:52:51 -0400231 <Paper>
232 <Toolbar>
233 <Typography variant="h6">Default moderators</Typography>
234 </Toolbar>
235 <List>
236 <ListItem key="add">
237 <TextField
238 variant="outlined"
239 value={defaultModeratorUri}
240 onChange={(e) => setDefaultModeratorUri(e.target.value)}
241 label="Add new default moderator"
242 placeholder="Enter new moderator name or URI"
243 fullWidth
244 />
245 <ListItemSecondaryAction>
246 <IconButton onClick={addModerator} size="large">
247 <AddCircle />
248 </IconButton>
249 </ListItemSecondaryAction>
250 </ListItem>
251 {!moderators || moderators.length === 0 ? (
252 <ListItem key="placeholder">
253 <ListItemText primary="No default moderator" />
Adrien Béraud21c53cf2021-04-22 00:04:32 -0400254 </ListItem>
ervinanohf1758a42022-09-14 14:52:51 -0400255 ) : (
256 moderators.map((moderator) => (
simonfe1de722022-10-02 00:21:43 -0400257 <ListItem key={moderator.getUri()}>
ervinanohf1758a42022-09-14 14:52:51 -0400258 <ListItemAvatar>
simonfe1de722022-10-02 00:21:43 -0400259 <ConversationAvatar displayName={moderator.getDisplayName()} />
ervinanohf1758a42022-09-14 14:52:51 -0400260 </ListItemAvatar>
261 <ListItemText primary={moderator.getDisplayName()} />
262 <ListItemSecondaryAction>
simon416d0792022-11-03 02:46:18 -0400263 <IconButton onClick={() => removeModerator(moderator.getUri())} size="large">
ervinanohf1758a42022-09-14 14:52:51 -0400264 <DeleteRounded />
265 </IconButton>
266 </ListItemSecondaryAction>
267 </ListItem>
268 ))
269 )}
270 </List>
271 </Paper>
Adrien Béraud6c934962021-06-07 10:13:26 -0400272 </motion.div>
Adrien Béraud150b4782021-04-21 19:40:59 -0400273 </List>
Adrien Béraudab519ff2022-05-03 15:34:48 -0400274 </motion.div>
275 );
Adrien Béraud150b4782021-04-21 19:40:59 -0400276}