Page MenuHomePhabricator

D4465.diff
No OneTemporary

D4465.diff

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
@@ -2,27 +2,57 @@
import classNames from 'classnames';
import invariant from 'invariant';
+import _isEqual from 'lodash/fp/isEqual';
import * as React from 'react';
import { useDrop } from 'react-dnd';
import { NativeTypes } from 'react-dnd-html5-backend';
+import { useDispatch } from 'react-redux';
import { threadInfoSelector } from 'lib/selectors/thread-selectors';
+import { userInfoSelectorForPotentialMembers } from 'lib/selectors/user-selectors';
import {
useWatchThread,
useExistingThreadInfoFinder,
+ createPendingThread,
} from 'lib/shared/thread-utils';
+import { threadTypes } from 'lib/types/thread-types';
+import type { AccountUserInfo } from 'lib/types/user-types';
import { InputStateContext } from '../input/input-state';
import { useSelector } from '../redux/redux-utils';
+import { updateNavInfoActionType } from '../types/nav-types';
import ChatInputBar from './chat-input-bar.react';
import css from './chat-message-list-container.css';
import ChatMessageList from './chat-message-list.react';
+import ChatThreadComposer from './chat-thread-composer.react';
import ThreadTopBar from './thread-top-bar.react';
function ChatMessageListContainer(): React.Node {
const activeChatThreadID = useSelector(
state => state.navInfo.activeChatThreadID,
);
+ const isChatCreation =
+ useSelector(state => state.navInfo.chatMode) === 'create';
+
+ const selectedUserIDs = useSelector(state => state.navInfo.selectedUserList);
+ const otherUserInfos = useSelector(userInfoSelectorForPotentialMembers);
+ const userInfoInputArray: $ReadOnlyArray<AccountUserInfo> = React.useMemo(
+ () => selectedUserIDs?.map(id => otherUserInfos[id]).filter(Boolean) ?? [],
+ [otherUserInfos, selectedUserIDs],
+ );
+ const viewerID = useSelector(state => state.currentUserInfo?.id);
+ invariant(viewerID, 'should be set');
+
+ const pendingPrivateThread = React.useRef(
+ createPendingThread({
+ viewerID,
+ threadType: threadTypes.PRIVATE,
+ }),
+ );
+ const existingThreadInfoFinderForCreatingThread = useExistingThreadInfoFinder(
+ pendingPrivateThread.current,
+ );
+
const baseThreadInfo = useSelector(state => {
if (!activeChatThreadID) {
return null;
@@ -33,16 +63,56 @@
);
});
const existingThreadInfoFinder = useExistingThreadInfoFinder(baseThreadInfo);
- const threadInfo = React.useMemo(
- () =>
- existingThreadInfoFinder({
- searching: false,
- userInfoInputArray: [],
- }),
- [existingThreadInfoFinder],
- );
+ const threadInfo = React.useMemo(() => {
+ if (isChatCreation) {
+ return existingThreadInfoFinderForCreatingThread({
+ searching: true,
+ userInfoInputArray,
+ });
+ }
+
+ return existingThreadInfoFinder({
+ searching: false,
+ userInfoInputArray: [],
+ });
+ }, [
+ existingThreadInfoFinder,
+ existingThreadInfoFinderForCreatingThread,
+ isChatCreation,
+ userInfoInputArray,
+ ]);
invariant(threadInfo, 'ThreadInfo should be set');
+ const dispatch = useDispatch();
+
+ // The effect removes members from list in navInfo
+ // if some of the user IDs don't exist in redux store
+ React.useEffect(() => {
+ if (!isChatCreation) {
+ return;
+ }
+ const existingSelectedUsersSet = new Set(
+ userInfoInputArray.map(userInfo => userInfo.id),
+ );
+ if (
+ selectedUserIDs?.length !== existingSelectedUsersSet.size ||
+ !_isEqual(new Set(selectedUserIDs), existingSelectedUsersSet)
+ ) {
+ dispatch({
+ type: updateNavInfoActionType,
+ payload: {
+ selectedUserList: Array.from(existingSelectedUsersSet),
+ },
+ });
+ }
+ }, [
+ dispatch,
+ isChatCreation,
+ otherUserInfos,
+ selectedUserIDs,
+ userInfoInputArray,
+ ]);
+
const inputState = React.useContext(InputStateContext);
invariant(inputState, 'InputState should be set');
const [{ isActive }, connectDropTarget] = useDrop({
@@ -97,11 +167,52 @@
};
}, [onPaste]);
+ const content = React.useMemo(() => {
+ const topBar = <ThreadTopBar threadInfo={threadInfo} />;
+ const messageListAndInput = (
+ <>
+ <ChatMessageList threadInfo={threadInfo} />
+ <ChatInputBar threadInfo={threadInfo} inputState={inputState} />
+ </>
+ );
+ if (!isChatCreation) {
+ return (
+ <>
+ {topBar}
+ {messageListAndInput}
+ </>
+ );
+ }
+ const chatUserSelection = (
+ <ChatThreadComposer
+ userInfoInputArray={userInfoInputArray}
+ otherUserInfos={otherUserInfos}
+ threadID={threadInfo.id}
+ inputState={inputState}
+ />
+ );
+
+ if (!userInfoInputArray.length) {
+ return chatUserSelection;
+ }
+ return (
+ <>
+ {topBar}
+ {chatUserSelection}
+ {messageListAndInput}
+ </>
+ );
+ }, [
+ inputState,
+ isChatCreation,
+ otherUserInfos,
+ threadInfo,
+ userInfoInputArray,
+ ]);
+
return connectDropTarget(
<div className={containerStyle} ref={containerRef}>
- <ThreadTopBar threadInfo={threadInfo} />
- <ChatMessageList threadInfo={threadInfo} />
- <ChatInputBar threadInfo={threadInfo} inputState={inputState} />
+ {content}
</div>,
);
}

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 26, 2:49 PM (20 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2585186
Default Alt Text
D4465.diff (5 KB)

Event Timeline