Page MenuHomePhabricator

D9430.id32270.diff
No OneTemporary

D9430.id32270.diff

diff --git a/lib/utils/role-utils.js b/lib/utils/role-utils.js
--- a/lib/utils/role-utils.js
+++ b/lib/utils/role-utils.js
@@ -2,13 +2,19 @@
import * as React from 'react';
+import { useSelector } from './redux-utils.js';
+import { threadInfoSelector } from '../selectors/thread-selectors.js';
import {
type UserSurfacedPermissionOption,
userSurfacedPermissions,
userSurfacedPermissionOptions,
} from '../types/thread-permission-types.js';
-import type { ThreadType } from '../types/thread-types-enum.js';
-import { threadTypes } from '../types/thread-types-enum.js';
+import { type ThreadType, threadTypes } from '../types/thread-types-enum.js';
+import type {
+ ThreadInfo,
+ RelativeMemberInfo,
+ RoleInfo,
+} from '../types/thread-types.js';
function useFilterPermissionOptionsByThreadType(
threadType: ThreadType,
@@ -74,8 +80,47 @@
}, [roleName, defaultRoleID, existingRoleID]);
}
+function useRolesFromCommunityThreadInfo(
+ threadInfo: ThreadInfo,
+ memberInfos: $ReadOnlyArray<RelativeMemberInfo>,
+): $ReadOnlyMap<string, ?RoleInfo> {
+ // Our in-code system has chat-specific roles, while the
+ // user-surfaced system has roles only for communities. We retrieve roles
+ // from the top-level community thread for accuracy, with a rare fallback
+ // for potential issues reading memberInfos, primarily in GENESIS threads.
+ // The special case is GENESIS threads, since per prior discussion
+ // (see context: https://linear.app/comm/issue/ENG-4077/), we don't really
+ // support roles for it. Also with GENESIS, the list of members are not
+ // populated in the community root. So in this case to prevent crashing, we
+ // should just return the role name from the current thread info.
+ const { community } = threadInfo;
+ const communityThreadInfo = useSelector(state =>
+ community ? threadInfoSelector(state)[community] : null,
+ );
+ const topMostThreadInfo = communityThreadInfo || threadInfo;
+ const roleMap = new Map();
+
+ if (topMostThreadInfo.type === threadTypes.GENESIS) {
+ memberInfos.forEach(memberInfo =>
+ roleMap.set(
+ memberInfo.id,
+ memberInfo.role ? threadInfo.roles[memberInfo.role] : null,
+ ),
+ );
+ return roleMap;
+ }
+
+ const { members: memberInfosFromTopMostThreadInfo, roles } =
+ topMostThreadInfo;
+ memberInfosFromTopMostThreadInfo.forEach(memberInfo => {
+ roleMap.set(memberInfo.id, memberInfo.role ? roles[memberInfo.role] : null);
+ });
+ return roleMap;
+}
+
export {
useFilterPermissionOptionsByThreadType,
constructRoleDeletionMessagePrompt,
useRoleDeletableAndEditableStatus,
+ useRolesFromCommunityThreadInfo,
};
diff --git a/native/chat/settings/thread-settings-member.react.js b/native/chat/settings/thread-settings-member.react.js
--- a/native/chat/settings/thread-settings-member.react.js
+++ b/native/chat/settings/thread-settings-member.react.js
@@ -23,6 +23,7 @@
type ThreadInfo,
type RelativeMemberInfo,
} from 'lib/types/thread-types.js';
+import { useRolesFromCommunityThreadInfo } from 'lib/utils/role-utils.js';
import type { ThreadSettingsNavigate } from './thread-settings.react.js';
import UserAvatar from '../../avatars/user-avatar.react.js';
@@ -55,6 +56,7 @@
type Props = {
...BaseProps,
// Redux state
+ +roleName: ?string,
+removeUserLoadingStatus: LoadingStatus,
+changeRoleLoadingStatus: LoadingStatus,
+colors: Colors,
@@ -116,14 +118,10 @@
);
}
- const roleName =
- this.props.memberInfo.role &&
- this.props.threadInfo.roles[this.props.memberInfo.role].name;
-
const roleInfo = (
<View style={this.props.styles.row}>
<Text style={this.props.styles.role} numberOfLines={1}>
- {roleName}
+ {this.props.roleName}
</Text>
</View>
);
@@ -280,10 +278,16 @@
const navigateToUserProfileBottomSheet =
useNavigateToUserProfileBottomSheet();
+ const roles = useRolesFromCommunityThreadInfo(props.threadInfo, [
+ props.memberInfo,
+ ]);
+ const roleName = roles.get(props.memberInfo.id)?.name;
+
return (
<ThreadSettingsMember
{...props}
memberInfo={memberInfo}
+ roleName={roleName}
removeUserLoadingStatus={removeUserLoadingStatus}
changeRoleLoadingStatus={changeRoleLoadingStatus}
colors={colors}
diff --git a/web/modals/threads/members/member.react.js b/web/modals/threads/members/member.react.js
--- a/web/modals/threads/members/member.react.js
+++ b/web/modals/threads/members/member.react.js
@@ -19,6 +19,7 @@
useDispatchActionPromise,
useServerCall,
} from 'lib/utils/action-utils.js';
+import { useRolesFromCommunityThreadInfo } from 'lib/utils/role-utils.js';
import ChangeMemberRoleModal from './change-member-role-modal.react.js';
import css from './members-modal.css';
@@ -41,8 +42,9 @@
const { memberInfo, threadInfo, setOpenMenu } = props;
const { pushModal } = useModalContext();
const userName = stringForUser(memberInfo);
- const { roles } = threadInfo;
- const { role } = memberInfo;
+
+ const roles = useRolesFromCommunityThreadInfo(threadInfo, [memberInfo]);
+ const roleName = roles.get(memberInfo.id)?.name;
const onMenuChange = React.useCallback(
menuOpen => {
@@ -109,8 +111,6 @@
[],
);
- const roleName = role && roles[role].name;
-
const label = React.useMemo(
() => <Label variant="grey">{roleName}</Label>,
[roleName],

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 30, 3:15 AM (19 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2599083
Default Alt Text
D9430.id32270.diff (5 KB)

Event Timeline