import { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import useKey from 'react-use/lib/useKey';
import styled from 'styled-components';
import { isEmpty } from 'lodash';
import { SessionButton } from '../../basic/SessionButton';
import { SessionSpinner } from '../../loading';
import { useSet } from '../../../hooks/useSet';
import { VALIDATION } from '../../../session/constants';
import { createClosedGroup } from '../../../session/conversations/createClosedGroup';
import { ToastUtils } from '../../../session/utils';
import LIBSESSION_CONSTANTS from '../../../session/utils/libsession/libsession_constants';
import { clearSearch } from '../../../state/ducks/search';
import { resetLeftOverlayMode } from '../../../state/ducks/section';
import { getPrivateContactsPubkeys } from '../../../state/selectors/conversations';
import {
getSearchResultsContactOnly,
getSearchTerm,
useIsSearching,
} from '../../../state/selectors/search';
import { MemberListItem } from '../../MemberListItem';
import { SessionSearchInput } from '../../SessionSearchInput';
import { Flex } from '../../basic/Flex';
import { SpacerLG, SpacerMD } from '../../basic/Text';
import { SessionInput } from '../../inputs';
import { StyledLeftPaneOverlay } from './OverlayMessage';
const StyledMemberListNoContacts = styled.div`
text-align: center;
padding: 20px;
`;
const StyledNoResults = styled.div`
width: 100%;
padding: var(--margins-xl) var(--margins-sm);
text-align: center;
`;
const StyledGroupMemberListContainer = styled.div`
display: flex;
flex-direction: column;
flex: 1;
width: 100%;
overflow-x: hidden;
overflow-y: auto;
&::-webkit-scrollbar-track {
background-color: var(--background-secondary-color);
}
`;
const NoContacts = () => {
return (
{window.i18n('conversationsNone')}
);
};
/**
* Makes some validity check and return true if the group was indeed created
*/
async function createClosedGroupWithErrorHandling(
groupName: string,
groupMemberIds: Array,
onError: (error: string) => void
): Promise {
// Validate groupName and groupMembers length
if (groupName.length === 0) {
ToastUtils.pushToastError('invalidGroupName', window.i18n('groupNameEnterPlease'));
onError(window.i18n('groupNameEnterPlease'));
return false;
}
if (groupName.length > LIBSESSION_CONSTANTS.BASE_GROUP_MAX_NAME_LENGTH) {
onError(window.i18n('groupNameEnterShorter'));
return false;
}
// >= because we add ourself as a member AFTER this. so a 10 group is already invalid as it will be 11 when we are included
// the same is valid with groups count < 1
if (groupMemberIds.length < 1) {
onError(window.i18n('groupCreateErrorNoMembers'));
return false;
}
if (groupMemberIds.length >= VALIDATION.CLOSED_GROUP_SIZE_LIMIT) {
onError(window.i18n('groupAddMemberMaximum'));
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 = useIsSearching();
const searchTerm = useSelector(getSearchTerm);
const searchResultContactsOnly = useSelector(getSearchResultsContactOnly);
function closeOverlay() {
dispatch(clearSearch());
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 contactsToRender = isSearch ? searchResultContactsOnly : privateContactsPubkeys;
const noContactsForClosedGroup = isEmpty(searchTerm) && contactsToRender.length === 0;
const disableCreateButton = loading || (!selectedMemberIds.length && !groupName.length);
return (
{noContactsForClosedGroup ? (
) : searchTerm && !contactsToRender.length ? (
{window.i18n('searchMatchesNoneSpecific', { query: searchTerm })}
) : (
contactsToRender.map((pubkey: string) => (
))
)}
);
};