diff --git a/lib/shared/thread-actions-utils.js b/lib/shared/thread-actions-utils.js --- a/lib/shared/thread-actions-utils.js +++ b/lib/shared/thread-actions-utils.js @@ -6,14 +6,12 @@ threadIsPending, threadOtherMembers, pendingThreadType, - userHasDeviceList, } from './thread-utils.js'; import { newThreadActionTypes, removeUsersFromThreadActionTypes, type RemoveUsersFromThreadInput, } from '../actions/thread-actions.js'; -import type { AuxUserInfos } from '../types/aux-user-types.js'; import type { CalendarQuery } from '../types/entry-types.js'; import type { RelativeMemberInfo, @@ -63,7 +61,6 @@ +handleError?: () => mixed, +calendarQuery: CalendarQuery, +usingOlmViaTunnelbrokerForDMs: boolean, - +auxUserInfos: AuxUserInfos, }; async function createRealThreadFromPendingThread({ @@ -75,7 +72,6 @@ viewerID, calendarQuery, usingOlmViaTunnelbrokerForDMs, - auxUserInfos, }: CreateRealThreadParameters): Promise<{ +threadID: string, +threadType: ThreadType, @@ -137,10 +133,7 @@ otherMemberIDs.length > 0, 'otherMemberIDs should not be empty for threads', ); - const allUsersSupportThickThreads = otherMemberIDs.every(memberID => - userHasDeviceList(memberID, auxUserInfos), - ); - if (threadTypeIsThick(threadInfo.type) && allUsersSupportThickThreads) { + if (threadTypeIsThick(threadInfo.type)) { const type = assertThickThreadType( pendingThreadType( otherMemberIDs.length, 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 @@ -1242,6 +1242,7 @@ type ExistingThreadInfoFinderParams = { +searching: boolean, +userInfoInputArray: $ReadOnlyArray, + +allUsersSupportThickThreads: boolean, }; type ExistingThreadInfoFinder = ( params: ExistingThreadInfoFinderParams, @@ -1330,7 +1331,7 @@ viewerID, threadType: pendingThreadType( userInfoInputArray.length, - 'thick', + params.allUsersSupportThickThreads ? 'thick' : 'thin', usingOlmViaTunnelbrokerForDMs, ), members: [loggedInUserInfo, ...userInfoInputArray], 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 @@ -8,6 +8,7 @@ import genesis from 'lib/facts/genesis.js'; import { useAllowOlmViaTunnelbrokerForDMs } from 'lib/hooks/flag-hooks.js'; +import { useUsersSupportThickThreads } from 'lib/hooks/user-identities-hooks.js'; import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; import { userInfoSelectorForPotentialMembers } from 'lib/selectors/user-selectors.js'; import { @@ -86,7 +87,7 @@ +updateUsernameInput: (text: string) => void, +userInfoInputArray: $ReadOnlyArray, +updateTagInput: (items: $ReadOnlyArray) => void, - +resolveToUser: (user: AccountUserInfo) => void, + +resolveToUser: (user: AccountUserInfo) => Promise, +userSearchResults: $ReadOnlyArray, +threadInfo: ThreadInfo, +genesisThreadInfo: ?ThreadInfo, @@ -283,14 +284,36 @@ const existingThreadInfoFinder = useExistingThreadInfoFinder(baseThreadInfo); + const checkUsersThickThreadSupport = useUsersSupportThickThreads(); + const [allUsersSupportThickThreads, setAllUsersSupportThickThreads] = + React.useState(false); + React.useEffect(() => { + void (async () => { + const usersSupportingThickThreads = await checkUsersThickThreadSupport( + userInfoInputArray.map(user => user.id), + ); + setAllUsersSupportThickThreads( + userInfoInputArray.every(userInfo => + usersSupportingThickThreads.has(userInfo.id), + ), + ); + })(); + }, [checkUsersThickThreadSupport, userInfoInputArray]); + const isSearching = !!props.route.params.searching; const threadInfo = React.useMemo( () => existingThreadInfoFinder({ searching: isSearching, userInfoInputArray, + allUsersSupportThickThreads, }), - [existingThreadInfoFinder, isSearching, userInfoInputArray], + [ + allUsersSupportThickThreads, + existingThreadInfoFinder, + isSearching, + userInfoInputArray, + ], ); invariant( threadInfo, @@ -351,10 +374,14 @@ ); const { editInputMessage } = inputState; const resolveToUser = React.useCallback( - (user: AccountUserInfo) => { + async (user: AccountUserInfo) => { + const usersSupportingThickThreads = await checkUsersThickThreadSupport([ + user.id, + ]); const resolvedThreadInfo = existingThreadInfoFinder({ searching: true, userInfoInputArray: [user], + allUsersSupportThickThreads: usersSupportingThickThreads.has(user.id), }); invariant( resolvedThreadInfo, @@ -364,7 +391,12 @@ setBaseThreadInfo(resolvedThreadInfo); setParams({ searching: false, threadInfo: resolvedThreadInfo }); }, - [existingThreadInfoFinder, editInputMessage, setParams], + [ + checkUsersThickThreadSupport, + editInputMessage, + existingThreadInfoFinder, + setParams, + ], ); const messageListData = useNativeMessageListData({ 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 @@ -18,7 +18,7 @@ +updateUsernameInput: (text: string) => void, +userInfoInputArray: $ReadOnlyArray, +updateTagInput: (items: $ReadOnlyArray) => void, - +resolveToUser: (user: AccountUserInfo) => void, + +resolveToUser: (user: AccountUserInfo) => Promise, +userSearchResults: $ReadOnlyArray, }; @@ -59,14 +59,14 @@ }, [userSearchResults, userInfoInputArray]); const onUserSelect = React.useCallback( - (userInfo: AccountUserInfo) => { + async (userInfo: AccountUserInfo) => { for (const existingUserInfo of userInfoInputArray) { if (userInfo.id === existingUserInfo.id) { return; } } if (nonFriends.has(userInfo.id)) { - resolveToUser(userInfo); + await resolveToUser(userInfo); return; } const newUserInfoInputArray = [...userInfoInputArray, userInfo]; 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 @@ -39,7 +39,7 @@ type BaseProps = { +userInfo: UserListItem, - +onSelect: (user: AccountUserInfo) => void, + +onSelect: (user: AccountUserInfo) => mixed, +textStyle?: TextStyle, }; type Props = { 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 @@ -12,7 +12,7 @@ type BaseProps = { +userInfos: $ReadOnlyArray, - +onSelect: (user: AccountUserInfo) => void, + +onSelect: (user: AccountUserInfo) => mixed, +itemTextStyle?: TextStyle, }; type Props = { diff --git a/native/input/input-state-container.react.js b/native/input/input-state-container.react.js --- a/native/input/input-state-container.react.js +++ b/native/input/input-state-container.react.js @@ -57,7 +57,6 @@ threadIsPending, threadIsPendingSidebar, } from 'lib/shared/thread-utils.js'; -import type { AuxUserInfos } from 'lib/types/aux-user-types'; import type { CalendarQuery } from 'lib/types/entry-types.js'; import type { Media, @@ -172,7 +171,6 @@ +newThickThread: (request: NewThickThreadRequest) => Promise, +textMessageCreationSideEffectsFunc: CreationSideEffectsFunc, +usingOlmViaTunnelbrokerForDMs: boolean, - +auxUserInfos: AuxUserInfos, }; type State = { +pendingUploads: PendingMultimediaUploads, @@ -577,7 +575,6 @@ viewerID: this.props.viewerID, calendarQuery, usingOlmViaTunnelbrokerForDMs: this.props.usingOlmViaTunnelbrokerForDMs, - auxUserInfos: this.props.auxUserInfos, }); this.pendingThreadCreations.set(threadInfo.id, threadCreationPromise); } @@ -1790,7 +1787,6 @@ const textMessageCreationSideEffectsFunc = useMessageCreationSideEffectsFunc(messageTypes.TEXT); const usingOlmViaTunnelbrokerForDMs = useAllowOlmViaTunnelbrokerForDMs(); - const auxUserInfos = useSelector(state => state.auxUserStore.auxUserInfos); return ( ); }); 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 @@ -9,6 +9,7 @@ import SWMansionIcon from 'lib/components/swmansion-icon.react.js'; import { useLoggedInUserInfo } from 'lib/hooks/account-hooks.js'; import { useENSNames } from 'lib/hooks/ens-cache.js'; +import { useUsersSupportThickThreads } from 'lib/hooks/user-identities-hooks.js'; import { usePotentialMemberItems, useSearchUsers, @@ -84,8 +85,10 @@ pendingPrivateThread.current, ); + const checkUsersThickThreadSupport = useUsersSupportThickThreads(); + const onSelectUserFromSearch = React.useCallback( - (userListItem: UserListItem) => { + async (userListItem: UserListItem) => { const { alert, notice, disabled, ...user } = userListItem; setUsernameInputText(''); if (!alert) { @@ -102,9 +105,15 @@ const newUserInfoInputArray = [ { id: userListItem.id, username: userListItem.username }, ]; + const usersSupportingThickThreads = await checkUsersThickThreadSupport( + newUserInfoInputArray.map(userInfo => userInfo.id), + ); const threadInfo = existingThreadInfoFinderForCreatingThread({ searching: true, userInfoInputArray: newUserInfoInputArray, + allUsersSupportThickThreads: newUserInfoInputArray.every(userInfo => + usersSupportingThickThreads.has(userInfo.id), + ), }); dispatch({ type: updateNavInfoActionType, @@ -119,6 +128,7 @@ } }, [ + checkUsersThickThreadSupport, dispatch, existingThreadInfoFinderForCreatingThread, pushModal, diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js --- a/web/input/input-state-container.react.js +++ b/web/input/input-state-container.react.js @@ -59,7 +59,6 @@ threadIsPending, threadIsPendingSidebar, } from 'lib/shared/thread-utils.js'; -import type { AuxUserInfos } from 'lib/types/aux-user-types.js'; import type { CalendarQuery } from 'lib/types/entry-types.js'; import type { MediaMission, @@ -172,7 +171,6 @@ +textMessageCreationSideEffectsFunc: CreationSideEffectsFunc, +identityContext: ?IdentityClientContextType, +usingOlmViaTunnelbrokerForDMs: boolean, - +auxUserInfos: AuxUserInfos, }; type WritableState = { pendingUploads: { @@ -612,7 +610,6 @@ viewerID: this.props.viewerID, calendarQuery, usingOlmViaTunnelbrokerForDMs: this.props.usingOlmViaTunnelbrokerForDMs, - auxUserInfos: this.props.auxUserInfos, }); this.pendingThreadCreations.set(threadInfo.id, threadCreationPromise); } @@ -1735,7 +1732,6 @@ const textMessageCreationSideEffectsFunc = useMessageCreationSideEffectsFunc(messageTypes.TEXT); const usingOlmViaTunnelbrokerForDMs = useAllowOlmViaTunnelbrokerForDMs(); - const auxUserInfos = useSelector(state => state.auxUserStore.auxUserInfos); return ( ); }); diff --git a/web/utils/thread-utils.js b/web/utils/thread-utils.js --- a/web/utils/thread-utils.js +++ b/web/utils/thread-utils.js @@ -5,6 +5,7 @@ import { useLoggedInUserInfo } from 'lib/hooks/account-hooks.js'; import { useAllowOlmViaTunnelbrokerForDMs } from 'lib/hooks/flag-hooks.js'; +import { useUsersSupportThickThreads } from 'lib/hooks/user-identities-hooks.js'; import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; import { userInfoSelectorForPotentialMembers } from 'lib/selectors/user-selectors.js'; import { @@ -87,6 +88,23 @@ return state.navInfo.pendingThread; }); const existingThreadInfoFinder = useExistingThreadInfoFinder(baseThreadInfo); + const checkUsersThickThreadSupport = useUsersSupportThickThreads(); + + const [allUsersSupportThickThreads, setAllUsersSupportThickThreads] = + React.useState(false); + React.useEffect(() => { + void (async () => { + const usersSupportingThickThreads = await checkUsersThickThreadSupport( + selectedUserInfos.map(user => user.id), + ); + setAllUsersSupportThickThreads( + selectedUserInfos.every(userInfo => + usersSupportingThickThreads.has(userInfo.id), + ), + ); + })(); + }, [checkUsersThickThreadSupport, selectedUserInfos]); + const threadInfo = React.useMemo(() => { if (isChatCreation) { if (selectedUserInfos.length === 0) { @@ -96,14 +114,17 @@ return existingThreadInfoFinderForCreatingThread({ searching: true, userInfoInputArray: selectedUserInfos, + allUsersSupportThickThreads, }); } return existingThreadInfoFinder({ searching: false, userInfoInputArray: [], + allUsersSupportThickThreads: true, }); }, [ + allUsersSupportThickThreads, existingThreadInfoFinder, existingThreadInfoFinderForCreatingThread, isChatCreation,