diff --git a/web/settings/relationship/friend-list-panel.react.js b/web/settings/relationship/friend-list-panel.react.js new file mode 100644 index 000000000..856174529 --- /dev/null +++ b/web/settings/relationship/friend-list-panel.react.js @@ -0,0 +1,87 @@ +// @flow + +import * as React from 'react'; + +import { useModalContext } from 'lib/components/modal-provider.react.js'; +import { userRelationshipStatus } from 'lib/types/relationship-types.js'; +import type { AccountUserInfo, UserInfo } from 'lib/types/user-types.js'; + +import AddFriendsModal from './add-friends-modal.react.js'; +import FriendListRow from './friend-list-row.react.js'; +import css from './user-list.css'; +import { UserList } from './user-list.react.js'; +import PanelHeader from '../../components/panel-header.react.js'; +import Panel, { type PanelData } from '../../components/panel.react.js'; +import Search from '../../components/search.react.js'; + +const relationships = [ + userRelationshipStatus.REQUEST_RECEIVED, + userRelationshipStatus.REQUEST_SENT, + userRelationshipStatus.FRIEND, +]; + +function filterUser(userInfo: UserInfo) { + return relationships.includes(userInfo.relationshipStatus); +} + +function usersComparator(user1: AccountUserInfo, user2: AccountUserInfo) { + if (user1.relationshipStatus === user2.relationshipStatus) { + return user1.username.localeCompare(user2.username); + } + return ( + relationships.indexOf(user1.relationshipStatus) - + relationships.indexOf(user2.relationshipStatus) + ); +} + +function FriendListPanel(): React.Node { + const [searchText, setSearchText] = React.useState(''); + + const { pushModal, popModal } = useModalContext(); + + const onClickAddFriendsButton = React.useCallback( + () => pushModal(), + [popModal, pushModal], + ); + + const friendList = React.useMemo( + () => ( +
+
+ +
+ +
+ ), + [searchText], + ); + + const panelData: $ReadOnlyArray = React.useMemo( + () => [ + { + header: ( + + ), + body: friendList, + classNameOveride: css.panelContainer, + }, + ], + [friendList, onClickAddFriendsButton], + ); + + return ; +} + +export default FriendListPanel; diff --git a/web/settings/relationship/user-list.css b/web/settings/relationship/user-list.css index 581c24d85..27646f197 100644 --- a/web/settings/relationship/user-list.css +++ b/web/settings/relationship/user-list.css @@ -1,16 +1,31 @@ +.panelContainer { + flex: 1; +} + .container { + display: flex; + flex-direction: column; + height: 100%; + padding: 8px; +} + +.searchContainer { + padding: 8px; +} + +.userListContainer { overflow: auto; flex-grow: 1; flex-basis: 120px; } .noScroll { overflow: hidden; } .searchModalContent { display: flex; flex-direction: column; row-gap: 8px; height: 625px; } diff --git a/web/settings/relationship/user-list.react.js b/web/settings/relationship/user-list.react.js index 06363f9ff..130a3377b 100644 --- a/web/settings/relationship/user-list.react.js +++ b/web/settings/relationship/user-list.react.js @@ -1,80 +1,80 @@ // @flow import classNames from 'classnames'; import * as React from 'react'; import { useENSNames } from 'lib/hooks/ens-cache.js'; import { useUserSearchIndex } from 'lib/selectors/nav-selectors.js'; import type { AccountUserInfo, UserInfo } from 'lib/types/user-types.js'; import { values } from 'lib/utils/objects.js'; import css from './user-list.css'; import { useSelector } from '../../redux/redux-utils.js'; export type UserRowProps = { +userInfo: AccountUserInfo, +onMenuVisibilityChange?: (visible: boolean) => void, }; type UserListProps = { +userRowComponent: React.ComponentType, +filterUser: (userInfo: UserInfo) => boolean, +usersComparator: (user1: AccountUserInfo, user2: AccountUserInfo) => number, +searchText: string, }; export function UserList(props: UserListProps): React.Node { const { userRowComponent, filterUser, usersComparator, searchText } = props; const userInfos = useSelector(state => state.userStore.userInfos); const userInfosArray = React.useMemo( () => values(userInfos).filter(filterUser), [userInfos, filterUser], ); const userStoreSearchIndex = useUserSearchIndex(userInfosArray); const [isMenuVisible, setIsMenuVisible] = React.useState(false); const onMenuVisibilityChange = React.useCallback( (visible: boolean) => setIsMenuVisible(visible), [], ); const searchResult = React.useMemo( () => userStoreSearchIndex.getSearchResults(searchText), [searchText, userStoreSearchIndex], ); const users = React.useMemo(() => { const userIDs = searchText ? searchResult : userInfosArray.map(u => u.id); const matchedUserInfos = []; for (const id of userIDs) { const { username, relationshipStatus } = userInfos[id]; if (!username) { continue; } matchedUserInfos.push({ id, username, relationshipStatus, }); } return matchedUserInfos.sort(usersComparator); }, [userInfosArray, searchResult, searchText, userInfos, usersComparator]); const usersWithENSNames = useENSNames(users); const userRows = React.useMemo(() => { const UserRow = userRowComponent; return usersWithENSNames.map(user => ( )); }, [userRowComponent, usersWithENSNames, onMenuVisibilityChange]); - const containerClasses = classNames(css.container, { + const containerClasses = classNames(css.userListContainer, { [css.noScroll]: isMenuVisible, }); return
{userRows}
; }