diff --git a/lib/utils/entity-helpers.js b/lib/utils/entity-helpers.js --- a/lib/utils/entity-helpers.js +++ b/lib/utils/entity-helpers.js @@ -44,6 +44,41 @@ ); } +function useResolvedOptionalThreadInfos( + threadInfos: ?$ReadOnlyArray, +): ?$ReadOnlyArray { + const entityText = React.useMemo(() => { + if (!threadInfos) { + return null; + } + return threadInfos.map(threadInfo => + ET.thread({ display: 'uiName', threadInfo }), + ); + }, [threadInfos]); + const withENSNames = useENSNamesForEntityText(entityText); + return React.useMemo(() => { + if (!threadInfos) { + return threadInfos; + } + invariant( + withENSNames, + 'useENSNamesForEntityText only returns falsey when passed falsey', + ); + return threadInfos.map((threadInfo, i) => { + if (typeof threadInfo.uiName === 'string') { + // Flow wants return { ...threadInfo, uiName: threadInfo.uiName } + // but that's wasteful and unneeded, so we any-cast here + return (threadInfo: any); + } + const resolvedThreadEntity = withENSNames[i]; + return { + ...threadInfo, + uiName: entityTextToRawString([resolvedThreadEntity]), + }; + }); + }, [threadInfos, withENSNames]); +} + function useResolvedThreadInfosObj(threadInfosObj: { +[id: string]: ThreadInfo, }): { +[id: string]: ResolvedThreadInfo } { @@ -66,8 +101,24 @@ return resolvedThreadInfo; } +function useResolvedOptionalThreadInfo( + threadInfo: ?ThreadInfo, +): ?ResolvedThreadInfo { + const resolutionInput = React.useMemo( + () => (threadInfo ? [threadInfo] : []), + [threadInfo], + ); + const [resolvedThreadInfo] = useResolvedThreadInfos(resolutionInput); + if (!threadInfo) { + return threadInfo; + } + return resolvedThreadInfo; +} + export { useResolvedThreadInfos, + useResolvedOptionalThreadInfos, useResolvedThreadInfosObj, useResolvedThreadInfo, + useResolvedOptionalThreadInfo, }; diff --git a/native/chat/settings/delete-thread.react.js b/native/chat/settings/delete-thread.react.js --- a/native/chat/settings/delete-thread.react.js +++ b/native/chat/settings/delete-thread.react.js @@ -19,12 +19,17 @@ import { threadInfoSelector } from 'lib/selectors/thread-selectors'; import { identifyInvalidatedThreads } from 'lib/shared/thread-utils'; import type { LoadingStatus } from 'lib/types/loading-types'; -import type { ThreadInfo, LeaveThreadPayload } from 'lib/types/thread-types'; +import type { + ThreadInfo, + ResolvedThreadInfo, + LeaveThreadPayload, +} from 'lib/types/thread-types'; import { useServerCall, useDispatchActionPromise, type DispatchActionPromise, } from 'lib/utils/action-utils'; +import { useResolvedThreadInfo } from 'lib/utils/entity-helpers'; import Button from '../../components/button.react'; import { clearThreadsActionType } from '../../navigation/action-types'; @@ -49,7 +54,7 @@ type Props = { ...BaseProps, // Redux state - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, +loadingStatus: LoadingStatus, +activeTheme: ?GlobalTheme, +colors: Colors, @@ -231,8 +236,8 @@ setParams({ threadInfo: reduxThreadInfo }); } }, [reduxThreadInfo, setParams]); - const threadInfo: ThreadInfo = - reduxThreadInfo ?? props.route.params.threadInfo; + const threadInfo = reduxThreadInfo ?? props.route.params.threadInfo; + const resolvedThreadInfo = useResolvedThreadInfo(threadInfo); const loadingStatus = useSelector(loadingStatusSelector); const activeTheme = useSelector(state => state.globalThemeInfo.activeTheme); @@ -250,7 +255,7 @@ return ( void) => void, +canChangeSettings: boolean, diff --git a/native/chat/settings/thread-settings.react.js b/native/chat/settings/thread-settings.react.js --- a/native/chat/settings/thread-settings.react.js +++ b/native/chat/settings/thread-settings.react.js @@ -31,11 +31,17 @@ import type { RelationshipButton } from 'lib/types/relationship-types'; import { type ThreadInfo, + type ResolvedThreadInfo, type RelativeMemberInfo, threadPermissions, threadTypes, } from 'lib/types/thread-types'; import type { UserInfos } from 'lib/types/user-types'; +import { + useResolvedThreadInfo, + useResolvedOptionalThreadInfo, + useResolvedOptionalThreadInfos, +} from 'lib/utils/entity-helpers'; import ThreadAncestors from '../../components/thread-ancestors.react'; import { @@ -113,14 +119,14 @@ | { +itemType: 'name', +key: string, - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, +nameEditValue: ?string, +canChangeSettings: boolean, } | { +itemType: 'color', +key: string, - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, +colorEditValue: string, +canChangeSettings: boolean, +navigate: ThreadSettingsNavigate, @@ -129,7 +135,7 @@ | { +itemType: 'description', +key: string, - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, +descriptionEditValue: ?string, +descriptionTextHeight: ?number, +canChangeSettings: boolean, @@ -137,23 +143,23 @@ | { +itemType: 'parent', +key: string, - +threadInfo: ThreadInfo, - +parentThreadInfo: ?ThreadInfo, + +threadInfo: ResolvedThreadInfo, + +parentThreadInfo: ?ResolvedThreadInfo, } | { +itemType: 'visibility', +key: string, - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, } | { +itemType: 'pushNotifs', +key: string, - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, } | { +itemType: 'homeNotifs', +key: string, - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, } | { +itemType: 'seeMore', @@ -163,7 +169,7 @@ | { +itemType: 'childThread', +key: string, - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, +firstListItem: boolean, +lastListItem: boolean, } @@ -175,7 +181,7 @@ +itemType: 'member', +key: string, +memberInfo: RelativeMemberInfo, - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, +canEdit: boolean, +navigate: ThreadSettingsNavigate, +firstListItem: boolean, @@ -190,14 +196,14 @@ | { +itemType: 'promoteSidebar' | 'leaveThread' | 'deleteThread', +key: string, - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, +navigate: ThreadSettingsNavigate, +buttonStyle: ViewStyle, } | { +itemType: 'editRelationship', +key: string, - +threadInfo: ThreadInfo, + +threadInfo: ResolvedThreadInfo, +navigate: ThreadSettingsNavigate, +buttonStyle: ViewStyle, +relationshipButton: RelationshipButton, @@ -212,9 +218,9 @@ // Redux state +userInfos: UserInfos, +viewerID: ?string, - +threadInfo: ThreadInfo, - +parentThreadInfo: ?ThreadInfo, - +childThreadInfos: ?$ReadOnlyArray, + +threadInfo: ResolvedThreadInfo, + +parentThreadInfo: ?ResolvedThreadInfo, + +childThreadInfos: ?$ReadOnlyArray, +somethingIsSaving: boolean, +styles: typeof unboundStyles, +indicatorStyle: IndicatorStyle, @@ -291,8 +297,8 @@ (propsAndState: PropsAndState) => propsAndState.navigation.navigate, (propsAndState: PropsAndState) => propsAndState.route.key, ( - threadInfo: ThreadInfo, - parentThreadInfo: ?ThreadInfo, + threadInfo: ResolvedThreadInfo, + parentThreadInfo: ?ResolvedThreadInfo, nameEditValue: ?string, colorEditValue: string, descriptionEditValue: ?string, @@ -420,9 +426,9 @@ (propsAndState: PropsAndState) => propsAndState.childThreadInfos, (propsAndState: PropsAndState) => propsAndState.numSubchannelsShowing, ( - threadInfo: ThreadInfo, + threadInfo: ResolvedThreadInfo, navigate: ThreadSettingsNavigate, - childThreads: ?$ReadOnlyArray, + childThreads: ?$ReadOnlyArray, numSubchannelsShowing: number, ) => { const listData: ChatSettingsItem[] = []; @@ -486,7 +492,7 @@ (propsAndState: PropsAndState) => propsAndState.numSidebarsShowing, ( navigate: ThreadSettingsNavigate, - childThreads: ?$ReadOnlyArray, + childThreads: ?$ReadOnlyArray, numSidebarsShowing: number, ) => { const listData: ChatSettingsItem[] = []; @@ -544,7 +550,7 @@ (propsAndState: PropsAndState) => propsAndState.numMembersShowing, (propsAndState: PropsAndState) => propsAndState.verticalBounds, ( - threadInfo: ThreadInfo, + threadInfo: ResolvedThreadInfo, canStartEditing: boolean, navigate: ThreadSettingsNavigate, routeKey: string, @@ -619,8 +625,8 @@ (propsAndState: PropsAndState) => propsAndState.userInfos, (propsAndState: PropsAndState) => propsAndState.viewerID, ( - threadInfo: ThreadInfo, - parentThreadInfo: ?ThreadInfo, + threadInfo: ResolvedThreadInfo, + parentThreadInfo: ?ResolvedThreadInfo, navigate: ThreadSettingsNavigate, styles: typeof unboundStyles, userInfos: UserInfos, @@ -1060,6 +1066,7 @@ }, [reduxThreadInfo, setParams]); const threadInfo: ThreadInfo = reduxThreadInfo ?? props.route.params.threadInfo; + const resolvedThreadInfo = useResolvedThreadInfo(threadInfo); React.useEffect(() => { if (threadInChatList(threadInfo)) { @@ -1075,10 +1082,16 @@ const parentThreadInfo: ?ThreadInfo = useSelector(state => parentThreadID ? threadInfoSelector(state)[parentThreadID] : null, ); + const resolvedParentThreadInfo = useResolvedOptionalThreadInfo( + parentThreadInfo, + ); const threadMembers = threadInfo.members; const boundChildThreadInfos = useSelector( state => childThreadInfos(state)[threadID], ); + const resolvedChildThreadInfos = useResolvedOptionalThreadInfos( + boundChildThreadInfos, + ); const boundSomethingIsSaving = useSelector(state => somethingIsSaving(state, threadMembers), ); @@ -1108,9 +1121,9 @@ {...props} userInfos={userInfos} viewerID={viewerID} - threadInfo={threadInfo} - parentThreadInfo={parentThreadInfo} - childThreadInfos={boundChildThreadInfos} + threadInfo={resolvedThreadInfo} + parentThreadInfo={resolvedParentThreadInfo} + childThreadInfos={resolvedChildThreadInfos} somethingIsSaving={boundSomethingIsSaving} styles={styles} indicatorStyle={indicatorStyle}