diff --git a/web/settings/relationship/block-list-modal.react.js b/web/settings/relationship/block-list-modal.react.js index 7d31fcc83..4fc5f756a 100644 --- a/web/settings/relationship/block-list-modal.react.js +++ b/web/settings/relationship/block-list-modal.react.js @@ -1,49 +1,49 @@ // @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 } from 'lib/types/user-types.js'; +import type { AccountUserInfo, UserInfo } from 'lib/types/user-types.js'; import BlockListRow from './block-list-row.react.js'; import BlockUsersModal from './block-users-modal.react.js'; import UserListModal from './user-list-modal.react.js'; -function filterUser(userInfo: AccountUserInfo) { +function filterUser(userInfo: UserInfo) { return ( userInfo.relationshipStatus === userRelationshipStatus.BLOCKED_BY_VIEWER || userInfo.relationshipStatus === userRelationshipStatus.BOTH_BLOCKED ); } function usersComparator(user1: AccountUserInfo, user2: AccountUserInfo) { return user1.username.localeCompare(user2.username); } type Props = { +onClose: () => void, }; function BlockListModal(props: Props): React.Node { const { onClose } = props; const { pushModal } = useModalContext(); const openBlockUsersModal = React.useCallback(() => { pushModal(); }, [onClose, pushModal]); return ( ); } export default BlockListModal; diff --git a/web/settings/relationship/friend-list-modal.react.js b/web/settings/relationship/friend-list-modal.react.js index eabc7c91f..342d896f4 100644 --- a/web/settings/relationship/friend-list-modal.react.js +++ b/web/settings/relationship/friend-list-modal.react.js @@ -1,58 +1,58 @@ // @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 } from 'lib/types/user-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 UserListModal from './user-list-modal.react.js'; const relationships = [ userRelationshipStatus.REQUEST_RECEIVED, userRelationshipStatus.REQUEST_SENT, userRelationshipStatus.FRIEND, ]; -function filterUser(userInfo: AccountUserInfo) { +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) ); } type Props = { +onClose: () => void, }; function FriendListModal(props: Props): React.Node { const { onClose } = props; const { pushModal } = useModalContext(); const openNewFriendsModal = React.useCallback(() => { pushModal(); }, [onClose, pushModal]); return ( ); } export default FriendListModal; diff --git a/web/settings/relationship/user-list-modal.react.js b/web/settings/relationship/user-list-modal.react.js index 1ca8d71d1..933f221a7 100644 --- a/web/settings/relationship/user-list-modal.react.js +++ b/web/settings/relationship/user-list-modal.react.js @@ -1,68 +1,68 @@ // @flow import * as React from 'react'; -import type { AccountUserInfo } from 'lib/types/user-types.js'; +import type { AccountUserInfo, UserInfo } from 'lib/types/user-types.js'; import css from './user-list.css'; import { UserList, type UserRowProps } from './user-list.react.js'; import Button from '../../components/button.react.js'; import SearchModal from '../../modals/search-modal.react.js'; type Props = { +onClose: () => void, +name: string, +userRowComponent: React.ComponentType, - +filterUser: (userInfo: AccountUserInfo) => boolean, + +filterUser: (userInfo: UserInfo) => boolean, +usersComparator: (user1: AccountUserInfo, user2: AccountUserInfo) => number, +buttonLabel: string, +onAddUsersClick: () => void, }; function UserListModal(props: Props): React.Node { const { onClose, name, userRowComponent, filterUser, usersComparator, buttonLabel, onAddUsersClick, } = props; const searchModalChildGenerator = React.useCallback( (searchText: string) => (
), [ buttonLabel, filterUser, onAddUsersClick, userRowComponent, usersComparator, ], ); return ( {searchModalChildGenerator} ); } export default UserListModal; diff --git a/web/settings/relationship/user-list.react.js b/web/settings/relationship/user-list.react.js index 9142b820a..06363f9ff 100644 --- a/web/settings/relationship/user-list.react.js +++ b/web/settings/relationship/user-list.react.js @@ -1,75 +1,80 @@ // @flow import classNames from 'classnames'; import * as React from 'react'; import { useENSNames } from 'lib/hooks/ens-cache.js'; -import { userStoreSearchIndex as userStoreSearchIndexSelector } from 'lib/selectors/user-selectors.js'; -import type { AccountUserInfo } from 'lib/types/user-types.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: AccountUserInfo) => boolean, + +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 userStoreSearchIndex = useSelector(userStoreSearchIndexSelector); + 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 : Object.keys(userInfos); - const unfilteredUserInfos = []; + const userIDs = searchText ? searchResult : userInfosArray.map(u => u.id); + const matchedUserInfos = []; for (const id of userIDs) { const { username, relationshipStatus } = userInfos[id]; if (!username) { continue; } - unfilteredUserInfos.push({ + matchedUserInfos.push({ id, username, relationshipStatus, }); } - return unfilteredUserInfos.filter(filterUser).sort(usersComparator); - }, [filterUser, searchResult, searchText, userInfos, usersComparator]); + 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, { [css.noScroll]: isMenuVisible, }); return
{userRows}
; }