Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32575956
D11065.1767389115.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D11065.1767389115.diff
View Options
diff --git a/web/modals/threads/create/compose-subchannel-modal.react.js b/web/modals/threads/create/compose-subchannel-modal.react.js
--- a/web/modals/threads/create/compose-subchannel-modal.react.js
+++ b/web/modals/threads/create/compose-subchannel-modal.react.js
@@ -22,6 +22,10 @@
import { updateNavInfoActionType } from '../../../redux/action-types.js';
import { useSelector } from '../../../redux/redux-utils.js';
import { nonThreadCalendarQuery } from '../../../selectors/nav-selectors.js';
+import {
+ useAddUsersListContext,
+ AddUsersListProvider,
+} from '../../../settings/relationship/add-users-list-provider.react.js';
import Modal from '../../modal.react.js';
type Props = {
@@ -64,16 +68,14 @@
const { parentThreadInfo, onClose } = props;
const { uiName: parentThreadName } = useResolvedThreadInfo(parentThreadInfo);
+ const { pendingUsersToAdd } = useAddUsersListContext();
+
const [activeStep, setActiveStep] = React.useState<Steps>('settings');
const [channelName, setChannelName] = React.useState<string>('');
const [visibilityType, setVisibilityType] =
React.useState<VisibilityType>('open');
const [announcement, setAnnouncement] = React.useState<boolean>(false);
- const [selectedUsers, setSelectedUsers] = React.useState<
- $ReadOnlySet<string>,
- >(new Set());
- const [searchUserText, setSearchUserText] = React.useState<string>('');
const loadingState = useSelector(createSubchannelLoadingStatusSelector);
@@ -94,7 +96,7 @@
name: channelName,
type: threadType,
parentThreadID: parentThreadInfo.id,
- initialMemberIDs: Array.from(selectedUsers),
+ initialMemberIDs: Array.from(pendingUsersToAdd.keys()),
calendarQuery: query,
color: parentThreadInfo.color,
});
@@ -105,13 +107,14 @@
return null;
}
}, [
- parentThreadInfo,
- selectedUsers,
visibilityType,
announcement,
- callNewThread,
calendarQuery,
+ callNewThread,
channelName,
+ parentThreadInfo.id,
+ parentThreadInfo.color,
+ pendingUsersToAdd,
]);
const dispatchCreateSubchannel = React.useCallback(async () => {
@@ -157,18 +160,6 @@
[announcement],
);
- const toggleUserSelection = React.useCallback((userID: string) => {
- setSelectedUsers((users: $ReadOnlySet<string>) => {
- const newUsers = new Set(users);
- if (newUsers.has(userID)) {
- newUsers.delete(userID);
- } else {
- newUsers.add(userID);
- }
- return newUsers;
- });
- }, []);
-
const subchannelSettings = React.useMemo(
() => (
<SubchannelSettings
@@ -213,31 +204,22 @@
nextProps: {
content: 'Create',
loading: loadingState === 'loading',
- disabled: selectedUsers.size === 0,
+ disabled: pendingUsersToAdd.size === 0,
onClick: dispatchCreateSubchannel,
},
},
}),
- [channelName, dispatchCreateSubchannel, loadingState, selectedUsers],
+ [
+ channelName,
+ dispatchCreateSubchannel,
+ loadingState,
+ pendingUsersToAdd.size,
+ ],
);
const subchannelMembers = React.useMemo(
- () => (
- <SubchannelMembers
- parentThreadInfo={parentThreadInfo}
- selectedUsers={selectedUsers}
- searchText={searchUserText}
- setSearchText={setSearchUserText}
- toggleUserSelection={toggleUserSelection}
- />
- ),
- [
- selectedUsers,
- toggleUserSelection,
- parentThreadInfo,
- searchUserText,
- setSearchUserText,
- ],
+ () => <SubchannelMembers parentThreadInfo={parentThreadInfo} />,
+ [parentThreadInfo],
);
const modalName =
@@ -273,4 +255,17 @@
);
}
-export default ComposeSubchannelModal;
+function ComposeSubchannelModalWrapper(props: Props): React.Node {
+ const composeSubchannelModalWrapper = React.useMemo(
+ () => (
+ <AddUsersListProvider>
+ <ComposeSubchannelModal {...props} />
+ </AddUsersListProvider>
+ ),
+ [props],
+ );
+
+ return composeSubchannelModalWrapper;
+}
+
+export default ComposeSubchannelModalWrapper;
diff --git a/web/modals/threads/create/steps/subchannel-members-list.react.js b/web/modals/threads/create/steps/subchannel-members-list.react.js
deleted file mode 100644
--- a/web/modals/threads/create/steps/subchannel-members-list.react.js
+++ /dev/null
@@ -1,108 +0,0 @@
-// @flow
-
-import * as React from 'react';
-
-import { useENSNames } from 'lib/hooks/ens-cache.js';
-import { stringForUser } from 'lib/shared/user-utils.js';
-import type {
- RelativeMemberInfo,
- ThreadInfo,
-} from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import type { UserListItem } from 'lib/types/user-types.js';
-
-import { useSelector } from '../../../../redux/redux-utils.js';
-import AddMembersList from '../../../components/add-members-list.react.js';
-
-type Props = {
- +searchText: string,
- +searchResult: $ReadOnlySet<string>,
- +communityThreadInfo: ThreadInfo,
- +parentThreadInfo: ThreadInfo,
- +selectedUsers: $ReadOnlySet<string>,
- +toggleUserSelection: (userID: string) => void,
-};
-
-function SubchannelMembersList(props: Props): React.Node {
- const {
- searchText,
- searchResult,
- communityThreadInfo,
- parentThreadInfo,
- selectedUsers,
- toggleUserSelection,
- } = props;
-
- const { name: communityName } = communityThreadInfo;
-
- const currentUserId = useSelector(state => state.currentUserInfo?.id);
-
- const parentMembersSet = React.useMemo(
- () => new Set(parentThreadInfo.members.map(user => user.id)),
- [parentThreadInfo],
- );
-
- const filterOutParentMembersWithENSNames = React.useCallback(
- (members: $ReadOnlyArray<RelativeMemberInfo>) =>
- members
- .filter(
- user =>
- user.id !== currentUserId &&
- (searchResult.has(user.id) || searchText.length === 0),
- )
- .map(user => ({ id: user.id, username: stringForUser(user) })),
- [currentUserId, searchResult, searchText.length],
- );
-
- const parentMemberListWithoutENSNames = React.useMemo(
- () => filterOutParentMembersWithENSNames(parentThreadInfo.members),
- [filterOutParentMembersWithENSNames, parentThreadInfo.members],
- );
-
- const parentMemberList = useENSNames<UserListItem>(
- parentMemberListWithoutENSNames,
- );
-
- const filterOutOtherMembersWithENSNames = React.useCallback(
- (members: $ReadOnlyArray<RelativeMemberInfo>) =>
- members
- .filter(
- user =>
- !parentMembersSet.has(user.id) &&
- user.id !== currentUserId &&
- (searchResult.has(user.id) || searchText.length === 0),
- )
- .map(user => ({ id: user.id, username: stringForUser(user) })),
- [currentUserId, parentMembersSet, searchResult, searchText.length],
- );
-
- const otherMemberListWithoutENSNames = React.useMemo(
- () => filterOutOtherMembersWithENSNames(communityThreadInfo.members),
- [communityThreadInfo.members, filterOutOtherMembersWithENSNames],
- );
-
- const otherMemberList = useENSNames<UserListItem>(
- otherMemberListWithoutENSNames,
- );
-
- const sortedGroupedUserList = React.useMemo(
- () =>
- [
- { header: 'Users in parent channel', userInfos: parentMemberList },
- {
- header: `All users in ${communityName ?? 'community'}`,
- userInfos: otherMemberList,
- },
- ].filter(item => item.userInfos.length),
- [parentMemberList, otherMemberList, communityName],
- );
-
- return (
- <AddMembersList
- switchUser={toggleUserSelection}
- pendingUsersToAdd={selectedUsers}
- sortedGroupedUsersList={sortedGroupedUserList}
- />
- );
-}
-
-export default SubchannelMembersList;
diff --git a/web/modals/threads/create/steps/subchannel-members.css b/web/modals/threads/create/steps/subchannel-members.css
--- a/web/modals/threads/create/steps/subchannel-members.css
+++ b/web/modals/threads/create/steps/subchannel-members.css
@@ -1,10 +1,5 @@
-.members {
- overflow-y: auto;
-}
-
.searchBar {
- background-color: var(--modal-bg);
position: sticky;
- padding: 2.5px 0;
top: 0;
+ z-index: 1;
}
diff --git a/web/modals/threads/create/steps/subchannel-members.react.js b/web/modals/threads/create/steps/subchannel-members.react.js
--- a/web/modals/threads/create/steps/subchannel-members.react.js
+++ b/web/modals/threads/create/steps/subchannel-members.react.js
@@ -2,60 +2,42 @@
import * as React from 'react';
-import { useUserSearchIndex } from 'lib/selectors/nav-selectors.js';
-import { useAncestorThreads } from 'lib/shared/ancestor-threads.js';
import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
-import MembersList from './subchannel-members-list.react.js';
import css from './subchannel-members.css';
import Search from '../../../../components/search.react.js';
+import AddUsersList from '../../../../settings/relationship/add-users-list.react.js';
+import { useSubchannelAddMembersListUserInfos } from '../../../../settings/relationship/add-users-utils.js';
type SubchannelMembersProps = {
+parentThreadInfo: ThreadInfo,
- +selectedUsers: $ReadOnlySet<string>,
- +searchText: string,
- +setSearchText: string => void,
- +toggleUserSelection: (userID: string) => void,
};
function SubchannelMembers(props: SubchannelMembersProps): React.Node {
- const {
- toggleUserSelection,
- searchText,
- setSearchText,
- parentThreadInfo,
- selectedUsers,
- } = props;
-
- const ancestorThreads = useAncestorThreads(parentThreadInfo);
-
- const communityThread = ancestorThreads[0] ?? parentThreadInfo;
-
- const userSearchIndex = useUserSearchIndex(communityThread.members);
- const searchResult = React.useMemo(
- () => new Set(userSearchIndex.getSearchResults(searchText)),
- [userSearchIndex, searchText],
- );
+ const { parentThreadInfo } = props;
+
+ const [searchUserText, setSearchUserText] = React.useState<string>('');
+
+ const { userInfos, sortedUsersWithENSNames } =
+ useSubchannelAddMembersListUserInfos({
+ parentThreadID: parentThreadInfo.id,
+ searchText: searchUserText,
+ });
return (
<>
<div className={css.searchBar}>
<Search
- searchText={searchText}
- onChangeText={setSearchText}
+ searchText={searchUserText}
+ onChangeText={setSearchUserText}
placeholder="Search"
/>
</div>
- <div className={css.members}>
- <MembersList
- communityThreadInfo={communityThread}
- parentThreadInfo={parentThreadInfo}
- selectedUsers={selectedUsers}
- searchResult={searchResult}
- searchText={searchText}
- toggleUserSelection={toggleUserSelection}
- />
- </div>
+ <AddUsersList
+ searchModeActive={searchUserText.length > 0}
+ userInfos={userInfos}
+ sortedUsersWithENSNames={sortedUsersWithENSNames}
+ />
</>
);
}
diff --git a/web/settings/relationship/add-users-utils.js b/web/settings/relationship/add-users-utils.js
--- a/web/settings/relationship/add-users-utils.js
+++ b/web/settings/relationship/add-users-utils.js
@@ -6,11 +6,13 @@
import { useUserSearchIndex } from 'lib/selectors/nav-selectors.js';
import { threadInfoSelector } from 'lib/selectors/thread-selectors.js';
import { userInfoSelectorForPotentialMembers } from 'lib/selectors/user-selectors.js';
+import { useAncestorThreads } from 'lib/shared/ancestor-threads.js';
import {
useSearchUsers,
usePotentialMemberItems,
} from 'lib/shared/search-utils.js';
import { threadActualMembers } from 'lib/shared/thread-utils.js';
+import type { RelativeMemberInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
import type { UserRelationshipStatus } from 'lib/types/relationship-types.js';
import type {
GlobalAccountUserInfo,
@@ -182,4 +184,78 @@
return result;
}
-export { useUserRelationshipUserInfos, useAddMembersListUserInfos };
+type UseSubchannelAddMembersListUserInfosParams = {
+ +parentThreadID: string,
+ +searchText: string,
+};
+
+function useSubchannelAddMembersListUserInfos(
+ params: UseSubchannelAddMembersListUserInfosParams,
+): {
+ +userInfos: {
+ [string]: RelativeMemberInfo,
+ },
+ +sortedUsersWithENSNames: $ReadOnlyArray<RelativeMemberInfo>,
+} {
+ const { parentThreadID, searchText } = params;
+
+ const { previouslySelectedUsers } = useAddUsersListContext();
+
+ const parentThreadInfo = useSelector(
+ state => threadInfoSelector(state)[parentThreadID],
+ );
+
+ const currentUserID = useSelector(state => state.currentUserInfo?.id);
+
+ const ancestorThreads = useAncestorThreads(parentThreadInfo);
+
+ const communityThreadInfo = ancestorThreads[0] ?? parentThreadInfo;
+
+ const userInfos = React.useMemo(() => {
+ const infos: { [string]: RelativeMemberInfo } = {};
+
+ for (const member of communityThreadInfo.members) {
+ infos[member.id] = member;
+ }
+
+ return infos;
+ }, [communityThreadInfo.members]);
+
+ const userSearchIndex = useUserSearchIndex(communityThreadInfo.members);
+
+ const searchResult = React.useMemo(
+ () => new Set(userSearchIndex.getSearchResults(searchText)),
+ [userSearchIndex, searchText],
+ );
+
+ const filterOutOtherMembersWithENSNames = React.useCallback(
+ (members: $ReadOnlyArray<RelativeMemberInfo>) =>
+ members.filter(
+ user =>
+ !previouslySelectedUsers.has(user.id) &&
+ user.id !== currentUserID &&
+ (searchResult.has(user.id) || searchText.length === 0),
+ ),
+ [currentUserID, previouslySelectedUsers, searchResult, searchText.length],
+ );
+
+ const otherMemberListWithoutENSNames = React.useMemo(
+ () => filterOutOtherMembersWithENSNames(communityThreadInfo.members),
+ [communityThreadInfo.members, filterOutOtherMembersWithENSNames],
+ );
+
+ const sortedUsersWithENSNames = useSortedENSResolvedUsers(
+ otherMemberListWithoutENSNames,
+ );
+
+ return {
+ userInfos,
+ sortedUsersWithENSNames,
+ };
+}
+
+export {
+ useUserRelationshipUserInfos,
+ useAddMembersListUserInfos,
+ useSubchannelAddMembersListUserInfos,
+};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 2, 9:25 PM (9 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5883168
Default Alt Text
D11065.1767389115.diff (13 KB)
Attached To
Mode
D11065: [web] use AddUsersList in SubchannelMembers
Attached
Detach File
Event Timeline
Log In to Comment