Changeset View
Changeset View
Standalone View
Standalone View
web/utils/thread-utils.js
- This file was added.
// @flow | |||||
import invariant from 'invariant'; | |||||
import * as React from 'react'; | |||||
import { useLoggedInUserInfo } from 'lib/hooks/account-hooks.js'; | |||||
import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; | |||||
import { userInfoSelectorForPotentialMembers } from 'lib/selectors/user-selectors.js'; | |||||
import { | |||||
createPendingThread, | |||||
useExistingThreadInfoFinder, | |||||
} from 'lib/shared/thread-utils.js'; | |||||
import { threadTypes, type ThreadInfo } from 'lib/types/thread-types.js'; | |||||
import type { AccountUserInfo } from 'lib/types/user-types.js'; | |||||
import { useSelector } from '../redux/redux-utils.js'; | |||||
type InfosForPendingThread = { | |||||
+isChatCreation: boolean, | |||||
+selectedUserIDs: ?$ReadOnlyArray<string>, | |||||
+otherUserInfos: { [id: string]: AccountUserInfo }, | |||||
+userInfoInputArray: $ReadOnlyArray<AccountUserInfo>, | |||||
}; | |||||
function useInfosForPendingThread(): InfosForPendingThread { | |||||
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], | |||||
); | |||||
return { | |||||
isChatCreation, | |||||
selectedUserIDs, | |||||
otherUserInfos, | |||||
userInfoInputArray, | |||||
}; | |||||
} | |||||
function useThreadInfoForPossiblyPendingThread( | |||||
activeChatThreadID: ?string, | |||||
): ?ThreadInfo { | |||||
const { isChatCreation, userInfoInputArray } = useInfosForPendingThread(); | |||||
const loggedInUserInfo = useLoggedInUserInfo(); | |||||
invariant(loggedInUserInfo, 'loggedInUserInfo should be set'); | |||||
const pendingPrivateThread = React.useRef( | |||||
createPendingThread({ | |||||
viewerID: loggedInUserInfo.id, | |||||
threadType: threadTypes.PRIVATE, | |||||
members: [loggedInUserInfo], | |||||
}), | |||||
); | |||||
const newThreadID = 'pending/new_thread'; | |||||
const pendingNewThread = React.useMemo( | |||||
() => ({ | |||||
...createPendingThread({ | |||||
viewerID: loggedInUserInfo.id, | |||||
threadType: threadTypes.PRIVATE, | |||||
members: [loggedInUserInfo], | |||||
name: 'New thread', | |||||
}), | |||||
id: newThreadID, | |||||
}), | |||||
[loggedInUserInfo], | |||||
); | |||||
const existingThreadInfoFinderForCreatingThread = useExistingThreadInfoFinder( | |||||
pendingPrivateThread.current, | |||||
); | |||||
const baseThreadInfo = useSelector(state => { | |||||
if (!activeChatThreadID) { | |||||
return null; | |||||
} | |||||
return ( | |||||
threadInfoSelector(state)[activeChatThreadID] ?? | |||||
state.navInfo.pendingThread | |||||
); | |||||
}); | |||||
const existingThreadInfoFinder = useExistingThreadInfoFinder(baseThreadInfo); | |||||
const threadInfo = React.useMemo(() => { | |||||
if (isChatCreation) { | |||||
if (userInfoInputArray.length === 0) { | |||||
return pendingNewThread; | |||||
} | |||||
return existingThreadInfoFinderForCreatingThread({ | |||||
searching: true, | |||||
userInfoInputArray, | |||||
}); | |||||
} | |||||
return existingThreadInfoFinder({ | |||||
searching: false, | |||||
userInfoInputArray: [], | |||||
}); | |||||
}, [ | |||||
existingThreadInfoFinder, | |||||
existingThreadInfoFinderForCreatingThread, | |||||
isChatCreation, | |||||
userInfoInputArray, | |||||
pendingNewThread, | |||||
]); | |||||
return threadInfo; | |||||
} | |||||
export { useThreadInfoForPossiblyPendingThread, useInfosForPendingThread }; |