add account overview, cleanup

Change-Id: I176af7a7688f38cb30eb7d65fa3e00e55f10da6f
diff --git a/JamiDaemon.js b/JamiDaemon.js
index 841b979..f60ac50 100755
--- a/JamiDaemon.js
+++ b/JamiDaemon.js
@@ -109,7 +109,8 @@
                 }
                 if (state == 0) {
                     const contact = account.getContactFromCache(address)
-                    contact.setRegisteredName(name)
+                    if (!contact.isRegisteredNameResolved())
+                        contact.setRegisteredName(name)
                 }
                 let index = account.lookups.length - 1
                 while (index >= 0) {
@@ -198,7 +199,24 @@
             )
             JamiDaemon.vectToJs(this.dring.getConversations(accountId)).forEach(conversationId => {
                 const members = JamiDaemon.vectMapToJs(this.dring.getConversationMembers(accountId, conversationId))
-                members.forEach(member => member.contact = account.getContactFromCache(member.uri))
+                members.forEach(member => {
+                    member.contact = account.getContactFromCache(member.uri)
+                    if (!member.contact.isRegisteredNameResolved()) {
+                        if (!member.uri) return
+                        console.log(`lookupAddress ${accountId} ${member.uri}`)
+                        member.contact.setRegisteredName(new Promise((resolve, reject) =>
+                            account.lookups.push({address: member.uri, resolve, reject})
+                        ).then(result => {
+                            if (result.state == 0)
+                                return result.name
+                            else if (result.state == 1)
+                                return undefined
+                            else
+                                return null
+                        }))
+                        this.dring.lookupAddress(accountId, "", member.uri)
+                    }
+                })
                 const conversation = new Conversation(conversationId, accountId, members)
                 account.addConversation(conversation)
             })
@@ -287,9 +305,19 @@
         return details
     }
 
-    //getContactDetails
+    getDefaultModerators(accountId) {
+        const account = this.getAccount(accountId)
+        if (!account) {
+            console.log(`Unknown account ${accountId}`)
+            return {}
+        }
+        return JamiDaemon.vectToJs(this.dring.getDefaultModerators(accountId))
+            .map(contactId => account.getContactFromCache(contctId))
+    }
 
