Changeset View
Changeset View
Standalone View
Standalone View
web/chat/chat-message-list-container.react.js
Show All 32 Lines | type Props = { | ||||
+activeChatThreadID: string, | +activeChatThreadID: string, | ||||
}; | }; | ||||
function ChatMessageListContainer(props: Props): React.Node { | function ChatMessageListContainer(props: Props): React.Node { | ||||
const { activeChatThreadID } = props; | const { activeChatThreadID } = props; | ||||
const isChatCreation = | const isChatCreation = | ||||
useSelector(state => state.navInfo.chatMode) === 'create'; | useSelector(state => state.navInfo.chatMode) === 'create'; | ||||
const selectedUserIDs = useSelector(state => state.navInfo.selectedUserList); | const selectedUserIDs = useSelector( | ||||
state => state.navInfo.selectedUserList ?? [], | |||||
); | |||||
const otherUserInfos = useSelector(userInfoSelectorForPotentialMembers); | const otherUserInfos = useSelector(userInfoSelectorForPotentialMembers); | ||||
const userInfoInputArray: $ReadOnlyArray<AccountUserInfo> = React.useMemo( | const [userInfoInputArray, setUserInfoInputArray] = React.useState(() => | ||||
() => selectedUserIDs?.map(id => otherUserInfos[id]).filter(Boolean) ?? [], | selectedUserIDs.map(id => otherUserInfos[id]).filter(Boolean), | ||||
[otherUserInfos, selectedUserIDs], | |||||
); | ); | ||||
React.useEffect(() => { | |||||
if (!isChatCreation) { | |||||
setUserInfoInputArray([]); | |||||
} | |||||
}, [isChatCreation]); | |||||
const loggedInUserInfo = useLoggedInUserInfo(); | const loggedInUserInfo = useLoggedInUserInfo(); | ||||
invariant(loggedInUserInfo, 'loggedInUserInfo should be set'); | invariant(loggedInUserInfo, 'loggedInUserInfo should be set'); | ||||
const pendingPrivateThread = React.useRef( | const pendingPrivateThread = React.useRef( | ||||
createPendingThread({ | createPendingThread({ | ||||
viewerID: loggedInUserInfo.id, | viewerID: loggedInUserInfo.id, | ||||
threadType: threadTypes.PRIVATE, | threadType: threadTypes.PRIVATE, | ||||
members: [loggedInUserInfo], | members: [loggedInUserInfo], | ||||
}), | }), | ||||
); | ); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | const threadInfo = React.useMemo(() => { | ||||
existingThreadInfoFinderForCreatingThread, | existingThreadInfoFinderForCreatingThread, | ||||
isChatCreation, | isChatCreation, | ||||
userInfoInputArray, | userInfoInputArray, | ||||
pendingNewThread, | pendingNewThread, | ||||
]); | ]); | ||||
invariant(threadInfo, 'ThreadInfo should be set'); | invariant(threadInfo, 'ThreadInfo should be set'); | ||||
const dispatch = useDispatch(); | 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(() => { | React.useEffect(() => { | ||||
if (!isChatCreation) { | if (isChatCreation) { | ||||
return; | let payload = {}; | ||||
} | |||||
const existingSelectedUsersSet = new Set( | const newSelectedUserIDs = userInfoInputArray.map(user => user.id); | ||||
userInfoInputArray.map(userInfo => userInfo.id), | if (!_isEqual(new Set(selectedUserIDs), new Set(newSelectedUserIDs))) { | ||||
); | payload = { | ||||
if ( | ...payload, | ||||
selectedUserIDs?.length !== existingSelectedUsersSet.size || | selectedUserList: newSelectedUserIDs, | ||||
!_isEqual(new Set(selectedUserIDs), existingSelectedUsersSet) | }; | ||||
) { | |||||
dispatch({ | |||||
type: updateNavInfoActionType, | |||||
payload: { | |||||
selectedUserList: Array.from(existingSelectedUsersSet), | |||||
}, | |||||
}); | |||||
} | } | ||||
}, [ | |||||
dispatch, | |||||
isChatCreation, | |||||
otherUserInfos, | |||||
selectedUserIDs, | |||||
userInfoInputArray, | |||||
]); | |||||
React.useEffect(() => { | if (activeChatThreadID !== threadInfo?.id) { | ||||
if (isChatCreation && activeChatThreadID !== threadInfo?.id) { | payload = { | ||||
let payload = { | ...payload, | ||||
activeChatThreadID: threadInfo?.id, | activeChatThreadID: threadInfo?.id, | ||||
}; | }; | ||||
if (threadIsPending(threadInfo?.id)) { | if (threadIsPending(threadInfo?.id)) { | ||||
payload = { | payload = { | ||||
...payload, | ...payload, | ||||
pendingThread: threadInfo, | pendingThread: threadInfo, | ||||
}; | }; | ||||
} | } | ||||
} | |||||
dispatch({ | dispatch({ | ||||
type: updateNavInfoActionType, | type: updateNavInfoActionType, | ||||
payload, | payload, | ||||
}); | }); | ||||
} | } | ||||
}, [activeChatThreadID, dispatch, isChatCreation, threadInfo]); | }, [ | ||||
activeChatThreadID, | |||||
dispatch, | |||||
isChatCreation, | |||||
selectedUserIDs, | |||||
threadInfo, | |||||
userInfoInputArray, | |||||
]); | |||||
const inputState = React.useContext(InputStateContext); | const inputState = React.useContext(InputStateContext); | ||||
invariant(inputState, 'InputState should be set'); | invariant(inputState, 'InputState should be set'); | ||||
const [{ isActive }, connectDropTarget] = useDrop({ | const [{ isActive }, connectDropTarget] = useDrop({ | ||||
accept: NativeTypes.FILE, | accept: NativeTypes.FILE, | ||||
drop: item => { | drop: item => { | ||||
const { files } = item; | const { files } = item; | ||||
if (inputState && files.length > 0) { | if (inputState && files.length > 0) { | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | if (!isChatCreation) { | ||||
{topBar} | {topBar} | ||||
{messageListAndInput} | {messageListAndInput} | ||||
</> | </> | ||||
); | ); | ||||
} | } | ||||
const chatUserSelection = ( | const chatUserSelection = ( | ||||
<ChatThreadComposer | <ChatThreadComposer | ||||
userInfoInputArray={userInfoInputArray} | userInfoInputArray={userInfoInputArray} | ||||
setUserInfoInputArray={setUserInfoInputArray} | |||||
otherUserInfos={otherUserInfos} | otherUserInfos={otherUserInfos} | ||||
threadID={threadInfo.id} | threadID={threadInfo.id} | ||||
inputState={inputState} | inputState={inputState} | ||||
/> | /> | ||||
); | ); | ||||
if (!userInfoInputArray.length) { | if (!userInfoInputArray.length) { | ||||
return chatUserSelection; | return chatUserSelection; | ||||
Show All 24 Lines |