Page MenuHomePhabricator

D9430.id32230.diff
No OneTemporary

D9430.id32230.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,6 +2,8 @@
import * as React from 'react';
+import { useSelector } from './redux-utils.js';
+import { threadInfoSelector } from '../selectors/thread-selectors.js';
import {
type UserSurfacedPermissionOption,
userSurfacedPermissions,
@@ -9,6 +11,7 @@
} 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 { ThreadInfo, RelativeMemberInfo } from '../types/thread-types.js';
function useFilterPermissionOptionsByThreadType(
threadType: ThreadType,
@@ -74,8 +77,47 @@
}, [roleName, defaultRoleID, existingRoleID]);
}
+function useRoleNamesFromCommunityThreadInfo(
+ threadInfo: ThreadInfo,
+ memberInfos: $ReadOnlyArray<RelativeMemberInfo>,
+): $ReadOnlyMap<string, ?string> {
+ // 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].name : null,
+ ),
+ );
+ return roleMap;
+ }
+
+ const { members: memberInfosFromTopMostThreadInfo, roles } =
+ topMostThreadInfo;
+ memberInfosFromTopMostThreadInfo.forEach(memberInfo => {
+ roleMap.set(memberInfo.id, memberInfo.role && roles[memberInfo.role].name);
+ });
+ return roleMap;
+}
+
export {
useFilterPermissionOptionsByThreadType,
constructRoleDeletionMessagePrompt,
useRoleDeletableAndEditableStatus,
+ useRoleNamesFromCommunityThreadInfo,
};
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 { useRoleNamesFromCommunityThreadInfo } 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 roleNames = useRoleNamesFromCommunityThreadInfo(props.threadInfo, [
+ props.memberInfo,
+ ]);
+ const roleName = roleNames.get(props.memberInfo.id);
+
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 { useRoleNamesFromCommunityThreadInfo } from 'lib/utils/role-utils.js';
import ChangeMemberRoleModal from './change-member-role-modal.react.js';
import css from './members-modal.css';
@@ -41,8 +42,11 @@
const { memberInfo, threadInfo, setOpenMenu } = props;
const { pushModal } = useModalContext();
const userName = stringForUser(memberInfo);
- const { roles } = threadInfo;
- const { role } = memberInfo;
+
+ const roleNames = useRoleNamesFromCommunityThreadInfo(threadInfo, [
+ memberInfo,
+ ]);
+ const roleName = roleNames.get(memberInfo.id);
const onMenuChange = React.useCallback(
menuOpen => {
@@ -109,8 +113,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:06 AM (19 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2599261
Default Alt Text
D9430.id32230.diff (5 KB)

Event Timeline