diff --git a/lib/types/user-types.js b/lib/types/user-types.js --- a/lib/types/user-types.js +++ b/lib/types/user-types.js @@ -131,11 +131,9 @@ }; export type UserListItem = { - +id: string, - +username: string, + ...AccountUserInfo, +disabled?: boolean, +notice?: string, +alertText?: string, +alertTitle?: string, - +avatar?: ?ClientAvatar, }; diff --git a/native/chat/compose-subchannel.react.js b/native/chat/compose-subchannel.react.js --- a/native/chat/compose-subchannel.react.js +++ b/native/chat/compose-subchannel.react.js @@ -249,13 +249,13 @@ ); const onUserSelect = React.useCallback( - (userID: string) => { - if (userInfoInputIDs.some(existingUserID => userID === existingUserID)) { + ({ id }: AccountUserInfo) => { + if (userInfoInputIDs.some(existingUserID => id === existingUserID)) { return; } setUserInfoInputArray(oldUserInfoInputArray => [ ...oldUserInfoInputArray, - otherUserInfos[userID], + otherUserInfos[id], ]); setUsernameInputText(''); }, diff --git a/native/chat/message-list-container.react.js b/native/chat/message-list-container.react.js --- a/native/chat/message-list-container.react.js +++ b/native/chat/message-list-container.react.js @@ -6,6 +6,10 @@ import * as React from 'react'; import { View, Text } from 'react-native'; +import { + searchUsers, + searchUsersActionTypes, +} from 'lib/actions/user-actions.js'; import genesis from 'lib/facts/genesis.js'; import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; import { @@ -18,7 +22,15 @@ pendingThreadType, } from 'lib/shared/thread-utils.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; -import type { AccountUserInfo, UserListItem } from 'lib/types/user-types.js'; +import type { + AccountUserInfo, + UserListItem, + GlobalAccountUserInfo, +} from 'lib/types/user-types.js'; +import { + useServerCall, + useDispatchActionPromise, +} from 'lib/utils/action-utils.js'; import { type MessagesMeasurer, useHeightMeasurer } from './chat-context.js'; import { ChatInputBar } from './chat-input-bar.react.js'; @@ -58,7 +70,6 @@ +userInfoInputArray: $ReadOnlyArray, +updateTagInput: (items: $ReadOnlyArray) => void, +resolveToUser: (user: AccountUserInfo) => void, - +otherUserInfos: { [id: string]: AccountUserInfo }, +userSearchResults: $ReadOnlyArray, +threadInfo: ThreadInfo, +genesisThreadInfo: ?ThreadInfo, @@ -154,7 +165,6 @@ userInfoInputArray={userInfoInputArray} updateTagInput={this.props.updateTagInput} resolveToUser={this.props.resolveToUser} - otherUserInfos={this.props.otherUserInfos} userSearchResults={this.props.userSearchResults} /> @@ -249,17 +259,51 @@ const otherUserInfos = useSelector(userInfoSelectorForPotentialMembers); const userSearchIndex = useSelector(userSearchIndexForPotentialMembers); - const userSearchResults = React.useMemo( - () => - getPotentialMemberItems( - usernameInputText, - otherUserInfos, - userSearchIndex, - userInfoInputArray.map(userInfo => userInfo.id), - ), - [usernameInputText, otherUserInfos, userSearchIndex, userInfoInputArray], + + const currentUserID = useSelector( + state => state.currentUserInfo && state.currentUserInfo.id, ); + const [serverSearchResults, setServerSearchResults] = React.useState< + $ReadOnlyArray, + >([]); + const callSearchUsers = useServerCall(searchUsers); + const dispatchActionPromise = useDispatchActionPromise(); + React.useEffect(() => { + const searchUsersPromise = (async () => { + if (usernameInputText.length === 0) { + setServerSearchResults([]); + } else { + const { userInfos } = await callSearchUsers(usernameInputText); + setServerSearchResults( + userInfos.filter(({ id }) => id !== currentUserID), + ); + } + })(); + dispatchActionPromise(searchUsersActionTypes, searchUsersPromise); + }, [ + callSearchUsers, + currentUserID, + dispatchActionPromise, + usernameInputText, + ]); + + const userSearchResults = React.useMemo(() => { + return getPotentialMemberItems( + usernameInputText, + otherUserInfos, + userSearchIndex, + userInfoInputArray.map(userInfo => userInfo.id), + serverSearchResults, + ); + }, [ + usernameInputText, + otherUserInfos, + userSearchIndex, + userInfoInputArray, + serverSearchResults, + ]); + const [baseThreadInfo, setBaseThreadInfo] = React.useState( props.route.params.threadInfo, ); @@ -421,7 +465,6 @@ userInfoInputArray={userInfoInputArray} updateTagInput={updateTagInput} resolveToUser={resolveToUser} - otherUserInfos={otherUserInfos} userSearchResults={userSearchResults} threadInfo={threadInfo} genesisThreadInfo={genesisThreadInfo} diff --git a/native/chat/message-list-thread-search.react.js b/native/chat/message-list-thread-search.react.js --- a/native/chat/message-list-thread-search.react.js +++ b/native/chat/message-list-thread-search.react.js @@ -19,7 +19,6 @@ +userInfoInputArray: $ReadOnlyArray, +updateTagInput: (items: $ReadOnlyArray) => void, +resolveToUser: (user: AccountUserInfo) => void, - +otherUserInfos: { [id: string]: AccountUserInfo }, +userSearchResults: $ReadOnlyArray, }; @@ -36,7 +35,6 @@ userInfoInputArray, updateTagInput, resolveToUser, - otherUserInfos, userSearchResults, }) { const styles = useStyles(unboundStyles); @@ -61,14 +59,13 @@ }, [userSearchResults, userInfoInputArray]); const onUserSelect = React.useCallback( - (userID: string) => { + (userInfo: AccountUserInfo) => { for (const existingUserInfo of userInfoInputArray) { - if (userID === existingUserInfo.id) { + if (userInfo.id === existingUserInfo.id) { return; } } - const userInfo = otherUserInfos[userID]; - if (nonFriends.has(userID)) { + if (nonFriends.has(userInfo.id)) { resolveToUser(userInfo); return; } @@ -79,7 +76,6 @@ [ userInfoInputArray, nonFriends, - otherUserInfos, updateTagInput, resolveToUser, updateUsernameInput, diff --git a/native/chat/settings/add-users-modal.react.js b/native/chat/settings/add-users-modal.react.js --- a/native/chat/settings/add-users-modal.react.js +++ b/native/chat/settings/add-users-modal.react.js @@ -211,16 +211,16 @@ ); const onUserSelect = React.useCallback( - (userID: string) => { + ({ id }: AccountUserInfo) => { if (isLoading) { return; } - if (userInfoInputIDs.some(existingUserID => userID === existingUserID)) { + if (userInfoInputIDs.some(existingUserID => id === existingUserID)) { return; } setUserInfoInputArray(oldUserInfoInputArray => [ ...oldUserInfoInputArray, - otherUserInfos[userID], + otherUserInfos[id], ]); setUsernameInputText(''); }, diff --git a/native/components/user-list-user.react.js b/native/components/user-list-user.react.js --- a/native/components/user-list-user.react.js +++ b/native/components/user-list-user.react.js @@ -3,7 +3,7 @@ import * as React from 'react'; import { Text, Platform, Alert } from 'react-native'; -import type { UserListItem } from 'lib/types/user-types.js'; +import type { UserListItem, AccountUserInfo } from 'lib/types/user-types.js'; import Button from './button.react.js'; import { SingleLine } from './single-line.react.js'; @@ -19,7 +19,7 @@ type BaseProps = { +userInfo: UserListItem, - +onSelect: (userID: string) => void, + +onSelect: (user: AccountUserInfo) => void, +textStyle?: TextStyle, }; type Props = { @@ -58,7 +58,9 @@ onSelect = () => { const { userInfo } = this.props; if (!userInfo.alertText) { - this.props.onSelect(userInfo.id); + const { alertText, alertTitle, notice, disabled, ...accountUserInfo } = + userInfo; + this.props.onSelect(accountUserInfo); return; } Alert.alert(userInfo.alertTitle, userInfo.alertText, [{ text: 'OK' }], { diff --git a/native/components/user-list.react.js b/native/components/user-list.react.js --- a/native/components/user-list.react.js +++ b/native/components/user-list.react.js @@ -4,7 +4,7 @@ import * as React from 'react'; import { FlatList } from 'react-native'; -import type { UserListItem } from 'lib/types/user-types.js'; +import type { UserListItem, AccountUserInfo } from 'lib/types/user-types.js'; import { UserListUser, getUserListItemHeight } from './user-list-user.react.js'; import { type IndicatorStyle, useIndicatorStyle } from '../themes/colors.js'; @@ -12,7 +12,7 @@ type BaseProps = { +userInfos: $ReadOnlyArray, - +onSelect: (userID: string) => void, + +onSelect: (user: AccountUserInfo) => void, +itemTextStyle?: TextStyle, }; type Props = {