diff --git a/lib/shared/search-utils.js b/lib/shared/search-utils.js --- a/lib/shared/search-utils.js +++ b/lib/shared/search-utils.js @@ -129,43 +129,51 @@ relationshipStatus, ...result }) => { - let notice, alertText, alertTitle; + let notice, alert; const username = result.username; if (blockedRelationshipsStatuses.has(relationshipStatus)) { notice = 'user is blocked'; - alertTitle = 'User is blocked'; - alertText = - `Before you add ${username} to this chat, ` + - 'you’ll need to unblock them. You can do this from the Block List ' + - 'in the Profile tab.'; + alert = { + title: 'User is blocked', + text: + `Before you add ${username} to this chat, ` + + 'you’ll need to unblock them. You can do this from the Block List ' + + 'in the Profile tab.', + }; } else if (!isMemberOfContainingThread && containingThreadInfo) { if (threadType !== threadTypes.SIDEBAR) { notice = 'not in community'; - alertTitle = 'Not in community'; - alertText = 'You can only add members of the community to this chat'; + alert = { + title: 'Not in community', + text: 'You can only add members of the community to this chat', + }; } else { notice = 'not in parent chat'; - alertTitle = 'Not in parent chat'; - alertText = 'You can only add members of the parent chat to a thread'; + alert = { + title: 'Not in parent chat', + text: 'You can only add members of the parent chat to a thread', + }; } } else if ( !containingThreadInfo && relationshipStatus !== userRelationshipStatus.FRIEND ) { notice = notFriendNotice; - alertTitle = 'Not a friend'; - alertText = - `Before you add ${username} to this chat, ` + - 'you’ll need to send them a friend request. ' + - 'You can do this from the Friend List in the Profile tab.'; + alert = { + title: 'Not a friend', + text: + `Before you add ${username} to this chat, ` + + 'you’ll need to send them a friend request. ' + + 'You can do this from the Friend List in the Profile tab.', + }; } else if (parentThreadInfo && !isMemberOfParentThread) { notice = 'not in parent chat'; } if (notice) { result = { ...result, notice }; } - if (alertTitle) { - result = { ...result, alertTitle, alertText }; + if (alert) { + result = { ...result, alert }; } return result; }, diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js --- a/lib/shared/thread-utils.js +++ b/lib/shared/thread-utils.js @@ -1027,7 +1027,7 @@ +searching: boolean, +userInfoInputArray: $ReadOnlyArray, }; -type ExistingThreadInfoFinder = ( +export type ExistingThreadInfoFinder = ( params: ExistingThreadInfoFinderParams, ) => ?ThreadInfo; function useExistingThreadInfoFinder( 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 @@ -71,6 +71,8 @@ +username: string, +disabled?: boolean, +notice?: string, - +alertText?: string, - +alertTitle?: string, + +alert?: { + title: string, + text: string, + }, }; 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 @@ -53,7 +53,7 @@ continue; } nonFriendsSet.add(searchResult.id); - const { alertText, alertTitle, ...rest } = searchResult; + const { alert, ...rest } = searchResult; userListItemsArr.push(rest); } return [userListItemsArr, nonFriendsSet]; 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 @@ -54,11 +54,11 @@ onSelect = () => { const { userInfo } = this.props; - if (!userInfo.alertText) { + if (!userInfo.alert) { this.props.onSelect(userInfo.id); return; } - Alert.alert(userInfo.alertTitle, userInfo.alertText, [{ text: 'OK' }], { + Alert.alert(userInfo.alert?.title, userInfo.alert?.text, [{ text: 'OK' }], { cancelable: true, }); }; diff --git a/web/chat/chat-message-list-container.react.js b/web/chat/chat-message-list-container.react.js --- a/web/chat/chat-message-list-container.react.js +++ b/web/chat/chat-message-list-container.react.js @@ -226,6 +226,9 @@ ); }, [ + existingThreadInfoFinderForCreatingThread, inputState, isChatCreation, otherUserInfos, diff --git a/web/chat/chat-thread-composer.react.js b/web/chat/chat-thread-composer.react.js --- a/web/chat/chat-thread-composer.react.js +++ b/web/chat/chat-thread-composer.react.js @@ -5,12 +5,17 @@ import { useDispatch } from 'react-redux'; import { searchUsers } from 'lib/actions/user-actions'; +import { useModalContext } from 'lib/components/modal-provider.react'; import { filterPotentialMembers, userSearchIndexForPotentialMembers, } from 'lib/selectors/user-selectors'; -import { getPotentialMemberItems } from 'lib/shared/search-utils'; +import { + getPotentialMemberItems, + notFriendNotice, +} from 'lib/shared/search-utils'; import { threadIsPending } from 'lib/shared/thread-utils'; +import type { ExistingThreadInfoFinder } from 'lib/shared/thread-utils'; import type { SetState } from 'lib/types/hook-types'; import type { AccountUserInfo, @@ -23,6 +28,7 @@ import Label from '../components/label.react'; import Search from '../components/search.react'; import type { InputState } from '../input/input-state'; +import Alert from '../modals/alert.react'; import { updateNavInfoActionType } from '../redux/action-types'; import { useSelector } from '../redux/redux-utils'; import SWMansionIcon from '../SWMansionIcon.react'; @@ -31,6 +37,7 @@ type Props = { +userInfoInputArray: $ReadOnlyArray, +setUserInfoInputArray: SetState<$ReadOnlyArray>, + +existingThreadInfoFinderForCreatingThread: ExistingThreadInfoFinder, +otherUserInfos: { [id: string]: AccountUserInfo }, +threadID: string, +inputState: InputState, @@ -44,6 +51,7 @@ const { userInfoInputArray, setUserInfoInputArray, + existingThreadInfoFinderForCreatingThread, otherUserInfos, threadID, inputState, @@ -116,15 +124,49 @@ ], ); + const dispatch = useDispatch(); + const { pushModal } = useModalContext(); const onSelectUserFromSearch = React.useCallback( - (id: string, username: string) => { - setUserInfoInputArray(previousUserInfoInputArray => [ - ...previousUserInfoInputArray, - { id, username }, - ]); + (userItem: UserListItem) => { setUsernameInputText(''); + if (!userItem.alert) { + setUserInfoInputArray(previousUserInfoInputArray => [ + ...previousUserInfoInputArray, + { id: userItem.id, username: userItem.username }, + ]); + } else if ( + userItem.notice === notFriendNotice && + userInfoInputArray.length === 0 + ) { + const newUserInfoInputArray = [ + { id: userItem.id, username: userItem.username }, + ]; + setUserInfoInputArray(newUserInfoInputArray); + const threadInfo = existingThreadInfoFinderForCreatingThread({ + searching: true, + userInfoInputArray: newUserInfoInputArray, + }); + dispatch({ + type: updateNavInfoActionType, + payload: { + chatMode: 'view', + activeChatThreadID: threadInfo?.id, + pendingThread: threadInfo, + }, + }); + } else { + pushModal( + {userItem.alert?.text}, + ); + } }, - [setUserInfoInputArray], + [ + dispatch, + existingThreadInfoFinderForCreatingThread, + pushModal, + setUserInfoInputArray, + userInfoInputArray.length, + ], ); const onRemoveUserFromSelected = React.useCallback( @@ -150,16 +192,11 @@
  • ))} @@ -172,7 +209,6 @@ usernameInputText, ]); - const dispatch = useDispatch(); const hideSearch = React.useCallback( (threadBehavior: ActiveThreadBehavior = 'keep-active-thread') => { dispatch({ diff --git a/web/modals/components/add-members-item.react.js b/web/modals/components/add-members-item.react.js --- a/web/modals/components/add-members-item.react.js +++ b/web/modals/components/add-members-item.react.js @@ -16,7 +16,7 @@ function AddMemberItem(props: AddMembersItemProps): React.Node { const { userInfo, onClick, userAdded = false } = props; - const canBeAdded = !userInfo.alertText; + const canBeAdded = !userInfo.alert; const onClickCallback = React.useCallback(() => { if (!canBeAdded) { @@ -27,14 +27,14 @@ const action = React.useMemo(() => { if (!canBeAdded) { - return userInfo.alertTitle; + return userInfo.alert?.title; } if (userAdded) { return Remove; } else { return 'Add'; } - }, [canBeAdded, userAdded, userInfo.alertTitle]); + }, [canBeAdded, userAdded, userInfo.alert]); return (