Add search in People drawer

Signed-off-by: Ajay Bura <ajbura@gmail.com>
This commit is contained in:
Ajay Bura 2021-10-21 17:50:49 +05:30 committed by Krishan
parent 5f6667debf
commit 5018df11f1
2 changed files with 76 additions and 19 deletions

View file

@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import './PeopleDrawer.scss'; import './PeopleDrawer.scss';
@ -6,6 +6,7 @@ import initMatrix from '../../../client/initMatrix';
import { getPowerLabel, getUsernameOfRoomMember } from '../../../util/matrixUtil'; import { getPowerLabel, getUsernameOfRoomMember } from '../../../util/matrixUtil';
import colorMXID from '../../../util/colorMXID'; import colorMXID from '../../../util/colorMXID';
import { openInviteUser, openProfileViewer } from '../../../client/action/navigation'; import { openInviteUser, openProfileViewer } from '../../../client/action/navigation';
import AsyncSearch from '../../../util/AsyncSearch';
import Text from '../../atoms/text/Text'; import Text from '../../atoms/text/Text';
import Header, { TitleWrapper } from '../../atoms/header/Header'; import Header, { TitleWrapper } from '../../atoms/header/Header';
@ -37,31 +38,88 @@ function sortByPowerLevel(m1, m2) {
if (pl1 < pl2) return 1; if (pl1 < pl2) return 1;
return 0; 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 }) { function PeopleDrawer({ roomId }) {
const PER_PAGE_MEMBER = 50; const PER_PAGE_MEMBER = 50;
const room = initMatrix.matrixClient.getRoom(roomId); const mx = initMatrix.matrixClient;
const totalMemberList = room.getJoinedMembers().sort(AtoZ).sort(sortByPowerLevel); const room = mx.getRoom(roomId);
const [memberList, updateMemberList] = useState([]);
let isRoomChanged = false; 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() { 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(() => { 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(() => { room.loadMembersIfNeeded().then(() => {
if (isRoomChanged) return; if (isRoomChanged) return;
const newTotalMemberList = room.getJoinedMembers().sort(AtoZ).sort(sortByPowerLevel); setMemberList(
updateMemberList(newTotalMemberList.slice(0, PER_PAGE_MEMBER)); simplyfiMembers(
getMembersWithMembership(membership)
.sort(AtoZ).sort(sortByPowerLevel),
),
);
}); });
asyncSearch.on(asyncSearch.RESULT_SENT, handleSearchData);
return () => { return () => {
isRoomChanged = true; isRoomChanged = true;
setMemberList([]);
setSearchedMembers(null);
setItemCount(PER_PAGE_MEMBER);
asyncSearch.removeListener(asyncSearch.RESULT_SENT, handleSearchData);
}; };
}, [roomId]); }, [roomId]);
const mList = searchedMembers !== null ? searchedMembers.data : memberList.slice(0, itemCount);
return ( return (
<div className="people-drawer"> <div className="people-drawer">
<Header> <Header>
@ -78,20 +136,20 @@ function PeopleDrawer({ roomId }) {
<ScrollView autoHide> <ScrollView autoHide>
<div className="people-drawer__content"> <div className="people-drawer__content">
{ {
memberList.map((member) => ( mList.map((member) => (
<PeopleSelector <PeopleSelector
key={member.userId} key={member.userId}
onClick={() => openProfileViewer(member.userId, roomId)} onClick={() => openProfileViewer(member.userId, roomId)}
avatarSrc={member.getAvatarUrl(initMatrix.matrixClient.baseUrl, 24, 24, 'crop')} avatarSrc={member.avatarSrc}
name={getUsernameOfRoomMember(member)} name={member.name}
color={colorMXID(member.userId)} color={colorMXID(member.userId)}
peopleRole={getPowerLabel(member.powerLevel)} peopleRole={member.peopleRole}
/> />
)) ))
} }
<div className="people-drawer__load-more"> <div className="people-drawer__load-more">
{ {
memberList.length !== totalMemberList.length && ( mList.length !== 0 && mList.length > itemCount && (
<Button onClick={loadMorePeople}>View more</Button> <Button onClick={loadMorePeople}>View more</Button>
) )
} }
@ -101,7 +159,7 @@ function PeopleDrawer({ roomId }) {
</div> </div>
<div className="people-drawer__sticky"> <div className="people-drawer__sticky">
<form onSubmit={(e) => e.preventDefault()} className="people-search"> <form onSubmit={(e) => e.preventDefault()} className="people-search">
<Input type="text" placeholder="Search" required /> <Input type="text" onChange={handleSearch} placeholder="Search" required />
</form> </form>
</div> </div>
</div> </div>

View file

@ -36,10 +36,9 @@
} }
&__sticky { &__sticky {
display: none;
& .people-search { & .people-search {
min-height: 48px; --search-input-height: 40px;
min-height: var(--search-input-height);
margin: 0 var(--sp-normal); margin: 0 var(--sp-normal);
@ -47,7 +46,7 @@
bottom: var(--sp-normal); bottom: var(--sp-normal);
& .input { & .input {
height: 48px; height: var(--search-input-height);
} }
} }
} }
@ -55,7 +54,7 @@
.people-drawer__content { .people-drawer__content {
padding-top: var(--sp-extra-tight); 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 { .people-drawer__load-more {
padding: var(--sp-normal); padding: var(--sp-normal);