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}
;
}