Skip to content

Commit

Permalink
[lib] Update pending thread type based on selected members
Browse files Browse the repository at this point in the history
Summary:
Every time a list of selected users change check whether they support thick threads and update the type accordingly. Checking the support is an asynchronous operation which causes a lot of changes in other places.

https://linear.app/comm/issue/ENG-9393/update-pending-thread-type-based-on-selected-members

Depends on D13489

Test Plan:
Modify `useUserSupportThickThread` so that it returns false for some users. Check if the thread type is determined correctly on native and web.

Tested following scenarios

  # Searching for a user on native with useUserSupportThickThread modified to return false for some users
  # Searching for a user on native without modifications to useUserSupportThickThread
  # Searching for a user on web with useUserSupportThickThread modified to return false for some users
  # Searching for a user on web without modifications to useUserSupportThickThread
  # Composing a thread on native with useUserSupportThickThread modified to return false for some users
  # Composing a thread on native without modifications to useUserSupportThickThread
  # Composing a thread on web with useUserSupportThickThread modified to return false for some users
  # Composing a thread on web without modifications to useUserSupportThickThread

For each of these verified that the thread type is displayed correctly and that sending a message results in the creation of the correct thread type.

Reviewers: kamil, inka, ashoat

Reviewed By: kamil, ashoat

Subscribers: ashoat

Differential Revision: https://phab.comm.dev/D13519
  • Loading branch information