-// private
+    setDefaultModerators(accountId, moderators) {
+
+    }
 
     boolToStr(bool) {
         return bool ? "true" : "false"
diff --git a/client/package.json b/client/package.json
index 6cd7d4d..191dd7f 100644
--- a/client/package.json
+++ b/client/package.json
@@ -27,6 +27,7 @@
     "@pmmmwh/react-refresh-webpack-plugin": "^0.5.0-beta.3",
     "babel-loader": "^8.2.2",
     "css-loader": "^5.2.0",
+    "copy-webpack-plugin": "^8.1.1",
     "html-webpack-plugin": "^5.3.1",
     "react-refresh": "^0.10.0",
     "sass": "^1.32.8",
diff --git a/client/src/App.js b/client/src/App.js
index cc1b5bf..bce1842 100644
--- a/client/src/App.js
+++ b/client/src/App.js
@@ -16,6 +16,7 @@
 import AccountSelection from "./pages/accountSelection.jsx"
 import ServerSetup from "./pages/serverSetup.jsx"
 import NotFoundPage from "./pages/404.jsx"
+import LoadingPage from './components/loading'
 
 const App = (props) => {
     const history = useHistory()
@@ -36,7 +37,7 @@
     console.log(location)
 
     if (!state.loaded) {
-      return <Container><CircularProgress /></Container>
+      return <LoadingPage />
     } else if (!state.auth.setupComplete) {
       return <Switch>
           <Route path="/setup" component={ServerSetup} />
@@ -44,7 +45,6 @@
         </Switch>
     }
     return <React.Fragment>
-      <CssBaseline />
         <Switch>
           <Route exact path="/"><Redirect to="/account" /></Route>
           <Route path="/account/:accountId/settings" component={AccountSettings} />
diff --git a/client/src/AuthManager.js b/client/src/AuthManager.js
index 4f504db..4b7b6b4 100644
--- a/client/src/AuthManager.js
+++ b/client/src/AuthManager.js
@@ -140,7 +140,7 @@
     }
 
     fetch(url, init) {
-        console.log(`get ${url}`)
+        console.log(`fetch ${url}`)
         if (!this.state.authenticated) {
             return new Promise((resolve, reject) => this.tasks.push({url, init, resolve, reject}))
         }
diff --git a/client/src/components/AccountList.js b/client/src/components/AccountList.js
index 38f1291..594c979 100644
--- a/client/src/components/AccountList.js
+++ b/client/src/components/AccountList.js
@@ -1,6 +1,6 @@
 import React from 'react'
-import { Avatar, List, ListItem, ListItemAvatar, ListItemText } from '@material-ui/core'
-import { PersonRounded } from '@material-ui/icons';
+import { List, ListItem, ListItemAvatar, ListItemText } from '@material-ui/core'
+import ConversationAvatar from './ConversationAvatar'
 
 export default function AccountList(props) {
   return <List>
@@ -9,7 +9,7 @@
         const displayName = account.getDisplayNameNoFallback()
         return <ListItem button key={account.getId()} onClick={() => props.onClick(account)}>
           <ListItemAvatar>
-            <Avatar>{displayName ? displayName[0].toUpperCase() : <PersonRounded />}</Avatar>
+            <ConversationAvatar displayName={displayName} />
           </ListItemAvatar>
           <ListItemText primary={account.getDisplayName()} secondary={account.getDisplayUri()} />
         </ListItem>
diff --git a/client/src/components/AccountPreferences.js b/client/src/components/AccountPreferences.js
index 5b6ae28..5629ef0 100644
--- a/client/src/components/AccountPreferences.js
+++ b/client/src/components/AccountPreferences.js
@@ -1,63 +1,142 @@
 import React from 'react';
-
-import Typography from '@material-ui/core/Typography';
+import { makeStyles } from '@material-ui/core/styles';
+import { List, ListItem, ListItemIcon, ListItemSecondaryAction, ListItemText, ListSubheader, Switch, Typography, Grid, Paper, CardContent, Card } from '@material-ui/core';
+import { PhoneCallbackRounded, GroupRounded } from '@material-ui/icons';
 
 import JamiIdCard from './JamiIdCard';
-import List from '@material-ui/core/List';
-import ListItem from '@material-ui/core/ListItem';
-import ListItemIcon from '@material-ui/core/ListItemIcon';
-import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
-import ListItemText from '@material-ui/core/ListItemText';
-import ListSubheader from '@material-ui/core/ListSubheader';
-import Switch from '@material-ui/core/Switch';
-import PhoneCallbackIcon from '@material-ui/icons/PhoneCallback';
-import GroupRoundedIcon from '@material-ui/icons/GroupRounded';
 import Account from '../../../model/Account';
+import ConversationsOverviewCard from './ConversationsOverviewCard';
 
-class AccountPreferences extends React.Component {
+const useStyles = makeStyles({
+  root: {
+    minWidth: 275,
+  },
+  bullet: {
+    display: 'inline-block',
+    margin: '0 2px',
+    transform: 'scale(0.8)',
+  },
+  title: {
+    fontSize: 14,
+  },
+  pos: {
+    marginBottom: 12,
+  },
+});
 
-  render() {
-    const account = this.props.account
-    const isJamiAccount = account.getType() === Account.TYPE_JAMI
-    return (
-      <React.Fragment>
-        <Typography variant="h2" component="h2">{isJamiAccount ? "Jami account" : "SIP account"}</Typography>
+const columns = [
+  { id: 'name', label: 'Name', minWidth: 170 },
+  { id: 'code', label: 'ISO\u00a0Code', minWidth: 100 },
+  {
+    id: 'population',
+    label: 'Population',
+    minWidth: 170,
+    align: 'right',
+    format: (value) => value.toLocaleString('en-US'),
+  },
+  {
+    id: 'size',
+    label: 'Size\u00a0(km\u00b2)',
+    minWidth: 170,
+    align: 'right',
+    format: (value) => value.toLocaleString('en-US'),
+  },
+  {
+    id: 'density',
+    label: 'Density',
+    minWidth: 170,
+    align: 'right',
+    format: (value) => value.toFixed(2),
+  },
+];
 
-        {isJamiAccount &&
-          <JamiIdCard account={account} />}
-
-        <List subheader={<ListSubheader>Settings</ListSubheader>}>
-          <ListItem>
-            <ListItemIcon>
-              <GroupRoundedIcon />
-            </ListItemIcon>
-            <ListItemText id="switch-list-label-rendezvous" primary="Rendez-Vous point" />
-            <ListItemSecondaryAction>
-              <Switch
-                edge="end"
-                /*onChange={handleToggle('wifi')}*/
-                checked={account.isRendezVous()}
-                inputProps={{ 'aria-labelledby': 'switch-list-label-wifi' }}
-              />
-            </ListItemSecondaryAction>
-          </ListItem>
-          <ListItem>
-            <ListItemIcon>
-              <PhoneCallbackIcon />
-            </ListItemIcon>
-            <ListItemText id="switch-list-label-publicin" primary="Allow connection from unkown peers" />
-            <ListItemSecondaryAction>
-              <Switch
-                edge="end"
-                /*onChange={handleToggle('bluetooth')}*/
-                checked={account.isPublicIn()}
-                inputProps={{ 'aria-labelledby': 'switch-list-label-bluetooth' }}
-              />
-            </ListItemSecondaryAction>
-          </ListItem>
-        </List>
-      </React.Fragment>)
-  }
+function createData(name, code, population, size) {
+  const density = population / size;
+  return { name, code, population, size, density };
 }
 
-export default AccountPreferences;
\ No newline at end of file
+const rows = [
+  createData('India', 'IN', 1324171354, 3287263),
+  createData('China', 'CN', 1403500365, 9596961),
+  createData('Italy', 'IT', 60483973, 301340),
+  createData('United States', 'US', 327167434, 9833520),
+  createData('Canada', 'CA', 37602103, 9984670),
+  createData('Australia', 'AU', 25475400, 7692024),
+  createData('Germany', 'DE', 83019200, 357578),
+  createData('Ireland', 'IE', 4857000, 70273),
+  createData('Mexico', 'MX', 126577691, 1972550),
+  createData('Japan', 'JP', 126317000, 377973),
+  createData('France', 'FR', 67022000, 640679),
+  createData('United Kingdom', 'GB', 67545757, 242495),
+  createData('Russia', 'RU', 146793744, 17098246),
+  createData('Nigeria', 'NG', 200962417, 923768),
+  createData('Brazil', 'BR', 210147125, 8515767),
+];
+
+export default function AccountPreferences(props) {
+  const classes = useStyles()
+  const account = props.account
+  const isJamiAccount = account.getType() === Account.TYPE_JAMI
+  const alias = isJamiAccount ? "Jami account" : "SIP account"
+  return (
+    <React.Fragment>
+      <Typography variant="h2" component="h2" gutterBottom>{alias}</Typography>
+      <Grid container spacing={3} style={{marginBottom: 16}}>
+        {isJamiAccount &&
+          <Grid item xs={12}><JamiIdCard account={account} /></Grid>}
+
+        <Grid item xs={12} sm={6}>
+          <ConversationsOverviewCard accountId={account.getId()} />
+        </Grid>
+
+        <Grid item xs={12} sm={6}>
+          <Card>
+            <CardContent>
+              <Typography className={classes.title} color="textSecondary" gutterBottom>
+                Current calls
+              </Typography>
+              <Typography gutterBottom variant="h5" component="h2">
+                0
+              </Typography>
+            </CardContent>
+          </Card>
+        </Grid>
+      </Grid>
+
+      <List subheader={<ListSubheader>Settings</ListSubheader>}>
+        <ListItem>
+          <ListItemIcon>
+            <GroupRounded />
+          </ListItemIcon>
+          <ListItemText id="switch-list-label-rendezvous" primary="Rendez-Vous point" />
+          <ListItemSecondaryAction>
+            <Switch
+              edge="end"
+              /*onChange={handleToggle('wifi')}*/
+              checked={account.isRendezVous()}
+              inputProps={{ 'aria-labelledby': 'switch-list-label-wifi' }}
+            />
+          </ListItemSecondaryAction>
+        </ListItem>
+        <ListItem>
+          <ListItemIcon>
+            <PhoneCallbackRounded />
+          </ListItemIcon>
+          <ListItemText id="switch-list-label-publicin" primary="Allow connection from unkown peers" />
+          <ListItemSecondaryAction>
+            <Switch
+              edge="end"
+              /*onChange={handleToggle('bluetooth')}*/
+              checked={account.isPublicIn()}
+              inputProps={{ 'aria-labelledby': 'switch-list-label-bluetooth' }}
+            />
+          </ListItemSecondaryAction>
+        </ListItem>
+      </List>
+
+
+
+
+
+    </React.Fragment>)
+}
diff --git a/client/src/components/ConversationAvatar.js b/client/src/components/ConversationAvatar.js
new file mode 100644
index 0000000..b9160a1
--- /dev/null
+++ b/client/src/components/ConversationAvatar.js
@@ -0,0 +1,7 @@
+import React from 'react';
+import { Avatar } from '@material-ui/core';
+import { PersonRounded } from '@material-ui/icons'
+
+export default function ConversationAvatar(props) {
+  return <Avatar>{props.displayName ? props.displayName[0].toUpperCase() : <PersonRounded />}</Avatar>
+}
diff --git a/client/src/components/ConversationList.js b/client/src/components/ConversationList.js
index b28a6d6..9fa4650 100644
--- a/client/src/components/ConversationList.js
+++ b/client/src/components/ConversationList.js
@@ -3,7 +3,7 @@
 import ConversationListItem from './ConversationListItem'
 import ListSubheader from '@material-ui/core/ListSubheader';
 import Conversation from '../../../model/Conversation';
-import GroupRoundedIcon from '@material-ui/icons/GroupRounded';
+import { GroupRounded as GroupIcon } from '@material-ui/icons';
 import Typography from '@material-ui/core/Typography';
 
 export default function ConversationList(props) {
@@ -21,7 +21,7 @@
                 )}
                 {props.conversations.length === 0 && (
                     <div className="list-placeholder">
-                        <GroupRoundedIcon color="disabled" fontSize="large"  />
+                        <GroupIcon color="disabled" fontSize="large"  />
                         <Typography className="subtitle" variant="subtitle2">No conversation yet</Typography>
                     </div>
                 )}
diff --git a/client/src/components/ConversationListItem.js b/client/src/components/ConversationListItem.js
index a769168..a0295d5 100644
--- a/client/src/components/ConversationListItem.js
+++ b/client/src/components/ConversationListItem.js
@@ -1,15 +1,14 @@
-import { Avatar, ListItem, ListItemAvatar, ListItemText } from '@material-ui/core'
+import { ListItem, ListItemAvatar, ListItemText } from '@material-ui/core'
 import React from 'react'
 import Conversation from '../../../model/Conversation'
 import { useHistory, useParams } from "react-router-dom"
-import { PersonRounded } from '@material-ui/icons'
+import ConversationAvatar from './ConversationAvatar'
 
 export default function ConversationListItem(props) {
     const { conversationId, contactId } = useParams()
     const conversation = props.conversation
     const pathId = conversationId || contactId
     const isSelected = conversation.getDisplayUri() === pathId
-    const displayName = conversation.getDisplayName()
     const history = useHistory()
 
     const uri = conversation.getId() ? `conversation/${conversation.getId()}` : `addContact/${conversation.getFirstMember().contact.getUri()}`
@@ -20,10 +19,8 @@
                 alignItems="flex-start"
                 selected={isSelected}
                 style={{overflow:'hidden'}}
-                onClick={() => history.push(`/account/${conversation.getAccountId()}/${uri}`)}>
-                <ListItemAvatar>
-                    <Avatar>{displayName ? displayName[0].toUpperCase() : <PersonRounded />}</Avatar>
-                </ListItemAvatar>
+                onClick={() => history.replace(`/account/${conversation.getAccountId()}/${uri}`)}>
+                <ListItemAvatar><ConversationAvatar displayName={conversation.getDisplayNameNoFallback()} /></ListItemAvatar>
                 <ListItemText
                     style={{overflow:'hidden', textOverflow:'ellipsis'}}
                     primary={conversation.getDisplayName()} secondary={conversation.getDisplayUri()} />
diff --git a/client/src/components/ConversationView.js b/client/src/components/ConversationView.js
index 678aafe..e818ba0 100644
--- a/client/src/components/ConversationView.js
+++ b/client/src/components/ConversationView.js
@@ -4,6 +4,7 @@
 import SendMessageForm from './SendMessageForm';
 import authManager from '../AuthManager'
 import Conversation from '../../../model/Conversation';
+import LoadingPage from './loading';
 
 class ConversationView extends React.Component {
     constructor(props) {
@@ -69,7 +70,7 @@
 
     render() {
         if (this.state.loaded === false) {
-            return <CircularProgress />
+            return <LoadingPage />
         } else if (this.state.error === true) {
             return <div>Error loding {this.props.conversationId}</div>
         } else {
diff --git a/client/src/components/ConversationsOverviewCard.js b/client/src/components/ConversationsOverviewCard.js
new file mode 100644
index 0000000..01b2d7b
--- /dev/null
+++ b/client/src/components/ConversationsOverviewCard.js
@@ -0,0 +1,47 @@
+import React, { useEffect, useState } from 'react';
+import { Box, Card, CardActionArea, CardContent, CircularProgress, Typography } from '@material-ui/core';
+import { makeStyles } from '@material-ui/core/styles';
+import { useHistory, useParams } from 'react-router';
+import authManager from '../AuthManager'
+import Conversation from '../../../model/Conversation';
+
+const useStyles = makeStyles({
+  title: {
+    fontSize: 14,
+  }, pos: {
+    fontSize: 14,
+  }
+});
+
+export default function ConversationsOverviewCard(props) {
+  const classes = useStyles()
+  const history = useHistory()
+  const accountId = props.accountId || useParams().accountId
+  const [state, setState] = useState({ loaded: false })
+
+  useEffect(() => {
+    const controller = new AbortController()
+    authManager.fetch(`/api/accounts/${accountId}/conversations`, { signal: controller.signal })
+      .then(res => res.json())
+      .then(result => {
+        console.log(result)
+        setState({ loaded: true, conversations: Object.values(result).map(c => Conversation.from(accountId, c)) })
+      })
+    return () => controller.abort()
+  }, [])
+
+  return (
+    <Card onClick={() => history.push(`/account/${accountId}`)} >
+      <CardActionArea>
+        <CardContent>
+          <Typography className={classes.title} color="textSecondary" gutterBottom>
+            Conversations
+          </Typography>
+          <Typography gutterBottom variant="h5" component="h2">
+            {state.loaded ? state.conversations.length : <CircularProgress size={24} />}
+          </Typography>
+        </CardContent>
+      </CardActionArea>
+    </Card>
+  )
+}
diff --git a/client/src/components/Header.js b/client/src/components/Header.js
index c0408a1..c621b56 100644
--- a/client/src/components/Header.js
+++ b/client/src/components/Header.js
@@ -1,45 +1,33 @@
-import React from 'react'
-import Button from '@material-ui/core/Button';
-import Menu from '@material-ui/core/Menu';
-import MenuItem from '@material-ui/core/MenuItem';
-//import { useHistory } from "react-router-dom";
+import React, { useState } from 'react'
+import { Box, Button, Menu, MenuItem } from '@material-ui/core'
+import { useHistory, useParams } from "react-router-dom"
 import authManager from '../AuthManager'
 
 export default function Header() {
-    //const history = useHistory();
+  const history = useHistory()
+  const [anchorEl, setAnchorEl] = useState(null)
+  const handleClick = (event) => setAnchorEl(event.currentTarget)
+  const handleClose = () => setAnchorEl(null)
+  const params = useParams()
 
-    const [anchorEl, setAnchorEl] = React.useState(null);
+  const goToAccountSelection = () => history.push(`/account`)
+  const goToAccountSettings = () => history.push(`/account/${params.accountId}/settings`)
 
-    const handleClick = (event) => {
-        setAnchorEl(event.currentTarget);
-    };
-
-    const handleClose = () => {
-        setAnchorEl(null);
-    };
-
-    const disconnect = () => {
-        authManager.disconnect()
-        //let path = `/`;
-        //history.push(path);
-    }
-
-    return (
-        <div>
-            <Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
-                Menu
-            </Button>
-            <Menu
-                id="simple-menu"
-                anchorEl={anchorEl}
-
-                open={Boolean(anchorEl)}
-                onClose={handleClose}
-            >
-                <MenuItem onClick={handleClose}>Profile</MenuItem>
-                <MenuItem onClick={handleClose}>Mon compte</MenuItem>
-                <MenuItem onClick={disconnect}>Déconnexion</MenuItem>
-            </Menu>
-        </div>
-    );
+  return (
+    <Box>
+      <Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
+        Menu
+      </Button>
+      <Menu
+        id="simple-menu"
+        anchorEl={anchorEl}
+        open={Boolean(anchorEl)}
+        onClose={handleClose}
+      >
+        <MenuItem onClick={goToAccountSelection}>Change account</MenuItem>
+        {params.accountId && <MenuItem onClick={goToAccountSettings}>Account settings</MenuItem>}
+        <MenuItem onClick={() => authManager.disconnect()}>Log out</MenuItem>
+      </Menu>
+      </Box>
+  )
 }
\ No newline at end of file
diff --git a/client/src/components/JamiIdCard.js b/client/src/components/JamiIdCard.js
index eb31a26..1b75bc5 100644
--- a/client/src/components/JamiIdCard.js
+++ b/client/src/components/JamiIdCard.js
@@ -1,25 +1,35 @@
 import React from 'react';
+import { Box, Card, CardContent, Typography } from '@material-ui/core';
+import { makeStyles } from '@material-ui/core/styles';
 
-import Card from '@material-ui/core/Card';
-import CardContent from '@material-ui/core/CardContent';
-import Typography from '@material-ui/core/Typography';
+const useStyles = makeStyles({
+  title: {
+    fontSize: 14,
+  }, pos: {
+    fontSize: 14,
 
-class JamiIdCard extends React.Component {
-  render() {
-    const account = this.props.account
-    const registeredName = account.getRegisteredName()
-    return (
-        <Card style={{marginBottom:16}}>
-          <CardContent>
-            <Typography variant="h6">Jami key ID</Typography>
-            <Typography variant="body1">{account.getUri()}</Typography>
-            {registeredName && <div>
-                <Typography variant="h6">Jami username</Typography>
-                <Typography variant="body1">{registeredName}</Typography></div>
-            }
-          </CardContent>
-        </Card>)
   }
-}
+});
 
-export default JamiIdCard;
\ No newline at end of file
+export default function JamiIdCard(props) {
+  const classes = useStyles()
+  const account = props.account
+  const registeredName = account.getRegisteredName()
+  return <Card style={{marginBottom:16}}>
+      <CardContent>
+        <Box>
+        <Typography className={classes.title} color="textSecondary">
+          Jami ID
+        </Typography>
+          <Typography variant="h5" component="h2" gutterBottom noWrap>{account.getUri()}</Typography>
+        </Box>
+        {registeredName && <Box>
+          <Typography className={classes.title} color="textSecondary" >
+          Jami username
+        </Typography>
+            <Typography variant="h5" component="h2" noWrap>{registeredName}</Typography>
+          </Box>
+        }
+      </CardContent>
+    </Card>
+}
diff --git a/client/src/components/MessageList.js b/client/src/components/MessageList.js
index 4841ea1..1673a38 100644
--- a/client/src/components/MessageList.js
+++ b/client/src/components/MessageList.js
@@ -1,26 +1,26 @@
 import Message from './Message'
 import React from 'react'
-import { Avatar, Box, Divider, Typography } from '@material-ui/core'
-import { PersonRounded } from '@material-ui/icons'
+import { Box, Divider, Typography } from '@material-ui/core'
+import ConversationAvatar from './ConversationAvatar'
 
 export default function MessageList(props) {
-    const displayName = props.conversation.getDisplayName()
+  const displayName = props.conversation.getDisplayName()
 
-    return (
-        <div className="message-list">
-            <Box>
-                <Box style={{ display: 'inline-block', margin: 16, verticalAlign: 'middle' }}>
-                    <Avatar>{displayName ? displayName[0].toUpperCase() : <PersonRounded />}</Avatar>
-                </Box>
-                <Box style={{ display: 'inline-block', verticalAlign: 'middle' }}>
-                    <Typography variant="h5">{displayName}</Typography>
-                    <Typography variant="subtitle1">{props.conversation.getId()}</Typography>
-                </Box>
-            </Box>
-            <Divider orientation="horizontal" />
-            {props.messages.map((message, index) =>
-                <Message key={index} username={message.senderId} text={message.text} />
-            )}
-        </div>
-    )
+  return (
+    <div className="message-list">
+      <Box>
+        <Box style={{ display: 'inline-block', margin: 16, verticalAlign: 'middle' }}>
+          <ConversationAvatar displayName={props.conversation.getDisplayNameNoFallback()} />
+        </Box>
+        <Box style={{ display: 'inline-block', verticalAlign: 'middle' }}>
+          <Typography variant="h6">{displayName}</Typography>
+          <Typography variant="subtitle1">{props.conversation.getId()}</Typography>
+        </Box>
+      </Box>
+      <Divider orientation="horizontal" />
+      {props.messages.map((message, index) =>
+        <Message key={index} username={message.senderId} text={message.text} />
+      )}
+    </div>
+  )
 }
\ No newline at end of file
diff --git a/client/src/components/NewContactForm.js b/client/src/components/NewContactForm.js
index 5636be2..3543d6d 100644
--- a/client/src/components/NewContactForm.js
+++ b/client/src/components/NewContactForm.js
@@ -1,49 +1,32 @@
-import React from 'react'
+import React, { useState } from 'react'
 import { InputBase, InputAdornment } from '@material-ui/core';
 import { SearchRounded } from '@material-ui/icons';
 
-class NewContactForm extends React.Component {
-    constructor(props) {
-        super(props)
-        this.state = {value: ''}
-        this.controller = new AbortController()
-        this.handleChange = this.handleChange.bind(this)
-        this.handleSubmit = this.handleSubmit.bind(this)
+export default function NewContactForm(props) {
+    const [value, setValue] = useState('')
+
+    const handleChange = event => {
+        setValue(event.target.value)
+        if (props.onChange)
+            props.onChange(event.target.value)
     }
 
-    componentDidMount() {
-        this.controller = new AbortController()
-    }
-
-    componentWillUnmount() {
-        this.controller.abort()
-        this.req = undefined
-    }
-
-    handleChange(event) {
-        this.setState({value: event.target.value})
-        this.props.onChange(event.target.value)
-    }
-
-    handleSubmit(event) {
+    const handleSubmit = event => {
         event.preventDefault()
-        if (this.props.onSubmit)
-            this.props.onSubmit(this.state.value)
+        if (value && props.onSubmit)
+            props.onSubmit(value)
     }
 
-    render() {
-        return (
-            <form className="main-search" onSubmit={this.handleSubmit} noValidate autoComplete="off">
-                <InputBase
-                    className="main-search-input"
-                    type="search"
-                    placeholder="Ajouter un contact"
-                    onChange={this.handleChange}
-                    startAdornment={<InputAdornment position="start"><SearchRounded /></InputAdornment>}
-                />
-            </form>
-        )
-    }
+    return (
+        <form className="main-search" onSubmit={handleSubmit} noValidate autoComplete="off">
+            <InputBase
+                className="main-search-input"
+                type="search"
+                placeholder="Ajouter un contact"
+                value={value}
+                onChange={handleChange}
+                startAdornment={<InputAdornment position="start"><SearchRounded /></InputAdornment>}
+            />
+        </form>
+    )
 }
-
-export default NewContactForm
\ No newline at end of file
diff --git a/client/src/components/loading.js b/client/src/components/loading.js
new file mode 100644
index 0000000..198b993
--- /dev/null
+++ b/client/src/components/loading.js
@@ -0,0 +1,8 @@
+import { CircularProgress, Container } from '@material-ui/core';
+import React from 'react';
+
+export default function LoadingPage() {
+    return <Container style={{ textAlign: "center" }}>
+        <CircularProgress style={{ margin: 32 }} />
+    </Container>
+}
\ No newline at end of file
diff --git a/client/src/index.ejs b/client/src/index.ejs
index aee5126..162d470 100644
--- a/client/src/index.ejs
+++ b/client/src/index.ejs
@@ -3,13 +3,12 @@
 
 <head>
   <meta charset="utf-8" />
-  <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
+  <link rel="icon" href="/favicon.ico" />
+  <link rel="apple-touch-icon" href="/logo192.png" />
   <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
-  <meta name="theme-color" content="#000000" />
   <meta name="description" content="Web site created using create-react-app" />
-  <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
   <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
-  <title>Jaas Web Client App</title>
+  <title>Jami Web Node</title>
 </head>
 
 <body>
diff --git a/client/src/index.js b/client/src/index.js
index 054afae..182e2cb 100644
--- a/client/src/index.js
+++ b/client/src/index.js
@@ -4,6 +4,7 @@
 import { BrowserRouter as Router } from 'react-router-dom'
 import App from './App.js'
 import './index.scss'
+import { CssBaseline } from '@material-ui/core'
 
 //import * as serviceWorker from './serviceWorker'
 const rootEl = document.getElementById('root')
@@ -11,6 +12,7 @@
 const render = Component =>
 ReactDOM.render(
   <React.StrictMode>
+    <CssBaseline />
     <Router>
     <Component />
     </Router>
diff --git a/client/src/index.scss b/client/src/index.scss
index 73ba105..9ddcfc8 100644
--- a/client/src/index.scss
+++ b/client/src/index.scss
@@ -23,16 +23,18 @@
 .app {
   display: grid;
   height: 100%;
-  grid-template-columns: repeat(6, 1fr);
-  grid-template-rows: 40px 40px 1fr 1fr 1fr 1fr 92px;
+  grid-template-columns: 320px 1fr;
+  grid-template-rows: 40px 50px 1fr 1fr 92px;
   grid-template-areas:
-      "h h h h h h"
-      "n m m m m m"
-      "r m m m m m"
-      "r m m m m m"
-      "r m m m m m"
-      "r m m m m m"
-      "r s s s s s";
+      "h m"
+      "n m"
+      "r m"
+      "r m"
+      "r s";
+}
+
+.MuiContainer-root {
+  padding-bottom: 32px;
 }
 
 .login {
diff --git a/client/src/pages/accountSelection.jsx b/client/src/pages/accountSelection.jsx
index 2a4c99b..40c0750 100644
--- a/client/src/pages/accountSelection.jsx
+++ b/client/src/pages/accountSelection.jsx
@@ -1,64 +1,52 @@
-import React from 'react';
-import Header from '../components/Header'
-import authManager from '../AuthManager'
-import AccountList from '../components/AccountList';
-import CircularProgress from '@material-ui/core/CircularProgress';
+import React, { useEffect, useState } from 'react';
 import { withRouter } from 'react-router-dom';
-import Card from '@material-ui/core/Card';
-import CardHeader from '@material-ui/core/CardHeader';
-import Container from '@material-ui/core/Container';
+import { Card, CardHeader, Container, CircularProgress } from '@material-ui/core';
+import Header from '../components/Header'
+import AccountList from '../components/AccountList';
+import authManager from '../AuthManager'
 import Account from '../../../model/Account';
+import LoadingPage from '../components/loading';
 
-class AccountSelection extends React.Component {
+const AccountSelection = (props) => {
+  const [state, setState] = useState({
+    loaded: false,
+    error: false,
+    accounts: []
+  })
 
-  constructor(props) {
-    super(props)
-    this.controller = new AbortController()
-    this.state = {
-      loaded: false,
-      error: false,
-      accounts: []
-    }
-  }
-
-  componentDidMount() {
-    if (!this.state.loaded) {
-      authManager.fetch('/api/accounts', {signal: this.controller.signal})
-        .then(res => res.json())
-        .then(result => {
-          console.log(result)
-          this.setState({
-            loaded: true,
-            accounts: result.map(account => Account.from(account)),
-          })
-        }, error => {
-          console.log(`get error ${error}`)
-          this.setState({
-            loaded: true,
-            error: true
-          })
+  useEffect(() => {
+    const controller = new AbortController()
+    authManager.fetch(`/api/accounts`, {signal: controller.signal})
+      .then(res => res.json())
+      .then(result => {
+        console.log(result)
+        setState({
+          loaded: true,
+          accounts: result.map(account => Account.from(account)),
         })
-      }
-  }
-  componentWillUnmount() {
-    this.controller.abort()
-  }
+      }, error => {
+        console.log(`get error ${error}`)
+        setState({
+          loaded: true,
+          error: true
+        })
+      })
+    return () => controller.abort()
+  }, [])
 
-  render() {
-    if (!this.state.loaded)
-      return <Container><CircularProgress /></Container>
-    return (
-      <div className="app" style={{marginBottom:32}} >
-        <Header />
-        <Container>
-          <Card style={{marginTop:32, marginBottom:32}}>
-            <CardHeader title="Choose an account" />
-            <AccountList accounts={this.state.accounts} onClick={account => this.props.history.push(`/account/${account.getId()}`)} />
-          </Card>
-        </Container>
-      </div>
-    )
-  }
+  if (!state.loaded)
+    return <LoadingPage />
+  return (
+    <React.Fragment>
+      <Header />
+      <Container maxWidth="sm" style={{paddingBottom:32}}>
+        <Card style={{marginTop:32, marginBottom:32}}>
+          <CardHeader title="Choose an account" />
+          <AccountList accounts={state.accounts} onClick={account => props.history.push(`/account/${account.getId()}/settings`)} />
+        </Card>
+      </Container>
+    </React.Fragment>
+  )
 }
 
 export default withRouter(AccountSelection);
\ No newline at end of file
diff --git a/client/src/pages/accountSettings.jsx b/client/src/pages/accountSettings.jsx
index 12fa43a..79ab388 100644
--- a/client/src/pages/accountSettings.jsx
+++ b/client/src/pages/accountSettings.jsx
@@ -1,45 +1,32 @@
-import React from 'react';
+import React, {useEffect, useState} from 'react';
+import { useParams } from 'react-router';
+import { Container, CircularProgress } from '@material-ui/core';
 import Header from '../components/Header'
 import AccountPreferences from '../components/AccountPreferences'
-import Container from '@material-ui/core/Container';
-import CircularProgress from '@material-ui/core/CircularProgress';
 import authManager from '../AuthManager'
 import Account from '../../../model/Account'
 
-class AccountSettings extends React.Component {
+const AccountSettings = (props) => {
+  const accountId = props.accountId || useParams().accountId
+  const [state, setState] = useState({ loaded: false })
 
-  constructor(props) {
-    super(props)
-    this.accountId = props.accountId || props.match.params.accountId
-    this.state = { loaded: false, account: props.account }
-    this.req = undefined
-  }
+  useEffect(() => {
+    const controller = new AbortController()
+    authManager.fetch(`/api/accounts/${accountId}`, {signal: controller.signal})
+      .then(res => res.json())
+      .then(result => {
+        console.log(result)
+        setState({loaded: true, account: Account.from(result)})
+      })
+      return () => controller.abort()
+  }, [])
 
-  componentDidMount() {
-    this.controller = new AbortController()
-    if (this.req === undefined) {
-      this.req = authManager.fetch(`/api/accounts/${this.accountId}`, {signal: this.controller.signal})
-        .then(res => res.json())
-        .then(result => {
-          console.log(result)
-          this.setState({loaded: true, account: Account.from(result)})
-        })
-    }
-  }
-
-  componentWillUnmount() {
-    this.controller.abort()
-    this.req = undefined
-  }
-
-  render() {
-    return (
-      <Container maxWidth="sm" className="app" >
-        <Header />
-        {this.state.loaded ? <AccountPreferences account={this.state.account} /> : <CircularProgress />}
-      </Container>
-    )
-  }
+  return (
+    <Container maxWidth="sm">
+      <Header />
+      {state.loaded ? <AccountPreferences account={state.account} /> : <CircularProgress />}
+    </Container>
+  )
 }
 
 export default AccountSettings;
\ No newline at end of file
diff --git a/client/src/pages/messenger.jsx b/client/src/pages/messenger.jsx
index f5e5104..3fef47b 100644
--- a/client/src/pages/messenger.jsx
+++ b/client/src/pages/messenger.jsx
@@ -15,6 +15,7 @@
 import Contact from '../../../model/Contact'
 import ConversationView from '../components/ConversationView';
 import AddContactPage from './addContactPage.jsx';
+import LoadingPage from '../components/loading';
 
 class JamiMessenger extends React.Component {
 
@@ -120,7 +121,7 @@
         <Header />
         {this.state.conversations ?
           <ConversationList search={this.state.searchResult} conversations={this.state.conversations} accountId={accountId} /> :
-          <CircularProgress />}
+          <div className="rooms-list"><LoadingPage /></div>}
         <NewContactForm onChange={query => this.handleSearch(query)} />
         {conversationId && <ConversationView accountId={accountId} conversationId={conversationId} />}
         {contactId && <AddContactPage accountId={accountId} contactId={contactId} />}
@@ -137,4 +138,4 @@
   }
 }
 
-export default JamiMessenger;
\ No newline at end of file
+export default JamiMessenger
\ No newline at end of file
diff --git a/client/src/pages/serverSetup.jsx b/client/src/pages/serverSetup.jsx
index 70f9342..29e4ea5 100644
--- a/client/src/pages/serverSetup.jsx
+++ b/client/src/pages/serverSetup.jsx
@@ -29,11 +29,13 @@
   const history = useHistory();
   const [password, setPassword] = useState('');
   const [passwordRepeat, setPasswordRepeat] = useState('');
+  const [loading, setLoading] = useState(false);
 
   const isValid = () => password && password === passwordRepeat
 
   const handleSubmit = async e => {
     e.preventDefault()
+    setLoading(true)
     if (!isValid())
       return
     if (await authManager.setup(password)) {
@@ -43,7 +45,7 @@
 
   return (
     <Container className='message-list'>
-      <Card  className={classes.wizardCard}>
+      <Card className={classes.wizardCard} disabled={loading}>
         <CardContent component="form" onSubmit={handleSubmit}>
           <Typography gutterBottom variant="h5" component="h2">
           Jami Web Node setup
@@ -53,7 +55,7 @@
             Let's start by creating a new administrator account to control access to the server configuration.
           </Typography>
 
-          <Typography variant='body1'></Typography>
+          <Box style={{ textAlign: 'center', marginTop: 8, marginBottom: 16 }}>
           <div><Input className={classes.textField} value="admin" name="username" autoComplete="username" disabled /></div>
           <div><Input
             className={classes.textField}
@@ -73,7 +75,8 @@
             type='password'
             placeholder="Repeat password"
             autoComplete="new-password" /></div>
-          <Box style={{ textAlign: 'center', marginTop: 16 }}>
+          </Box>
+          <Box style={{ textAlign: 'center', marginTop: 24 }}>
             <Fab variant='extended' color='primary' type='submit' disabled={!isValid()}>
               <GroupAddRounded className={classes.extendedIcon} />
               Create admin account
diff --git a/client/webpack.config.js b/client/webpack.config.js
index 82caf43..0b67ce9 100644
--- a/client/webpack.config.js
+++ b/client/webpack.config.js
@@ -5,6 +5,7 @@
 
 import { resolve } from 'path'
 import HtmlWebpackPlugin from 'html-webpack-plugin'
+import CopyWebpackPlugin from 'copy-webpack-plugin'
 
 import { fileURLToPath } from 'url';
 import { dirname } from 'path';
@@ -13,9 +14,12 @@
 const mode = process.env.NODE_ENV || 'development'
 
 let entry = [resolve(__dirname, 'src', 'index.js')]
-let plugins = [new HtmlWebpackPlugin({
-    template: resolve(__dirname, 'src', 'index.ejs')
-})]
+let plugins = [
+    new HtmlWebpackPlugin({template: resolve(__dirname, 'src', 'index.ejs')}),
+    new CopyWebpackPlugin({
+        patterns: [{ from: resolve(__dirname, 'public'), to: resolve(__dirname, 'dist') }]
+    })
+]
 let devtool = undefined
 let babelLoaderPlugins = ["@babel/plugin-transform-runtime"]
 
diff --git a/model/Contact.js b/model/Contact.js
index 8fa26b2..66459d2 100644
--- a/model/Contact.js
+++ b/model/Contact.js
@@ -18,14 +18,22 @@
 
     setRegisteredName(name) { this.registeredName = name }
 
-    getDisplayName() {
-        return this.displayName || this.getRegisteredName() || this.getUri()
+    isRegisteredNameResolved() {
+        return this.registeredName !== undefined
     }
 
-    getObject() {
+    getDisplayName() {
+        return this.getDisplayNameNoFallback() || this.getUri()
+    }
+
+    getDisplayNameNoFallback() {
+        return this.displayName || this.getRegisteredName()
+    }
+
+    async getObject() {
         return {
             uri: this.uri,
-            registeredName: this.registeredName
+            registeredName: await this.registeredName
         }
     }
 }
diff --git a/model/Conversation.js b/model/Conversation.js
index 09fb76f..98e21dd 100644
--- a/model/Conversation.js
+++ b/model/Conversation.js
@@ -29,15 +29,21 @@
         return this.getDisplayUri()
     }
 
-    getObject(params) {
+    getDisplayNameNoFallback() {
+        if (this.members.length !== 0) {
+            return this.members[0].contact.getDisplayNameNoFallback()
+        }
+    }
+
+    async getObject(params) {
         const members = params.memberFilter ? this.members.filter(params.memberFilter) : this.members
         return {
             id: this.id,
-            members: members.map(member => {
+            members: await Promise.all(members.map(async member => {
                 const copiedMember = { role: member.role }//Object.assign({}, member);
-                copiedMember.contact = member.contact.getObject()
+                copiedMember.contact = await member.contact.getObject()
                 return copiedMember
-            })
+            }))
         }
     }
 
diff --git a/package-lock.json b/package-lock.json
index 2042d1f..4873c1a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -31,6 +31,7 @@
         "socket.io": "^2.3.0"
       },
       "devDependencies": {
+        "copy-webpack-plugin": "^8.1.1",
         "jami-web-client": "file:client",
         "llnode": "^3.2.0",
         "nodemon": "^2.0.7",
@@ -39,6 +40,7 @@
       }
     },
     "client": {
+      "name": "jami-web-client",
       "version": "0.1.0",
       "dev": true,
       "dependencies": {
@@ -1912,6 +1914,41 @@
         "react-dom": "^16.8.0 || ^17.0.0"
       }
     },
+    "node_modules/@nodelib/fs.scandir": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
+      "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.stat": "2.0.4",
+        "run-parallel": "^1.1.9"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.stat": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
+      "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.walk": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
+      "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.scandir": "2.1.4",
+        "fastq": "^1.6.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
     "node_modules/@sheerun/mutationobserver-shim": {
       "version": "0.3.3",
       "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
@@ -2908,6 +2945,15 @@
       "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
       "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
     },
+    "node_modules/array-union": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/arraybuffer.slice": {
       "version": "0.0.7",
       "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
@@ -3590,6 +3636,31 @@
       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
     },
+    "node_modules/copy-webpack-plugin": {
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-8.1.1.tgz",
+      "integrity": "sha512-rYM2uzRxrLRpcyPqGceRBDpxxUV8vcDqIKxAUKfcnFpcrPxT5+XvhTxv7XLjo5AvEJFPdAE3zCogG2JVahqgSQ==",
+      "dev": true,
+      "dependencies": {
+        "fast-glob": "^3.2.5",
+        "glob-parent": "^5.1.1",
+        "globby": "^11.0.3",
+        "normalize-path": "^3.0.0",
+        "p-limit": "^3.1.0",
+        "schema-utils": "^3.0.0",
+        "serialize-javascript": "^5.0.1"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "webpack": "^5.1.0"
+      }
+    },
     "node_modules/core-js": {
       "version": "3.10.1",
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.10.1.tgz",
@@ -3897,6 +3968,18 @@
         "node": ">= 6"
       }
     },
+    "node_modules/dir-glob": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+      "dev": true,
+      "dependencies": {
+        "path-type": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/dom-accessibility-api": {
       "version": "0.5.4",
       "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz",
@@ -4472,6 +4555,23 @@
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
       "dev": true
     },
+    "node_modules/fast-glob": {
+      "version": "3.2.5",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
+      "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.0",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.2",
+        "picomatch": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/fast-json-stable-stringify": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -4496,6 +4596,15 @@
       "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
       "dev": true
     },
+    "node_modules/fastq": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
+      "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
+      "dev": true,
+      "dependencies": {
+        "reusify": "^1.0.4"
+      }
+    },
     "node_modules/faye": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/faye/-/faye-1.4.0.tgz",
@@ -4707,6 +4816,26 @@
         "node": ">=4"
       }
     },
+    "node_modules/globby": {
+      "version": "11.0.3",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz",
+      "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==",
+      "dev": true,
+      "dependencies": {
+        "array-union": "^2.1.0",
+        "dir-glob": "^3.0.1",
+        "fast-glob": "^3.1.1",
+        "ignore": "^5.1.4",
+        "merge2": "^1.3.0",
+        "slash": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/got": {
       "version": "9.6.0",
       "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
@@ -5013,6 +5142,15 @@
         "postcss": "^8.1.0"
       }
     },
+    "node_modules/ignore": {
+      "version": "5.1.8",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+      "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 4"
+      }
+    },
     "node_modules/ignore-by-default": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
@@ -5987,6 +6125,15 @@
       "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
       "dev": true
     },
+    "node_modules/merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
     "node_modules/methods": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
@@ -5995,6 +6142,19 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/micromatch": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+      "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+      "dev": true,
+      "dependencies": {
+        "braces": "^3.0.1",
+        "picomatch": "^2.2.3"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
     "node_modules/mime": {
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
@@ -6682,6 +6842,15 @@
       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
       "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
     },
+    "node_modules/path-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/pause": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
@@ -6949,6 +7118,26 @@
         "node": ">=0.4.x"
       }
     },
+    "node_modules/queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
     "node_modules/random-bytes": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
@@ -7465,6 +7654,39 @@
         "lowercase-keys": "^1.0.0"
       }
     },
+    "node_modules/reusify": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+      "dev": true,
+      "engines": {
+        "iojs": ">=1.0.0",
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
     "node_modules/safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -7702,6 +7924,15 @@
       "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
       "dev": true
     },
+    "node_modules/slash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/sliced": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
@@ -10115,6 +10346,32 @@
         "react-is": "^16.8.0 || ^17.0.0"
       }
     },
+    "@nodelib/fs.scandir": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
+      "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.stat": "2.0.4",
+        "run-parallel": "^1.1.9"
+      }
+    },
+    "@nodelib/fs.stat": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
+      "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
+      "dev": true
+    },
+    "@nodelib/fs.walk": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
+      "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.scandir": "2.1.4",
+        "fastq": "^1.6.0"
+      }
+    },
     "@sheerun/mutationobserver-shim": {
       "version": "0.3.3",
       "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
@@ -10984,6 +11241,12 @@
       "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
       "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
     },
+    "array-union": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true
+    },
     "arraybuffer.slice": {
       "version": "0.0.7",
       "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
@@ -11525,6 +11788,21 @@
       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
     },
