diff --git a/web/modals/threads/members/member.react.js b/web/modals/threads/members/member.react.js
index beacbc6ad..d09e8e4b0 100644
--- a/web/modals/threads/members/member.react.js
+++ b/web/modals/threads/members/member.react.js
@@ -1,144 +1,141 @@
// @flow
-import classNames from 'classnames';
import * as React from 'react';
import { removeUsersFromThread } from 'lib/actions/thread-actions.js';
import { useModalContext } from 'lib/components/modal-provider.react.js';
import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
import {
removeMemberFromThread,
getAvailableThreadMemberActions,
} from 'lib/shared/thread-utils.js';
import { stringForUser } from 'lib/shared/user-utils.js';
import type { SetState } from 'lib/types/hook-types.js';
import {
type RelativeMemberInfo,
type ThreadInfo,
} from 'lib/types/thread-types.js';
import {
useDispatchActionPromise,
useServerCall,
} from 'lib/utils/action-utils.js';
import ChangeMemberRoleModal from './change-member-role-modal.react.js';
import css from './members-modal.css';
import UserAvatar from '../../../avatars/user-avatar.react.js';
import CommIcon from '../../../CommIcon.react.js';
import Label from '../../../components/label.react.js';
import MenuItem from '../../../components/menu-item.react.js';
import Menu from '../../../components/menu.react.js';
+import { usePushUserProfileModal } from '../../user-profile/user-profile-utils.js';
const commIconComponent = ;
type Props = {
+memberInfo: RelativeMemberInfo,
+threadInfo: ThreadInfo,
+setOpenMenu: SetState,
- +isMenuOpen: boolean,
};
function ThreadMember(props: Props): React.Node {
- const { memberInfo, threadInfo, setOpenMenu, isMenuOpen } = props;
+ const { memberInfo, threadInfo, setOpenMenu } = props;
const { pushModal } = useModalContext();
const userName = stringForUser(memberInfo);
const { roles } = threadInfo;
const { role } = memberInfo;
const onMenuChange = React.useCallback(
menuOpen => {
if (menuOpen) {
setOpenMenu(() => memberInfo.id);
} else {
setOpenMenu(menu => (menu === memberInfo.id ? null : menu));
}
},
[memberInfo.id, setOpenMenu],
);
const dispatchActionPromise = useDispatchActionPromise();
const boundRemoveUsersFromThread = useServerCall(removeUsersFromThread);
const onClickRemoveUser = React.useCallback(
() =>
removeMemberFromThread(
threadInfo,
memberInfo,
dispatchActionPromise,
boundRemoveUsersFromThread,
),
[boundRemoveUsersFromThread, dispatchActionPromise, memberInfo, threadInfo],
);
const onClickChangeRole = React.useCallback(() => {
pushModal(
,
);
}, [memberInfo, pushModal, threadInfo]);
const menuItems = React.useMemo(
() =>
getAvailableThreadMemberActions(memberInfo, threadInfo).map(action => {
if (action === 'change_role') {
return (
);
}
if (action === 'remove_user') {
return (
);
}
return null;
}),
[memberInfo, onClickRemoveUser, onClickChangeRole, threadInfo],
);
const userSettingsIcon = React.useMemo(
() => ,
[],
);
const roleName = role && roles[role].name;
const label = React.useMemo(
() => ,
[roleName],
);
- const memberContainerClasses = classNames(css.memberContainer, {
- [css.memberContainerWithMenuOpen]: isMenuOpen,
- });
+ const pushUserProfileModal = usePushUserProfileModal(memberInfo.id);
return (
-
+
{userName}
{label}
);
}
export default ThreadMember;
diff --git a/web/modals/threads/members/members-list.react.js b/web/modals/threads/members/members-list.react.js
index 30a207073..e18ec50a0 100644
--- a/web/modals/threads/members/members-list.react.js
+++ b/web/modals/threads/members/members-list.react.js
@@ -1,82 +1,81 @@
// @flow
import classNames from 'classnames';
import _groupBy from 'lodash/fp/groupBy.js';
import _toPairs from 'lodash/fp/toPairs.js';
import * as React from 'react';
import { useENSNames } from 'lib/hooks/ens-cache.js';
import { stringForUser } from 'lib/shared/user-utils.js';
import {
type ThreadInfo,
type RelativeMemberInfo,
} from 'lib/types/thread-types.js';
import ThreadMember from './member.react.js';
import css from './members-modal.css';
type Props = {
+threadInfo: ThreadInfo,
+threadMembers: $ReadOnlyArray
,
};
function ThreadMembersList(props: Props): React.Node {
const { threadMembers, threadInfo } = props;
const [openMenu, setOpenMenu] = React.useState(null);
const hasMembers = threadMembers.length > 0;
const threadMembersWithENSNames = useENSNames(threadMembers);
const groupedByFirstLetterMembers = React.useMemo(
() =>
_groupBy(member => stringForUser(member)[0].toLowerCase())(
threadMembersWithENSNames,
),
[threadMembersWithENSNames],
);
const groupedMembersList = React.useMemo(
() =>
_toPairs(groupedByFirstLetterMembers)
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([letter, users]) => {
const userList = users
.sort((a, b) => stringForUser(a).localeCompare(stringForUser(b)))
.map((user: RelativeMemberInfo) => (
));
const letterHeader = (
{letter.toUpperCase()}
);
return (
{letterHeader}
{userList}
);
}),
- [groupedByFirstLetterMembers, openMenu, threadInfo],
+ [groupedByFirstLetterMembers, threadInfo],
);
let content = groupedMembersList;
if (!hasMembers) {
content = (
No matching users were found in the chat!
);
}
const membersListClasses = classNames(css.membersList, {
[css.noScroll]: !!openMenu,
});
return {content}
;
}
export default ThreadMembersList;
diff --git a/web/modals/threads/members/members-modal.css b/web/modals/threads/members/members-modal.css
index 50ee4d7de..d48cdf2a1 100644
--- a/web/modals/threads/members/members-modal.css
+++ b/web/modals/threads/members/members-modal.css
@@ -1,91 +1,89 @@
div.modalContentContainer {
height: 617px;
overflow: hidden;
display: flex;
flex-direction: column;
row-gap: 16px;
}
div.membersListTabs {
flex: 1;
overflow: hidden;
}
div.addNewMembers button {
width: 100%;
}
div.membersList {
overflow: auto;
padding: 8px 0;
color: var(--members-modal-member-text);
}
div.noScroll {
overflow: hidden;
}
div.memberContainer {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 8px 16px;
}
div.memberContainer:hover {
- color: var(--members-modal-member-text-hover);
-}
-
-div.memberContainerWithMenuOpen {
- color: var(--members-modal-member-text-hover);
+ cursor: pointer;
+ background-color: var(--drawer-open-community-bg);
+ border-radius: 8px;
}
div.memberInfo {
font-size: var(--l-font-18);
display: flex;
align-items: center;
gap: 10px;
}
div.memberAction {
position: relative;
}
h5.memberletterHeader {
margin: 16px;
color: var(--members-modal-member-text);
font-size: var(--s-font-14);
}
div.noUsers {
padding-top: 16px;
text-align: center;
}
div.addMembersContent {
display: flex;
flex-direction: column;
overflow: auto;
color: var(--fg);
height: 617px;
}
div.addMembersPendingList {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 6px;
padding: 8px;
}
div.addMembersListContainer {
overflow: auto;
flex: 1;
}
div.addMembersFooter {
display: flex;
justify-content: end;
column-gap: 16px;
margin-top: 16px;
}