blob: 8ca098e7a74f816f040153419659d09ceeaf5724 [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
simon07b4eb02022-09-29 17:50:26 -040041import authManager from '../AuthManager';
simon416d0792022-11-03 02:46:18 -040042import { useAuthContext } from '../contexts/AuthProvider';
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;
67 if (!account) {
68 throw new Error('Account not defined');
69 }
70
simonfe1de722022-10-02 00:21:43 -040071 const devices: string[][] = [];
72 const accountDevices = account.getDevices();
73 for (const i in accountDevices) devices.push([i, accountDevices[i]]);
Adrien Béraud4e287b92021-04-24 16:15:56 -040074
simond47ef9e2022-09-28 22:24:28 -040075 console.log(devices);
ervinanohf1758a42022-09-14 14:52:51 -040076
77 const isJamiAccount = account.getType() === Account.TYPE_JAMI;
simond47ef9e2022-09-28 22:24:28 -040078 const alias = isJamiAccount ? 'Jami account' : 'SIP account';
ervinanohf1758a42022-09-14 14:52:51 -040079 const moderators = account.getDefaultModerators();
simond47ef9e2022-09-28 22:24:28 -040080 const [defaultModeratorUri, setDefaultModeratorUri] = useState('');
ervinanohf1758a42022-09-14 14:52:51 -040081
82 const [details, setDetails] = useState(account.getDetails());
Adrien Béraud86986032021-04-25 12:04:53 -040083
Adrien Béraud4e287b92021-04-24 16:15:56 -040084 const addModerator = () => {
85 if (defaultModeratorUri) {
simond47ef9e2022-09-28 22:24:28 -040086 authManager.fetch(`/api/accounts/${account.getId()}/defaultModerators/${defaultModeratorUri}`, { method: 'PUT' });
87 setDefaultModeratorUri('');
Adrien Béraud4e287b92021-04-24 16:15:56 -040088 }
ervinanohf1758a42022-09-14 14:52:51 -040089 };
Adrien Béraud4e287b92021-04-24 16:15:56 -040090
simonfe1de722022-10-02 00:21:43 -040091 const removeModerator = (uri: string) =>
simond47ef9e2022-09-28 22:24:28 -040092 authManager.fetch(`/api/accounts/${account.getId()}/defaultModerators/${uri}`, { method: 'DELETE' });
Adrien Béraud4e287b92021-04-24 16:15:56 -040093
simonfe1de722022-10-02 00:21:43 -040094 const handleToggle = (key: keyof AccountDetails, value: boolean) => {
ervinanohf1758a42022-09-14 14:52:51 -040095 console.log(`handleToggle ${key} ${value}`);
simonfe1de722022-10-02 00:21:43 -040096 const newDetails: Partial<AccountDetails> = {};
simond47ef9e2022-09-28 22:24:28 -040097 newDetails[key] = value ? 'true' : 'false';
ervinanohf1758a42022-09-14 14:52:51 -040098 console.log(newDetails);
Adrien Béraud86986032021-04-25 12:04:53 -040099 authManager.fetch(`/api/accounts/${account.getId()}`, {
simond47ef9e2022-09-28 22:24:28 -0400100 method: 'POST',
Adrien Béraud86986032021-04-25 12:04:53 -0400101 headers: {
simond47ef9e2022-09-28 22:24:28 -0400102 Accept: 'application/json',
103 'Content-Type': 'application/json',
Adrien Béraud86986032021-04-25 12:04:53 -0400104 },
ervinanohf1758a42022-09-14 14:52:51 -0400105 body: JSON.stringify(newDetails),
106 });
107 setDetails({ ...account.updateDetails(newDetails) });
108 };
Adrien Béraud86986032021-04-25 12:04:53 -0400109
Adrien Béraud150b4782021-04-21 19:40:59 -0400110 return (
Adrien Béraud6c934962021-06-07 10:13:26 -0400111 <motion.div
ervinanohf1758a42022-09-14 14:52:51 -0400112 initial="initial"
113 animate="enter"
114 exit="exit"
115 variants={{
116 enter: { transition: { staggerChildren: 0.05 } },
117 exit: { transition: { staggerChildren: 0.02 } },
118 }}
119 >
120 <motion.div variants={thumbnailVariants}>
121 <Typography variant="h2" component="h2" gutterBottom>
122 {alias}
123 </Typography>
124 </motion.div>
Adrien Béraud21c53cf2021-04-22 00:04:32 -0400125 <Grid container spacing={3} style={{ marginBottom: 16 }}>
ervinanohf1758a42022-09-14 14:52:51 -0400126 {isJamiAccount && (
127 <Grid item xs={12}>
128 <motion.div variants={thumbnailVariants}>
129 <JamiIdCard account={account} />
130 </motion.div>
131 </Grid>
132 )}
Adrien Béraud150b4782021-04-21 19:40:59 -0400133
134 <Grid item xs={12} sm={6}>
ervinanohf1758a42022-09-14 14:52:51 -0400135 <motion.div variants={thumbnailVariants}>
136 <ConversationsOverviewCard accountId={account.getId()} />
Adrien Béraud6c934962021-06-07 10:13:26 -0400137 </motion.div>
Adrien Béraud150b4782021-04-21 19:40:59 -0400138 </Grid>
139
140 <Grid item xs={12} sm={6}>
ervinanohf1758a42022-09-14 14:52:51 -0400141 <motion.div variants={thumbnailVariants}>
142 <Card>
143 <CardContent>
144 <Typography color="textSecondary" gutterBottom>
145 Current calls
146 </Typography>
147 <Typography gutterBottom variant="h5" component="h2">
148 0
149 </Typography>
150 </CardContent>
151 </Card>
Adrien Béraud6c934962021-06-07 10:13:26 -0400152 </motion.div>
Adrien Béraud150b4782021-04-21 19:40:59 -0400153 </Grid>
Adrien Béraud6c934962021-06-07 10:13:26 -0400154
ervinanohf1758a42022-09-14 14:52:51 -0400155 <Grid item xs={12} sm={6}>
156 <motion.div variants={thumbnailVariants}>
157 <Card>
158 <CardContent>
159 <Typography color="textSecondary" gutterBottom>
160 Appareils associés
161 </Typography>
162 <Typography gutterBottom variant="h5" component="h2">
simon80b7b3b2022-09-28 17:50:10 -0400163 {devices.map((device, i) => (
164 <ListItem key={i}>
ervinanohf1758a42022-09-14 14:52:51 -0400165 <GroupRounded />
simond47ef9e2022-09-28 22:24:28 -0400166 <ListItemText id="switch-list-label-rendezvous" primary={device[1]} secondary={device[0]} />
ervinanohf1758a42022-09-14 14:52:51 -0400167 </ListItem>
168 ))}
169 {/* <ListItemTextsion> */}
170 </Typography>
171 </CardContent>
172 </Card>
173 </motion.div>
174 </Grid>
Adrien Béraud150b4782021-04-21 19:40:59 -0400175 </Grid>
176
ervinanohf1758a42022-09-14 14:52:51 -0400177 <List
178 subheader={
179 <motion.div variants={thumbnailVariants}>
180 <ListSubheader>Settings</ListSubheader>
181 </motion.div>
182 }
183 >
184 <motion.div variants={thumbnailVariants}>
185 <ListItem>
186 <ListItemIcon>
187 <GroupRounded />
188 </ListItemIcon>
simond47ef9e2022-09-28 22:24:28 -0400189 <ListItemText id="switch-list-label-rendezvous" primary="Rendez-Vous point" />
ervinanohf1758a42022-09-14 14:52:51 -0400190 <ListItemSecondaryAction>
191 <Switch
192 edge="end"
simond47ef9e2022-09-28 22:24:28 -0400193 onChange={(e) => handleToggle('Account.rendezVous', e.target.checked)}
194 checked={details['Account.rendezVous'] === 'true'}
ervinanohf1758a42022-09-14 14:52:51 -0400195 inputProps={{
simond47ef9e2022-09-28 22:24:28 -0400196 'aria-labelledby': 'switch-list-label-rendezvous',
ervinanohf1758a42022-09-14 14:52:51 -0400197 }}
198 />
199 </ListItemSecondaryAction>
200 </ListItem>
Adrien Béraud6c934962021-06-07 10:13:26 -0400201 </motion.div>
202 <motion.div variants={thumbnailVariants}>
ervinanohf1758a42022-09-14 14:52:51 -0400203 <ListItem>
204 <ListItemIcon>
205 <PhoneCallbackRounded />
206 </ListItemIcon>
simond47ef9e2022-09-28 22:24:28 -0400207 <ListItemText id="switch-list-label-publicin" primary="Allow connection from unkown peers" />
ervinanohf1758a42022-09-14 14:52:51 -0400208 <ListItemSecondaryAction>
209 <Switch
210 edge="end"
simond47ef9e2022-09-28 22:24:28 -0400211 onChange={(e) => handleToggle('DHT.PublicInCalls', e.target.checked)}
212 checked={details['DHT.PublicInCalls'] === 'true'}
213 inputProps={{ 'aria-labelledby': 'switch-list-label-publicin' }}
ervinanohf1758a42022-09-14 14:52:51 -0400214 />
215 </ListItemSecondaryAction>
216 </ListItem>
Adrien Béraud6c934962021-06-07 10:13:26 -0400217 </motion.div>
218 <motion.div variants={thumbnailVariants}>
ervinanohf1758a42022-09-14 14:52:51 -0400219 <Paper>
220 <Toolbar>
221 <Typography variant="h6">Default moderators</Typography>
222 </Toolbar>
223 <List>
224 <ListItem key="add">
225 <TextField
226 variant="outlined"
227 value={defaultModeratorUri}
228 onChange={(e) => setDefaultModeratorUri(e.target.value)}
229 label="Add new default moderator"
230 placeholder="Enter new moderator name or URI"
231 fullWidth
232 />
233 <ListItemSecondaryAction>
234 <IconButton onClick={addModerator} size="large">
235 <AddCircle />
236 </IconButton>
237 </ListItemSecondaryAction>
238 </ListItem>
239 {!moderators || moderators.length === 0 ? (
240 <ListItem key="placeholder">
241 <ListItemText primary="No default moderator" />
Adrien Béraud21c53cf2021-04-22 00:04:32 -0400242 </ListItem>
ervinanohf1758a42022-09-14 14:52:51 -0400243 ) : (
244 moderators.map((moderator) => (
simonfe1de722022-10-02 00:21:43 -0400245 <ListItem key={moderator.getUri()}>
ervinanohf1758a42022-09-14 14:52:51 -0400246 <ListItemAvatar>
simonfe1de722022-10-02 00:21:43 -0400247 <ConversationAvatar displayName={moderator.getDisplayName()} />
ervinanohf1758a42022-09-14 14:52:51 -0400248 </ListItemAvatar>
249 <ListItemText primary={moderator.getDisplayName()} />
250 <ListItemSecondaryAction>
simon416d0792022-11-03 02:46:18 -0400251 <IconButton onClick={() => removeModerator(moderator.getUri())} size="large">
ervinanohf1758a42022-09-14 14:52:51 -0400252 <DeleteRounded />
253 </IconButton>
254 </ListItemSecondaryAction>
255 </ListItem>
256 ))
257 )}
258 </List>
259 </Paper>
Adrien Béraud6c934962021-06-07 10:13:26 -0400260 </motion.div>
Adrien Béraud150b4782021-04-21 19:40:59 -0400261 </List>
Adrien Béraudab519ff2022-05-03 15:34:48 -0400262 </motion.div>
263 );
Adrien Béraud150b4782021-04-21 19:40:59 -0400264}