+    "copy-webpack-plugin": {
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-8.1.1.tgz",
+      "integrity": "sha512-rYM2uzRxrLRpcyPqGceRBDpxxUV8vcDqIKxAUKfcnFpcrPxT5+XvhTxv7XLjo5AvEJFPdAE3zCogG2JVahqgSQ==",
+      "dev": true,
+      "requires": {
+        "fast-glob": "^3.2.5",
+        "glob-parent": "^5.1.1",
+        "globby": "^11.0.3",
+        "normalize-path": "^3.0.0",
+        "p-limit": "^3.1.0",
+        "schema-utils": "^3.0.0",
+        "serialize-javascript": "^5.0.1"
+      }
+    },
     "core-js": {
       "version": "3.10.1",
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.10.1.tgz",
@@ -11752,6 +12030,15 @@
       "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==",
       "dev": true
     },
+    "dir-glob": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+      "dev": true,
+      "requires": {
+        "path-type": "^4.0.0"
+      }
+    },
     "dom-accessibility-api": {
       "version": "0.5.4",
       "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz",
@@ -12213,6 +12500,20 @@
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
       "dev": true
     },
+    "fast-glob": {
+      "version": "3.2.5",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
+      "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.0",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.2",
+        "picomatch": "^2.2.1"
+      }
+    },
     "fast-json-stable-stringify": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -12230,6 +12531,15 @@
       "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
       "dev": true
     },
