import { useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import useKey from 'react-use/lib/useKey'; import styled from 'styled-components'; import { SessionButton } from '../../basic/SessionButton'; import { SessionSpinner } from '../../loading'; import { MemberListItem } from '../../MemberListItem'; import { useSet } from '../../../hooks/useSet'; import { VALIDATION } from '../../../session/constants'; import { createClosedGroup } from '../../../session/conversations/createClosedGroup'; import { resetLeftOverlayMode } from '../../../state/ducks/section'; import { getPrivateContactsPubkeys } from '../../../state/selectors/conversations'; import { getSearchResultsContactOnly, isSearching } from '../../../state/selectors/search'; import { SpacerLG, SpacerMD } from '../../basic/Text'; import { SessionInput } from '../../inputs'; import { SessionSearchInput } from '../../SessionSearchInput'; import { StyledLeftPaneOverlay } from './OverlayMessage'; const StyledMemberListNoContacts = styled.div` font-family: var(--font-mono), var(--font-default); background: var(--background-secondary-color); text-align: center; padding: 20px; `; const StyledGroupMemberListContainer = styled.div` padding: 2px 0px; width: 100%; max-height: 400px; overflow-y: auto; border-top: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color); &::-webkit-scrollbar-track { background-color: var(--background-secondary-color); } `; const StyledGroupMemberList = styled.div` button { background-color: var(--background-secondary-color); } `; const NoContacts = () => { return ( {window.i18n('noContactsForGroup')} ); }; /** * Makes some validity check and return true if the group was indead created */ async function createClosedGroupWithErrorHandling( groupName: string, groupMemberIds: Array, errorHandler: (error: string) => void ): Promise { // Validate groupName and groupMembers length if (groupName.length === 0) { errorHandler(window.i18n('invalidGroupNameTooShort')); return false; } if (groupName.length > VALIDATION.MAX_GROUP_NAME_LENGTH) { errorHandler(window.i18n('invalidGroupNameTooLong')); return false; } // >= because we add ourself as a member AFTER this. so a 10 group is already invalid as it will be 11 with ourself // the same is valid with groups count < 1 if (groupMemberIds.length < 1) { errorHandler(window.i18n('pickClosedGroupMember')); return false; } if (groupMemberIds.length >= VALIDATION.CLOSED_GROUP_SIZE_LIMIT) { errorHandler(window.i18n('closedGroupMaxSize')); return false; } await createClosedGroup(groupName, groupMemberIds, window.sessionFeatureFlags.useClosedGroupV3); return true; } export const OverlayClosedGroup = () => { const dispatch = useDispatch(); const privateContactsPubkeys = useSelector(getPrivateContactsPubkeys); const [groupName, setGroupName] = useState(''); const [groupNameError, setGroupNameError] = useState(undefined); const [loading, setLoading] = useState(false); const { uniqueValues: selectedMemberIds, addTo: addToSelected, removeFrom: removeFromSelected, } = useSet([]); const isSearch = useSelector(isSearching); const searchResultContactsOnly = useSelector(getSearchResultsContactOnly); function closeOverlay() { dispatch(resetLeftOverlayMode()); } async function onEnterPressed() { setGroupNameError(undefined); if (loading) { window?.log?.warn('Closed group creation already in progress'); return; } setLoading(true); const groupCreated = await createClosedGroupWithErrorHandling( groupName, selectedMemberIds, setGroupNameError ); if (groupCreated) { closeOverlay(); return; } setLoading(false); } useKey('Escape', closeOverlay); const noContactsForClosedGroup = privateContactsPubkeys.length === 0; const contactsToRender = isSearch ? searchResultContactsOnly : privateContactsPubkeys; const disableCreateButton = !selectedMemberIds.length && !groupName.length; return ( {noContactsForClosedGroup ? ( ) : ( {contactsToRender.map((memberPubkey: string) => ( m === memberPubkey)} key={memberPubkey} onSelect={addToSelected} onUnselect={removeFromSelected} disableBg={true} /> ))} )} ); };