11import PropTypes from 'prop-types'
2- import React , { useState , useMemo } from 'react'
2+ import React , { useCallback , useMemo } from 'react'
33
4+ import { isQueryLoading , useClient , useQuery , useQueryAll } from 'cozy-client'
45import Avatar from 'cozy-ui/transpiled/react/Avatar'
56import ContactsListModal from 'cozy-ui/transpiled/react/ContactsListModal'
67import Divider from 'cozy-ui/transpiled/react/Divider'
@@ -9,16 +10,20 @@ import List from 'cozy-ui/transpiled/react/List'
910import ListItem from 'cozy-ui/transpiled/react/ListItem'
1011import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
1112import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
13+ import ListItemSkeleton from 'cozy-ui/transpiled/react/Skeletons/ListItemSkeleton'
1214import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
1315
1416import Contact from './Contact'
15- import { useSessionstorage } from '../Hooks/useSessionstorage'
17+ import { SETTINGS_DOCTYPE } from '../../doctypes'
18+ import { buildContactsQueryByIds , getAppSettings } from '../../helpers/queries'
1619
1720const styleAvatar = {
1821 color : 'var(--primaryColor)' ,
1922 backgroundColor : 'var(--primaryColorLightest)'
2023}
2124
25+ let contactList = [ ]
26+
2227const ContactList = ( {
2328 multiple,
2429 currentUser,
@@ -30,23 +35,40 @@ const ContactList = ({
3035 onSelection
3136} ) => {
3237 const { t } = useI18n ( )
38+ const client = useClient ( )
3339
34- const [ contactsLocalSession , setContactLocalSession ] = useSessionstorage (
35- 'contactList' ,
36- [ ]
40+ const { data : settingsData , ... settingsQuery } = useQuery (
41+ getAppSettings . definition ,
42+ getAppSettings . options
3743 )
38- const [ contactsList , setContactsList ] = useState ( [
39- currentUser ,
40- ...contactsLocalSession
41- ] )
44+ const isLoadingSettings = isQueryLoading ( settingsQuery )
45+
46+ const suggestedContactIds = settingsData [ 0 ] ?. suggestedContactIds || [ ]
47+ const contactsQueryByIds = buildContactsQueryByIds (
48+ suggestedContactIds ,
49+ ! isLoadingSettings
50+ )
51+ const { data : contacts , ...contactQueryResult } = useQueryAll (
52+ contactsQueryByIds . definition ,
53+ contactsQueryByIds . options
54+ )
55+ const isLoadingContacts =
56+ isQueryLoading ( contactQueryResult ) || contactQueryResult . hasMore
57+
58+ if ( ! isLoadingSettings && ! isLoadingContacts && currentUser ) {
59+ contactList = [ currentUser , ...contacts ]
60+ }
4261
4362 const idsSelected = useMemo ( ( ) => selected . map ( v => v . _id ) , [ selected ] )
4463
45- const onClickContactsListModal = contact => {
46- const contactAlreadyListed = contactsList . some ( cl => cl . _id === contact . _id )
64+ const onClickContactsListModal = async contact => {
65+ const contactAlreadyListed = contactList . some ( cl => cl . _id === contact . _id )
4766 if ( ! contactAlreadyListed ) {
48- setContactsList ( prev => [ ...prev , contact ] )
49- setContactLocalSession ( prev => [ ...prev , contact ] )
67+ await client . save ( {
68+ ...settingsData [ 0 ] ,
69+ suggestedContactIds : [ ...suggestedContactIds , contact . _id ] ,
70+ _type : SETTINGS_DOCTYPE
71+ } )
5072 }
5173 onSelection ( multiple ? [ ...selected , contact ] : [ contact ] )
5274 setContactModalOpened ( false )
@@ -63,29 +85,44 @@ const ContactList = ({
6385 else newContactIdSelected . push ( newValue )
6486
6587 onSelection (
66- contactsList . filter ( contact =>
88+ contactList . filter ( contact =>
6789 newContactIdSelected . includes ( contact . _id )
6890 )
6991 )
7092 } else {
71- onSelection ( contactsList . filter ( contact => contact . id === newValue ) )
93+ onSelection ( contactList . filter ( contact => contact . id === newValue ) )
7294 }
7395 }
7496
97+ // Returns a number of Skeletons based on the number of contactIds in the app settings + the current user
98+ const Skeleton = useCallback (
99+ ( ) =>
100+ Array . from ( Array ( suggestedContactIds . length + 1 ) , ( _ , idx ) => (
101+ < ListItemSkeleton key = { idx } />
102+ ) ) ,
103+ [ suggestedContactIds . length ]
104+ )
105+
75106 return (
76107 < >
77108 < List className = { className } >
78- < div className = "u-mah-5 u-ov-auto" >
79- { contactsList . map ( contact => (
80- < Contact
81- key = { contact . _id }
82- contact = { contact }
83- multiple = { multiple }
84- selected = { idsSelected . includes ( contact . _id ) }
85- onSelection = { onClickContactLine }
86- />
87- ) ) }
88- </ div >
109+ { contactList . length === 0 &&
110+ ( isLoadingSettings || isLoadingContacts ) ? (
111+ < Skeleton />
112+ ) : (
113+ < div className = "u-mah-5 u-ov-auto" >
114+ { contactList . map ( contact => (
115+ < Contact
116+ key = { contact . _id }
117+ contact = { contact }
118+ multiple = { multiple }
119+ selected = { idsSelected . includes ( contact . _id ) }
120+ onSelection = { onClickContactLine }
121+ />
122+ ) ) }
123+ </ div >
124+ ) }
125+
89126 { ! withoutDivider && < Divider variant = "inset" component = "li" /> }
90127 < ListItem button onClick = { ( ) => setContactModalOpened ( true ) } >
91128 < ListItemIcon >
@@ -116,7 +153,7 @@ ContactList.propTypes = {
116153 /** Determine whether the user can select several contacts */
117154 multiple : PropTypes . bool . isRequired ,
118155 /** Contact object representing the current user */
119- currentUser : PropTypes . object . isRequired ,
156+ currentUser : PropTypes . object ,
120157 className : PropTypes . string ,
121158 contactModalOpened : PropTypes . bool . isRequired ,
122159 setContactModalOpened : PropTypes . func . isRequired ,
0 commit comments