+    "fastq": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
+      "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
+      "dev": true,
+      "requires": {
+        "reusify": "^1.0.4"
+      }
+    },
     "faye": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/faye/-/faye-1.4.0.tgz",
@@ -12386,6 +12696,20 @@
       "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
       "dev": true
     },
+    "globby": {
+      "version": "11.0.3",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz",
+      "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==",
+      "dev": true,
+      "requires": {
+        "array-union": "^2.1.0",
+        "dir-glob": "^3.0.1",
+        "fast-glob": "^3.1.1",
+        "ignore": "^5.1.4",
+        "merge2": "^1.3.0",
+        "slash": "^3.0.0"
+      }
+    },
     "got": {
       "version": "9.6.0",
       "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
@@ -12639,6 +12963,12 @@
       "dev": true,
       "requires": {}
     },
+    "ignore": {
+      "version": "5.1.8",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+      "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+      "dev": true
+    },
     "ignore-by-default": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
@@ -13502,11 +13832,27 @@
       "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
       "dev": true
     },
+    "merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "dev": true
+    },
     "methods": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
       "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
     },
+    "micromatch": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+      "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+      "dev": true,
+      "requires": {
+        "braces": "^3.0.1",
+        "picomatch": "^2.2.3"
+      }
+    },
     "mime": {
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
@@ -14011,6 +14357,12 @@
       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
       "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
     },
