diff --git a/src/app/organisms/room/PeopleDrawer.jsx b/src/app/organisms/room/PeopleDrawer.jsx index 205047dc..dcddc76d 100644 --- a/src/app/organisms/room/PeopleDrawer.jsx +++ b/src/app/organisms/room/PeopleDrawer.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import PropTypes from 'prop-types'; import './PeopleDrawer.scss'; @@ -6,6 +6,7 @@ import initMatrix from '../../../client/initMatrix'; import { getPowerLabel, getUsernameOfRoomMember } from '../../../util/matrixUtil'; import colorMXID from '../../../util/colorMXID'; import { openInviteUser, openProfileViewer } from '../../../client/action/navigation'; +import AsyncSearch from '../../../util/AsyncSearch'; import Text from '../../atoms/text/Text'; import Header, { TitleWrapper } from '../../atoms/header/Header'; @@ -37,31 +38,88 @@ function sortByPowerLevel(m1, m2) { if (pl1 < pl2) return 1; return 0; } +function simplyfiMembers(members) { + const mx = initMatrix.matrixClient; + return members.map((member) => ({ + userId: member.userId, + name: getUsernameOfRoomMember(member), + username: member.userId.slice(1, member.userId.indexOf(':')), + avatarSrc: member.getAvatarUrl(mx.baseUrl, 24, 24, 'crop'), + peopleRole: getPowerLabel(member.powerLevel), + powerLevel: members.powerLevel, + })); +} +const asyncSearch = new AsyncSearch(); function PeopleDrawer({ roomId }) { const PER_PAGE_MEMBER = 50; - const room = initMatrix.matrixClient.getRoom(roomId); - const totalMemberList = room.getJoinedMembers().sort(AtoZ).sort(sortByPowerLevel); - const [memberList, updateMemberList] = useState([]); + const mx = initMatrix.matrixClient; + const room = mx.getRoom(roomId); let isRoomChanged = false; + const [itemCount, setItemCount] = useState(PER_PAGE_MEMBER); + const [membership, setMembership] = useState('join'); + const [memberList, setMemberList] = useState([]); + const [searchedMembers, setSearchedMembers] = useState(null); + + const getMembersWithMembership = useCallback( + (mship) => room.getMembersWithMembership(mship), + [roomId, membership], + ); + function loadMorePeople() { - updateMemberList(totalMemberList.slice(0, memberList.length + PER_PAGE_MEMBER)); + setItemCount(itemCount + PER_PAGE_MEMBER); + } + + function handleSearchData(data) { + // NOTICE: data is passed as object property + // because react sucks at handling state update with array. + setSearchedMembers({ data }); + setItemCount(PER_PAGE_MEMBER); + } + + function handleSearch(e) { + if (e.target.value === '') { + setSearchedMembers(null); + setItemCount(PER_PAGE_MEMBER); + } else asyncSearch.search(e.target.value); } useEffect(() => { - updateMemberList(totalMemberList.slice(0, PER_PAGE_MEMBER)); + asyncSearch.setup(memberList, { + keys: ['name', 'username', 'userId'], + limit: PER_PAGE_MEMBER, + }); + }, [memberList]); + + useEffect(() => { + setMemberList( + simplyfiMembers( + getMembersWithMembership(membership) + .sort(AtoZ).sort(sortByPowerLevel), + ), + ); room.loadMembersIfNeeded().then(() => { if (isRoomChanged) return; - const newTotalMemberList = room.getJoinedMembers().sort(AtoZ).sort(sortByPowerLevel); - updateMemberList(newTotalMemberList.slice(0, PER_PAGE_MEMBER)); + setMemberList( + simplyfiMembers( + getMembersWithMembership(membership) + .sort(AtoZ).sort(sortByPowerLevel), + ), + ); }); + asyncSearch.on(asyncSearch.RESULT_SENT, handleSearchData); return () => { isRoomChanged = true; + setMemberList([]); + setSearchedMembers(null); + setItemCount(PER_PAGE_MEMBER); + asyncSearch.removeListener(asyncSearch.RESULT_SENT, handleSearchData); }; }, [roomId]); + const mList = searchedMembers !== null ? searchedMembers.data : memberList.slice(0, itemCount); return (
@@ -78,20 +136,20 @@ function PeopleDrawer({ roomId }) {
{ - memberList.map((member) => ( + mList.map((member) => ( openProfileViewer(member.userId, roomId)} - avatarSrc={member.getAvatarUrl(initMatrix.matrixClient.baseUrl, 24, 24, 'crop')} - name={getUsernameOfRoomMember(member)} + avatarSrc={member.avatarSrc} + name={member.name} color={colorMXID(member.userId)} - peopleRole={getPowerLabel(member.powerLevel)} + peopleRole={member.peopleRole} /> )) }
{ - memberList.length !== totalMemberList.length && ( + mList.length !== 0 && mList.length > itemCount && ( ) } @@ -101,7 +159,7 @@ function PeopleDrawer({ roomId }) {
e.preventDefault()} className="people-search"> - +
diff --git a/src/app/organisms/room/PeopleDrawer.scss b/src/app/organisms/room/PeopleDrawer.scss index 56ac29e0..b3a2182f 100644 --- a/src/app/organisms/room/PeopleDrawer.scss +++ b/src/app/organisms/room/PeopleDrawer.scss @@ -36,10 +36,9 @@ } &__sticky { - display: none; - & .people-search { - min-height: 48px; + --search-input-height: 40px; + min-height: var(--search-input-height); margin: 0 var(--sp-normal); @@ -47,7 +46,7 @@ bottom: var(--sp-normal); & .input { - height: 48px; + height: var(--search-input-height); } } } @@ -55,7 +54,7 @@ .people-drawer__content { padding-top: var(--sp-extra-tight); - padding-bottom: calc( var(--sp-extra-tight) + var(--sp-normal)); + padding-bottom: calc(2 * var(--sp-normal)); } .people-drawer__load-more { padding: var(--sp-normal);