fix: improvements to closedGroupOverlay including virtualize member list

createClosedGroupWithErrorHandling errorHandler changed to onError, simplify search checks
pull/3083/head
William Grant 11 months ago
parent 4f44a7a5fa
commit 819d67aa97

@ -64,8 +64,8 @@ const ClosableOverlay = () => {
}; };
const ConversationRow = ( const ConversationRow = (
conversationIds: Array<string>, { index, key, style }: ListRowProps,
{ index, key, style }: ListRowProps conversationIds: Array<string>
): JSX.Element | null => { ): JSX.Element | null => {
// assume conversations that have been marked unapproved should be filtered out by selector. // assume conversations that have been marked unapproved should be filtered out by selector.
if (!conversationIds) { if (!conversationIds) {
@ -105,7 +105,7 @@ const ConversationList = () => {
height={height} height={height}
rowCount={conversationIds.length} rowCount={conversationIds.length}
rowHeight={64} rowHeight={64}
rowRenderer={props => ConversationRow(conversationIds, props)} rowRenderer={props => ConversationRow(props, conversationIds)}
width={width} width={width}
autoHeight={false} autoHeight={false}
conversationIds={conversationIds} conversationIds={conversationIds}

@ -5,7 +5,7 @@ import useKey from 'react-use/lib/useKey';
import styled from 'styled-components'; import styled from 'styled-components';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { MemberListItem } from '../../MemberListItem'; import { AutoSizer, List, ListRowProps } from 'react-virtualized';
import { SessionButton } from '../../basic/SessionButton'; import { SessionButton } from '../../basic/SessionButton';
import { SessionSpinner } from '../../loading'; import { SessionSpinner } from '../../loading';
@ -20,6 +20,7 @@ import {
getSearchTerm, getSearchTerm,
isSearching, isSearching,
} from '../../../state/selectors/search'; } from '../../../state/selectors/search';
import { MemberListItem } from '../../MemberListItem';
import { SessionSearchInput } from '../../SessionSearchInput'; import { SessionSearchInput } from '../../SessionSearchInput';
import { Flex } from '../../basic/Flex'; import { Flex } from '../../basic/Flex';
import { SpacerLG, SpacerMD } from '../../basic/Text'; import { SpacerLG, SpacerMD } from '../../basic/Text';
@ -40,6 +41,8 @@ const StyledNoResults = styled.div`
const StyledGroupMemberListContainer = styled.div` const StyledGroupMemberListContainer = styled.div`
padding: 0; padding: 0;
width: 100%; width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
border-top: 1px solid var(--border-color); border-top: 1px solid var(--border-color);
border-bottom: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color);
@ -55,21 +58,49 @@ const NoContacts = () => {
); );
}; };
const MemberRow = (
{ index, key }: ListRowProps,
contactsToRender: Array<string>,
selectedMemberIds: Array<string>,
addToSelected: (memberId: string) => void,
removeFromSelected: (memberId: string) => void
): JSX.Element | null => {
// assume conversations that have been marked unapproved should be filtered out by selector.
if (!contactsToRender) {
throw new Error('MemberRow: Tried to render without contacts');
}
const memberPubkey = contactsToRender[index];
if (!memberPubkey) {
throw new Error('MemberRow: contact selector returned element containing falsy value.');
}
return (
<MemberListItem
key={key}
pubkey={memberPubkey}
isSelected={selectedMemberIds.some(m => m === memberPubkey)}
onSelect={addToSelected}
onUnselect={removeFromSelected}
/>
);
};
/** /**
* Makes some validity check and return true if the group was indead created * Makes some validity check and return true if the group was indead created
*/ */
async function createClosedGroupWithErrorHandling( async function createClosedGroupWithErrorHandling(
groupName: string, groupName: string,
groupMemberIds: Array<string>, groupMemberIds: Array<string>,
errorHandler: (error: string) => void onError: (error: string) => void
): Promise<boolean> { ): Promise<boolean> {
// Validate groupName and groupMembers length // Validate groupName and groupMembers length
if (groupName.length === 0) { if (groupName.length === 0) {
errorHandler(window.i18n('invalidGroupNameTooShort')); onError(window.i18n('invalidGroupNameTooShort'));
return false; return false;
} }
if (groupName.length > VALIDATION.MAX_GROUP_NAME_LENGTH) { if (groupName.length > VALIDATION.MAX_GROUP_NAME_LENGTH) {
errorHandler(window.i18n('invalidGroupNameTooLong')); onError(window.i18n('invalidGroupNameTooLong'));
return false; return false;
} }
@ -77,11 +108,11 @@ async function createClosedGroupWithErrorHandling(
// the same is valid with groups count < 1 // the same is valid with groups count < 1
if (groupMemberIds.length < 1) { if (groupMemberIds.length < 1) {
errorHandler(window.i18n('pickClosedGroupMember')); onError(window.i18n('pickClosedGroupMember'));
return false; return false;
} }
if (groupMemberIds.length >= VALIDATION.CLOSED_GROUP_SIZE_LIMIT) { if (groupMemberIds.length >= VALIDATION.CLOSED_GROUP_SIZE_LIMIT) {
errorHandler(window.i18n('closedGroupMaxSize')); onError(window.i18n('closedGroupMaxSize'));
return false; return false;
} }
@ -173,23 +204,32 @@ export const OverlayClosedGroup = () => {
</Flex> </Flex>
<SessionSearchInput /> <SessionSearchInput />
<StyledGroupMemberListContainer> <StyledGroupMemberListContainer key={`member-list-0`}>
{noContactsForClosedGroup ? ( {noContactsForClosedGroup ? (
<NoContacts /> <NoContacts />
) : !isEmpty(searchTerm) && contactsToRender.length === 0 ? ( ) : searchTerm && !contactsToRender.length ? (
<StyledNoResults>{window.i18n('noSearchResults', [searchTerm])}</StyledNoResults> <StyledNoResults>{window.i18n('noSearchResults', [searchTerm])}</StyledNoResults>
) : ( ) : (
<div> <AutoSizer>
{contactsToRender.map((memberPubkey: string) => ( {({ height, width }) => (
<MemberListItem <List
pubkey={memberPubkey} height={height}
isSelected={selectedMemberIds.some(m => m === memberPubkey)} width={width}
key={memberPubkey} autoHeight={true}
onSelect={addToSelected} rowCount={contactsToRender.length}
onUnselect={removeFromSelected} rowHeight={50}
rowRenderer={props =>
MemberRow(
props,
contactsToRender,
selectedMemberIds,
addToSelected,
removeFromSelected
)
}
/> />
))} )}
</div> </AutoSizer>
)} )}
</StyledGroupMemberListContainer> </StyledGroupMemberListContainer>

Loading…
Cancel
Save