+    "path-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+      "dev": true
+    },
     "pause": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
@@ -14214,6 +14566,12 @@
       "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==",
       "dev": true
     },
+    "queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "dev": true
+    },
     "random-bytes": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
@@ -14641,6 +14999,21 @@
         "lowercase-keys": "^1.0.0"
       }
     },
+    "reusify": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+      "dev": true
+    },
+    "run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "dev": true,
+      "requires": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -14815,6 +15188,12 @@
       "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
       "dev": true
     },
+    "slash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "dev": true
+    },
     "sliced": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
diff --git a/routes/jami.js b/routes/jami.js
index 674a688..77d8139 100644
--- a/routes/jami.js
+++ b/routes/jami.js
@@ -32,6 +32,7 @@
         accountRouter.get(['/'], (req, res, next) => {
             console.log(`Get account ${req.params.accountId}`)
             const account = this.jami.getAccount(req.params.accountId)
+            account.defaultModerators = this.jami.getDefaultModerators(account.getId())
             if (account)
                 res.json(account.getObject())
             else
@@ -49,15 +50,15 @@
         })
 
         // Conversations
-        accountRouter.get('/conversations', (req, res, next) => {
+        accountRouter.get('/conversations', async (req, res, next) => {
             console.log(`Get conversations for account ${req.params.accountId}`)
             const account = this.jami.getAccount(req.params.accountId)
             if (!account)
                 return res.sendStatus(404)
             const conversations = account.getConversations()
-            res.json(Object.keys(conversations).map(conversationId => conversations[conversationId].getObject({
+            res.json(await Promise.all(Object.keys(conversations).map(async conversationId => await conversations[conversationId].getObject({
                 memberFilter: member => member.contact.getUri() !== account.getUri()
-            })))
+            }))))
             //res.json(account.getConversations())
         })
 
@@ -74,7 +75,7 @@
                 res.status(400).end()
         })
 
-        accountRouter.get('/conversations/:conversationId', (req, res, next) => {
+        accountRouter.get('/conversations/:conversationId', async (req, res, next) => {
             console.log(`Get conversation ${req.params.conversationId} for account ${req.params.accountId}`)
             const account = this.jami.getAccount(req.params.accountId)
             if (!account)
@@ -83,7 +84,7 @@
             if (!conversation)
                 res.status(404).end()
             else {
-                res.json(conversation.getObject({
+                res.json(await conversation.getObject({
                     memberFilter: member => member.contact.getUri() !== account.getUri()
                 }))
             }