palys-swm committed Sep 30, 2024
1 parent ea2feac commit be3e464
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 29 deletions.
9 changes: 1 addition & 8 deletions lib/shared/thread-actions-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import {
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,
Expand Down Expand Up @@ -63,7 +61,6 @@ type CreateRealThreadParameters = {
+handleError?: () => mixed,
+calendarQuery: CalendarQuery,
+usingOlmViaTunnelbrokerForDMs: boolean,
+auxUserInfos: AuxUserInfos,
};

async function createRealThreadFromPendingThread({
Expand All @@ -75,7 +72,6 @@ async function createRealThreadFromPendingThread({
viewerID,
calendarQuery,
usingOlmViaTunnelbrokerForDMs,
auxUserInfos,
}: CreateRealThreadParameters): Promise<{
+threadID: string,
+threadType: ThreadType,
Expand Down Expand Up @@ -137,10 +133,7 @@ async function createRealThreadFromPendingThread({
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,
Expand Down
3 changes: 2 additions & 1 deletion lib/shared/thread-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,7 @@ function threadLabel(threadType: ThreadType): string {
type ExistingThreadInfoFinderParams = {
+searching: boolean,
+userInfoInputArray: $ReadOnlyArray<AccountUserInfo>,
+allUsersSupportThickThreads: boolean,
};
type ExistingThreadInfoFinder = (
params: ExistingThreadInfoFinderParams,
Expand Down Expand Up @@ -1330,7 +1331,7 @@ function useExistingThreadInfoFinder(
viewerID,
threadType: pendingThreadType(
userInfoInputArray.length,
'thick',
params.allUsersSupportThickThreads ? 'thick' : 'thin',
usingOlmViaTunnelbrokerForDMs,
),
members: [loggedInUserInfo, ...userInfoInputArray],
Expand Down
40 changes: 36 additions & 4 deletions native/chat/message-list-container.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Text, View } from 'react-native';

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 {
Expand Down Expand Up @@ -86,7 +87,7 @@ type Props = {
+updateUsernameInput: (text: string) => void,
+userInfoInputArray: $ReadOnlyArray<AccountUserInfo>,
+updateTagInput: (items: $ReadOnlyArray<AccountUserInfo>) => void,
+resolveToUser: (user: AccountUserInfo) => void,
+resolveToUser: (user: AccountUserInfo) => Promise<void>,
+userSearchResults: $ReadOnlyArray<UserListItem>,
+threadInfo: ThreadInfo,
+genesisThreadInfo: ?ThreadInfo,
Expand Down Expand Up @@ -283,14 +284,36 @@ const ConnectedMessageListContainer: React.ComponentType<BaseProps> =
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,
Expand Down Expand Up @@ -351,10 +374,14 @@ const ConnectedMessageListContainer: React.ComponentType<BaseProps> =
);
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,
Expand All @@ -364,7 +391,12 @@ const ConnectedMessageListContainer: React.ComponentType<BaseProps> =
setBaseThreadInfo(resolvedThreadInfo);
setParams({ searching: false, threadInfo: resolvedThreadInfo });
},
[existingThreadInfoFinder, editInputMessage, setParams],
[
checkUsersThickThreadSupport,
editInputMessage,
existingThreadInfoFinder,
setParams,
],
);

const messageListData = useNativeMessageListData({
Expand Down
6 changes: 3 additions & 3 deletions native/chat/message-list-thread-search.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type Props = {
+updateUsernameInput: (text: string) => void,
+userInfoInputArray: $ReadOnlyArray<AccountUserInfo>,
+updateTagInput: (items: $ReadOnlyArray<AccountUserInfo>) => void,
+resolveToUser: (user: AccountUserInfo) => void,
+resolveToUser: (user: AccountUserInfo) => Promise<void>,
+userSearchResults: $ReadOnlyArray<UserListItem>,
};

Expand Down Expand Up @@ -59,14 +59,14 @@ const MessageListThreadSearch: React.ComponentType<Props> = React.memo<Props>(
}, [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];
Expand Down
2 changes: 1 addition & 1 deletion native/components/user-list-user.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const unboundStyles = {

type BaseProps = {
+userInfo: UserListItem,
+onSelect: (user: AccountUserInfo) => void,
+onSelect: (user: AccountUserInfo) => mixed,
+textStyle?: TextStyle,
};
type Props = {
Expand Down
2 changes: 1 addition & 1 deletion native/components/user-list.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { TextStyle } from '../types/styles.js';

type BaseProps = {
+userInfos: $ReadOnlyArray<UserListItem>,
+onSelect: (user: AccountUserInfo) => void,
+onSelect: (user: AccountUserInfo) => mixed,
+itemTextStyle?: TextStyle,
};
type Props = {
Expand Down
5 changes: 0 additions & 5 deletions native/input/input-state-container.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ import {
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,
Expand Down Expand Up @@ -172,7 +171,6 @@ type Props = {
+newThickThread: (request: NewThickThreadRequest) => Promise<string>,
+textMessageCreationSideEffectsFunc: CreationSideEffectsFunc<RawTextMessageInfo>,
+usingOlmViaTunnelbrokerForDMs: boolean,
+auxUserInfos: AuxUserInfos,
};
type State = {
+pendingUploads: PendingMultimediaUploads,
Expand Down Expand Up @@ -577,7 +575,6 @@ class InputStateContainer extends React.PureComponent<Props, State> {
viewerID: this.props.viewerID,
calendarQuery,
usingOlmViaTunnelbrokerForDMs: this.props.usingOlmViaTunnelbrokerForDMs,
auxUserInfos: this.props.auxUserInfos,
});
this.pendingThreadCreations.set(threadInfo.id, threadCreationPromise);
}
Expand Down Expand Up @@ -1790,7 +1787,6 @@ const ConnectedInputStateContainer: React.ComponentType<BaseProps> =
const textMessageCreationSideEffectsFunc =
useMessageCreationSideEffectsFunc<RawTextMessageInfo>(messageTypes.TEXT);
const usingOlmViaTunnelbrokerForDMs = useAllowOlmViaTunnelbrokerForDMs();
const auxUserInfos = useSelector(state => state.auxUserStore.auxUserInfos);

return (
<InputStateContainer
Expand All @@ -1812,7 +1808,6 @@ const ConnectedInputStateContainer: React.ComponentType<BaseProps> =
staffCanSee={staffCanSee}
textMessageCreationSideEffectsFunc={textMessageCreationSideEffectsFunc}
usingOlmViaTunnelbrokerForDMs={usingOlmViaTunnelbrokerForDMs}
auxUserInfos={auxUserInfos}
/>
);
});
Expand Down
12 changes: 11 additions & 1 deletion web/chat/chat-thread-composer.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useModalContext } from 'lib/components/modal-provider.react.js';
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,
Expand Down Expand Up @@ -84,8 +85,10 @@ function ChatThreadComposer(props: Props): React.Node {
pendingPrivateThread.current,
);

const checkUsersThickThreadSupport = useUsersSupportThickThreads();

const onSelectUserFromSearch = React.useCallback(
(userListItem: UserListItem) => {
async (userListItem: UserListItem) => {
const { alert, notice, disabled, ...user } = userListItem;
setUsernameInputText('');
if (!alert) {
Expand All @@ -102,9 +105,15 @@ function ChatThreadComposer(props: Props): React.Node {
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,
Expand All @@ -119,6 +128,7 @@ function ChatThreadComposer(props: Props): React.Node {
}
},
[
checkUsersThickThreadSupport,
dispatch,
existingThreadInfoFinderForCreatingThread,
pushModal,
Expand Down
5 changes: 0 additions & 5 deletions web/input/input-state-container.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ import {
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,
Expand Down Expand Up @@ -172,7 +171,6 @@ type Props = {
+textMessageCreationSideEffectsFunc: CreationSideEffectsFunc<RawTextMessageInfo>,
+identityContext: ?IdentityClientContextType,
+usingOlmViaTunnelbrokerForDMs: boolean,
+auxUserInfos: AuxUserInfos,
};
type WritableState = {
pendingUploads: {
Expand Down Expand Up @@ -612,7 +610,6 @@ class InputStateContainer extends React.PureComponent<Props, State> {
viewerID: this.props.viewerID,
calendarQuery,
usingOlmViaTunnelbrokerForDMs: this.props.usingOlmViaTunnelbrokerForDMs,
auxUserInfos: this.props.auxUserInfos,
});
this.pendingThreadCreations.set(threadInfo.id, threadCreationPromise);
}
Expand Down Expand Up @@ -1735,7 +1732,6 @@ const ConnectedInputStateContainer: React.ComponentType<BaseProps> =
const textMessageCreationSideEffectsFunc =
useMessageCreationSideEffectsFunc<RawTextMessageInfo>(messageTypes.TEXT);
const usingOlmViaTunnelbrokerForDMs = useAllowOlmViaTunnelbrokerForDMs();
const auxUserInfos = useSelector(state => state.auxUserStore.auxUserInfos);

return (
<InputStateContainer
Expand All @@ -1762,7 +1758,6 @@ const ConnectedInputStateContainer: React.ComponentType<BaseProps> =
textMessageCreationSideEffectsFunc={textMessageCreationSideEffectsFunc}
identityContext={identityContext}
usingOlmViaTunnelbrokerForDMs={usingOlmViaTunnelbrokerForDMs}
auxUserInfos={auxUserInfos}
/>
);
});
Expand Down
21 changes: 21 additions & 0 deletions web/utils/thread-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as React from 'react';

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 {
Expand Down Expand Up @@ -87,6 +88,23 @@ function useThreadInfoForPossiblyPendingThread(
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) {
Expand All @@ -96,14 +114,17 @@ function useThreadInfoForPossiblyPendingThread(
return existingThreadInfoFinderForCreatingThread({
searching: true,
userInfoInputArray: selectedUserInfos,
allUsersSupportThickThreads,
});
}

return existingThreadInfoFinder({
searching: false,
userInfoInputArray: [],
allUsersSupportThickThreads: true,
});
}, [
allUsersSupportThickThreads,
existingThreadInfoFinder,
existingThreadInfoFinderForCreatingThread,
isChatCreation,
Expand Down

0 comments on commit be3e464

Please sign in to comment.